Wednesday 9 April 2008

BypassProxyOnLocal - a bug in .Net ?

If you have a local proxy server on your computer (127.0.0.1) that you wish to use when doing FTP communications, all you need do is set BypassProxyOnLocal = false right?

There may be many important reasons for using a local proxy, such as caching and security etc.

Here's an example:

WebProxy proxy = new WebProxy("127.0.0.1", 3128);

proxy.BypassProxyOnLocal = true;
bool a = proxy.IsBypassed(new Uri("ftp://127.0.0.1:3128"));
bool b = proxy.IsBypassed(new Uri("ftp://127.0.0.1:21"));
// a=true, b=true (ok)


proxy.BypassProxyOnLocal = false;
bool c = proxy.IsBypassed(new Uri("ftp://127.0.0.1:3128"));
bool d = proxy.IsBypassed(new Uri("ftp://127.0.0.1:21"));
// c=true, d=true (???)


Why is the proxy being bypassed when I told it not to?
The local proxy is always bypassed when when the proxy is on a loopback address. Why?

Setting BypassProxyOnLocal to false should NOT bypass the proxy for local addresses. So let's see what MSDN Library has to say about IsBypassed method:

If BypassProxyOnLocal is true, requests to local Internet resources do not use
the proxy server. Local requests are identified by the lack of a period (.) in
the URI, as in http://webserver/, or access the local server, including
http://localhost, http://loopback, or http://127.0.0.1. When BypassProxyOnLocal
is false, all Internet requests are made through the proxy server.

Here is the WebProxy.IsBypassed source code:


public bool IsBypassed(Uri host)
{
GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::IsBypassed() destination:" + ValidationHelper.ToString(host));

if (host == null)
{
throw new ArgumentNullException("host");
}

AutoWebProxyState autoWebProxyState;
bool result = IsBypassedAuto(host, out autoWebProxyState);
if (autoWebProxyState==AutoWebProxyState.ExecutionSuccess) {
return result;
}

return IsBypassedManual(host);
}

private bool IsBypassedManual(Uri host) {
if (host.IsLoopback) {
return true; // bypass localhost from using a proxy.
}
return (_ProxyAddress==null && _ProxyHostAddresses==null) (_BypassOnLocal && IsLocal(host)) IsMatchInBypassList(host) IsLocalInProxyHash(host);
}