Bug 2933 - Cant send https via http proxy
Summary: Cant send https via http proxy
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime ()
Version: 5.0
Hardware: Other Other
: Normal normal
Target Milestone: Untriaged
Assignee: Sebastien Pouliot
URL:
Depends on:
Blocks:
 
Reported: 2012-01-17 07:48 UTC by Jamie Briant
Modified: 2012-02-05 12:46 UTC (History)
5 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Jamie Briant 2012-01-17 07:48:09 UTC
I'm trying to test my app via charles proxy (charlesproxy.com) a well known http proxy which supports https. Safari works fine over https-over-http thru charles.

As I understand it (and i could be wrong) when a client requires https over an http-proxy, it must first send the CONNECT in clear text to allow the proxy to initiate the session, and after the first 200 OK it becomes encrypted.

Monotouch is not doing this. It is immediately sending the TLS handshake (0x16 0x03 0x01 ...) down the tcp stream.
Comment 2 Jamie Briant 2012-01-17 08:23:19 UTC
This will also affect our customers who have to use a proxy.
Comment 3 Jamie Briant 2012-01-18 04:07:07 UTC
I set up a local Squid Proxy to see if it's just charles, or if it really is *any* proxy, and indeed, the calls fail and squid logs an error: error:unsupported-request-method. Squid successfully proxies https for safari.
Comment 4 Sebastien Pouliot 2012-02-01 16:41:01 UTC
It looks like the default (device) proxy is not set when creating a WebClient - but once we assign one manually, or ask for WebRequest.DefaultWebProxy, then things go right. 

			WebClient wc = new WebClient ();

			try {
				Console.WriteLine ("*** direct ***");
				if (wc.Proxy == null)
					Console.WriteLine ("no default proxy");
				else
					Console.WriteLine (wc.DownloadString ("https://www.google.com"));
				
				Console.WriteLine ("*** manual proxy ***");
				wc.Proxy = new WebProxy ("10.0.1.20", 8888);
				Console.WriteLine (wc.DownloadString ("https://www.google.com"));
				
				Console.WriteLine ("*** default web proxy ***");
				wc.Proxy = WebRequest.DefaultWebProxy;
				Console.WriteLine (wc.DownloadString ("https://www.google.com"));
			}
			catch (Exception e) {
				Console.WriteLine (e);
			}

Could you confirm if setting WebRequest.DefaultWebProxy works for you ?

c.c. Jeff to know if (and why) this was the intended behavior.
Comment 5 Sebastien Pouliot 2012-02-01 21:32:25 UTC
This seems to be a Mono-specific behaviour (or bug ? Gonzalo ?) not to set the WebClient.Proxy to the default value, i.e. WebRequest.DefaultWebProxy

A quick test on Windows shows that the Proxy property is not null when a proxy is defined (at least that's the way it behave with Windows 7). E.g.

			WebClient wc = new WebClient ();
			Assert.IsNotNull (wc.Proxy);

Bug or not (it only change where the fix needs to be) I think we should use the iOS* default proxy (when defined) and not require an extra line of code (not long but confusing) to our users.

* that's likely a fix for MOBILE - but I'm not sure how Mono for Android handles this.
Comment 6 Jamie Briant 2012-02-01 23:47:53 UTC
I haven't had time to check the fix proposed above, but I wanted to clarify something that seems to have been missed:

The proxy is there and working for http calls.

For https calls, the app *is* sending the traffic to the proxy, but it is not following the rules for proxying https traffic. It just starts tls negotiation straight away.
Comment 7 Sebastien Pouliot 2012-02-02 08:46:18 UTC
Not missed ;-) and AFAIK that's normal [1] but to be 100% sure could you please describe your (iOS) device proxy settings to ensure I'm testing the same things as you are ?

Here's how I tested this:
- My iPad used a proxy to my Mac (10.0.1.20) on port 8888. 
- Charles' proxy was running the Mac.
- My app requests https://www.google.com
- It works when I set the proxy object (in my app), it fails when I do not.


[1] the proxy configuration (in iOS) exists even if unassigned to WebClient.Proxy. This means that the application will use the proxy, so using http:// will work. 

OTOH special care must be given to do https:// via http:// (i.e. the link you added in comment #1) and this is done by Mono[Touch] code *only* if a IWebProxy is assigned to WebClient.Proxy. That explains the failure you're having while using https://
Comment 8 Gonzalo Paniagua Javier 2012-02-02 09:32:33 UTC
Re comment #5: the proxy property will not be null if there is a proxy set (environment variable http_proxy)
Comment 9 Sebastien Pouliot 2012-02-02 09:48:08 UTC
Gonzalo, mono (2.10.8.1 at least) disagree with comment #8


$ cat wcp.cs 
using System;
using System.Net;

class Program {
	static string ShowProxy (IWebProxy proxy)
	{
		if (proxy == null)
			return "(none)";
		WebProxy wb = (proxy as WebProxy);
		if (wb == null)
			return "(not a WebProxy)";
		return wb.Address == null ? "(no address)" : wb.Address.ToString ();
	}

	static void Main ()
	{
		WebClient wc = new WebClient ();
		Console.WriteLine ("WebClient.Proxy: '{0}'", ShowProxy (wc.Proxy));
		Console.WriteLine ("WebRequest.DefaultWebProxy: '{0}'", ShowProxy (WebRequest.DefaultWebProxy));
	}
}
$ gmcs -debug wcp.cs
$ mono --debug wcp.exe 
WebClient.Proxy: '(none)'
WebRequest.DefaultWebProxy: '(no address)'
$ HTTP_PROXY=10.0.1.20:8888 mono wcp.exe 
WebClient.Proxy: '(none)'
WebRequest.DefaultWebProxy: 'http://10.0.1.20:8888/'
Comment 10 Gonzalo Paniagua Javier 2012-02-02 09:55:52 UTC
Well, then that is the bug, no?
Comment 11 Sebastien Pouliot 2012-02-02 10:09:03 UTC
That was exactly my question ;-)

> This seems to be a Mono-specific behaviour (or bug ? Gonzalo ?)

Thanks for confirming it. I'll update WebClient (master, mono-2-10 and mobile-master) to use the proxy.

Jamie, until the fix makes its way back to a released version of MonoTouch the workaround is to assign the default proxy to any WebClient you use in your application. e.g.

WebClient wc = ...
wc.Proxy = WebRequest.DefaultWebProxy;
Comment 13 Sebastien Pouliot 2012-02-05 12:46:42 UTC
Mono master was already fixed (added unit test).
Patches backported to mono-2-10 branch.
Patches backported to mobile-master branch.
MonoTouch master bumped.

The workaround is to set the proxy manually when creating WebClient instances. 

WebClient wc = ...
wc.Proxy = WebRequest.DefaultWebProxy;

This will continue to work on a fixed MonoTouch is released.