public static SocksHttpWebResponse CreateErrorResponse(HttpStatusCode statusCode)
        {
            var response = new SocksHttpWebResponse
            {
                StatusCode = statusCode
            };

            return response;
        }
예제 #2
0
        private SocksHttpWebResponse InternalGetResponse()
        {
            Uri requestUri = RequestUri;

            int       redirects            = 0;
            const int maxAutoredirectCount = 10;

            while (redirects++ < maxAutoredirectCount)
            {
                // Loop while redirecting

                var proxyUri  = Proxy.GetProxy(requestUri);
                var ipAddress = GetProxyIpAddress(proxyUri);
                var response  = new List <byte>();

                using (var client = new TcpClient(ipAddress.ToString(), proxyUri.Port))
                {
                    int timeout = Timeout;
                    if (timeout == 0)
                    {
                        timeout = 30 * 1000;
                    }
                    client.ReceiveTimeout = timeout;
                    client.SendTimeout    = timeout;
                    var networkStream = client.GetStream();
                    // auth
                    var buf = new byte[300];
                    buf[0] = 0x05; // Version
                    buf[1] = 0x01; // NMETHODS
                    buf[2] = 0x00; // No auth-method
                    networkStream.Write(buf, 0, 3);

                    networkStream.Read(buf, 0, 2);
                    if (buf[0] != 0x05)
                    {
                        throw new IOException("Invalid Socks Version");
                    }
                    if (buf[1] == 0xff)
                    {
                        throw new IOException("Socks Server does not support no-auth");
                    }
                    if (buf[1] != 0x00)
                    {
                        throw new Exception("Socks Server did choose bogus auth");
                    }

                    // connect
                    var destIP = Dns.GetHostEntry(requestUri.DnsSafeHost).AddressList[0];
                    var index  = 0;
                    buf[index++] = 0x05; // version 5 .
                    buf[index++] = 0x01; // command = connect.
                    buf[index++] = 0x00; // Reserve = must be 0x00

                    buf[index++] = 0x01; // Address is full-qualified domain name.
                    var rawBytes = destIP.GetAddressBytes();
                    rawBytes.CopyTo(buf, index);
                    index += (ushort)rawBytes.Length;

                    var portBytes = BitConverter.GetBytes(Uri.UriSchemeHttps == requestUri.Scheme ? 443 : 80);
                    for (var i = portBytes.Length - 3; i >= 0; i--)
                    {
                        buf[index++] = portBytes[i];
                    }


                    networkStream.Write(buf, 0, index);

                    networkStream.Read(buf, 0, 4);
                    if (buf[0] != 0x05)
                    {
                        throw new IOException("Invalid Socks Version");
                    }
                    if (buf[1] != 0x00)
                    {
                        throw new IOException($"Socks Error {buf[1]:X}");
                    }

                    var rdest = string.Empty;
                    switch (buf[3])
                    {
                    case 0x01:     // IPv4
                        networkStream.Read(buf, 0, 4);
                        var v4 = BitConverter.ToUInt32(buf, 0);
                        rdest = new IPAddress(v4).ToString();
                        break;

                    case 0x03:     // Domain name
                        networkStream.Read(buf, 0, 1);
                        if (buf[0] == 0xff)
                        {
                            throw new IOException("Invalid Domain Name");
                        }
                        networkStream.Read(buf, 1, buf[0]);
                        rdest = Encoding.ASCII.GetString(buf, 1, buf[0]);
                        break;

                    case 0x04:     // IPv6
                        var octets = new byte[16];
                        networkStream.Read(octets, 0, 16);
                        rdest = new IPAddress(octets).ToString();
                        break;

                    default:
                        throw new IOException("Invalid Address type");
                    }
                    networkStream.Read(buf, 0, 2);
                    var rport = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(buf, 0));

                    Stream readStream = null;
                    if (Uri.UriSchemeHttps == requestUri.Scheme)
                    {
                        var ssl = new SslStream(networkStream);
                        ssl.AuthenticateAsClient(requestUri.DnsSafeHost);
                        readStream = ssl;
                    }
                    else
                    {
                        readStream = networkStream;
                    }

                    string requestString = BuildHttpRequestMessage(requestUri);

                    var request = Encoding.ASCII.GetBytes(requestString);
                    readStream.Write(request, 0, request.Length);
                    readStream.Flush();

                    var buffer = new byte[client.ReceiveBufferSize];

                    var readlen = 0;
                    do
                    {
                        readlen = readStream.Read(buffer, 0, buffer.Length);
                        response.AddRange(buffer.Take(readlen));
                    } while (readlen != 0);

                    readStream.Close();
                }

                var webResponse = new SocksHttpWebResponse(requestUri, response.ToArray());

                if (webResponse.StatusCode == HttpStatusCode.Moved || webResponse.StatusCode == HttpStatusCode.MovedPermanently)
                {
                    string redirectUrl = webResponse.Headers["Location"];
                    if (string.IsNullOrEmpty(redirectUrl))
                    {
                        throw new WebException("Missing location for redirect");
                    }

                    requestUri = new Uri(requestUri, redirectUrl);
                    if (AllowAutoRedirect)
                    {
                        continue;
                    }
                    return(webResponse);
                }

                if ((int)webResponse.StatusCode < 200 || (int)webResponse.StatusCode > 299)
                {
                    throw new WebException(webResponse.StatusDescription, null, WebExceptionStatus.UnknownError, webResponse);
                }

                return(webResponse);
            }

            throw new WebException("Too many redirects", null, WebExceptionStatus.ProtocolError, SocksHttpWebResponse.CreateErrorResponse(HttpStatusCode.BadRequest));
        }
        private SocksHttpWebResponse InternalGetResponse()
        {
            Uri requestUri = RequestUri;

            int redirects = 0;
            while (redirects++ < 10)
            {
                // Loop while redirecting

                var proxyUri = Proxy.GetProxy(requestUri);
                var ipAddress = GetProxyIpAddress(proxyUri);
                var response = new List<byte>();

                using (var client = new TcpClient(ipAddress.ToString(), proxyUri.Port))
                {
                    int timeout = Timeout;
                    if (timeout == 0)
                        timeout = 30 * 1000;
                    client.ReceiveTimeout = timeout;
                    client.SendTimeout = timeout;
                    var networkStream = client.GetStream();
                    // auth
                    var buf = new byte[300];
                    buf[0] = 0x05; // Version
                    buf[1] = 0x01; // NMETHODS
                    buf[2] = 0x00; // No auth-method
                    networkStream.Write(buf, 0, 3);

                    networkStream.Read(buf, 0, 2);
                    if (buf[0] != 0x05)
                    {
                        throw new IOException("Invalid Socks Version");
                    }
                    if (buf[1] == 0xff)
                    {
                        throw new IOException("Socks Server does not support no-auth");
                    }
                    if (buf[1] != 0x00)
                    {
                        throw new Exception("Socks Server did choose bogus auth");
                    }

                    // connect
                    var destIP = Dns.GetHostEntry(requestUri.DnsSafeHost).AddressList[0];
                    var index = 0;
                    buf[index++] = 0x05; // version 5 .
                    buf[index++] = 0x01; // command = connect.
                    buf[index++] = 0x00; // Reserve = must be 0x00

                    buf[index++] = 0x01; // Address is full-qualified domain name.
                    var rawBytes = destIP.GetAddressBytes();
                    rawBytes.CopyTo(buf, index);
                    index += (ushort)rawBytes.Length;

                    var portBytes = BitConverter.GetBytes(Uri.UriSchemeHttps == requestUri.Scheme ? 443 : 80);
                    for (var i = portBytes.Length - 3; i >= 0; i--)
                        buf[index++] = portBytes[i];


                    networkStream.Write(buf, 0, index);

                    networkStream.Read(buf, 0, 4);
                    if (buf[0] != 0x05)
                    {
                        throw new IOException("Invalid Socks Version");
                    }
                    if (buf[1] != 0x00)
                    {
                        throw new IOException($"Socks Error {buf[1]:X}");
                    }

                    var rdest = string.Empty;
                    switch (buf[3])
                    {
                        case 0x01: // IPv4
                            networkStream.Read(buf, 0, 4);
                            var v4 = BitConverter.ToUInt32(buf, 0);
                            rdest = new IPAddress(v4).ToString();
                            break;
                        case 0x03: // Domain name
                            networkStream.Read(buf, 0, 1);
                            if (buf[0] == 0xff)
                            {
                                throw new IOException("Invalid Domain Name");
                            }
                            networkStream.Read(buf, 1, buf[0]);
                            rdest = Encoding.ASCII.GetString(buf, 1, buf[0]);
                            break;
                        case 0x04: // IPv6
                            var octets = new byte[16];
                            networkStream.Read(octets, 0, 16);
                            rdest = new IPAddress(octets).ToString();
                            break;
                        default:
                            throw new IOException("Invalid Address type");
                    }
                    networkStream.Read(buf, 0, 2);
                    var rport = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(buf, 0));

                    Stream readStream = null;
                    if (Uri.UriSchemeHttps == requestUri.Scheme)
                    {
                        var ssl = new SslStream(networkStream);
                        ssl.AuthenticateAsClient(requestUri.DnsSafeHost);
                        readStream = ssl;
                    }
                    else
                    {
                        readStream = networkStream;
                    }

                    string requestString = BuildHttpRequestMessage(requestUri);

                    var request = Encoding.ASCII.GetBytes(requestString);
                    readStream.Write(request, 0, request.Length);
                    readStream.Flush();

                    var buffer = new byte[client.ReceiveBufferSize];

                    var readlen = 0;
                    do
                    {
                        readlen = readStream.Read(buffer, 0, buffer.Length);
                        response.AddRange(buffer.Take(readlen));
                    } while (readlen != 0);

                    readStream.Close();
                }

                var webResponse = new SocksHttpWebResponse(requestUri, response.ToArray());

                if (webResponse.StatusCode == HttpStatusCode.Moved || webResponse.StatusCode == HttpStatusCode.MovedPermanently)
                {
                    string redirectUrl = webResponse.Headers["Location"];
                    if (string.IsNullOrEmpty(redirectUrl))
                        throw new WebException("Missing location for redirect");

                    requestUri = new Uri(requestUri, redirectUrl);
                    continue;
                }

                if ((int)webResponse.StatusCode < 200 || (int)webResponse.StatusCode > 299)
                    throw new WebException(webResponse.StatusDescription, null, WebExceptionStatus.UnknownError, webResponse);

                return webResponse;
            }

            throw new WebException("Too many redirects", null, WebExceptionStatus.ProtocolError, SocksHttpWebResponse.CreateErrorResponse(HttpStatusCode.BadRequest));
        }
        public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
        {
            if (Proxy == null)
            {
                throw new InvalidOperationException("Proxy property cannot be null.");
            }
            if (string.IsNullOrEmpty(Method))
            {
                throw new InvalidOperationException("Method has not been set.");
            }

            var task = Task.Run<WebResponse>(() =>
            {
                if (RequestSubmitted)
                {
                    return _response;
                }
                _response = InternalGetResponse();
                RequestSubmitted = true;
                return _response;
            });

            return task.AsApm(callback, state);
        }
        public override WebResponse GetResponse()
        {
            if (Proxy == null)
            {
                throw new InvalidOperationException("Proxy property cannot be null.");
            }
            if (string.IsNullOrEmpty(Method))
            {
                throw new InvalidOperationException("Method has not been set.");
            }

            if (RequestSubmitted)
            {
                return _response;
            }
            _response = InternalGetResponse();
            RequestSubmitted = true;
            return _response;
        }
예제 #6
0
        private SocksHttpWebResponse InternalGetResponse()
        {
            Uri requestUri = RequestUri;

            int       redirects            = 0;
            short     http1SubVers         = 1; // Use HTTP 1.1 by default, fallback to 1.0 if bad request : Unsupported method error
            const int maxAutoredirectCount = 10;

            while (redirects++ < maxAutoredirectCount)
            {
                // Loop while redirecting

                var proxyUri  = Proxy.GetProxy(requestUri);
                var ipAddress = GetProxyIpAddress(proxyUri);
                var response  = new List <byte>();

                using (var client = new TcpClient(ipAddress.ToString(), proxyUri.Port))
                {
                    int timeout = Timeout;
                    if (timeout == 0)
                    {
                        timeout = 30 * 1000;
                    }
                    client.ReceiveTimeout = timeout;
                    client.SendTimeout    = timeout;
                    var networkStream = client.GetStream();
                    // auth
                    var buf = new byte[300];
                    buf[0] = 0x05; // Version
                    buf[1] = 0x01; // NMETHODS
                    buf[2] = 0x00; // No auth-method
                    networkStream.Write(buf, 0, 3);

                    networkStream.Read(buf, 0, 2);
                    if (buf[0] != 0x05)
                    {
                        throw new IOException("Invalid Socks Version");
                    }
                    if (buf[1] == 0xff)
                    {
                        throw new IOException("Socks Server does not support no-auth");
                    }
                    if (buf[1] != 0x00)
                    {
                        throw new Exception("Socks Server did choose bogus auth");
                    }

                    // connect
                    var index = 0;
                    buf[index++] = 0x05; // version 5 .
                    buf[index++] = 0x01; // command = connect.
                    buf[index++] = 0x00; // Reserve = must be 0x00

                    if (DnsResolvedBySocksProxy)
                    {
                        buf[index++] = 0x03; // Address is full-qualified domain name.
                        buf[index++] = (byte)requestUri.DnsSafeHost.Length;
                        byte[] rawBytes = Encoding.ASCII.GetBytes(requestUri.DnsSafeHost);
                        rawBytes.CopyTo(buf, index);
                        index += (ushort)rawBytes.Length;
                    }
                    else
                    {
                        IPAddress destIP = Dns.GetHostEntry(requestUri.DnsSafeHost).AddressList[0];
                        buf[index++] = 0x01; // IP v4 Address
                        byte[] rawBytes = destIP.GetAddressBytes();
                        rawBytes.CopyTo(buf, index);
                        index += (ushort)rawBytes.Length;
                    }

                    var portBytes = BitConverter.GetBytes(Uri.UriSchemeHttps == requestUri.Scheme ? 443 : 80);
                    for (var i = portBytes.Length - 3; i >= 0; i--)
                    {
                        buf[index++] = portBytes[i];
                    }


                    networkStream.Write(buf, 0, index);

                    networkStream.Read(buf, 0, 4);
                    if (buf[0] != 0x05)
                    {
                        throw new IOException("Invalid Socks Version");
                    }
                    if (buf[1] != 0x00)
                    {
                        string err;
                        switch (buf[1])
                        {
                        case 0x01: err = "General SOCKS server failure"; break;

                        case 0x02: err = "Connection not allowed by ruleset"; break;

                        case 0x03: err = "Network unreachable"; break;

                        case 0x04: err = "Host unreachable"; break;

                        case 0x05: err = "Connection refused"; break;

                        case 0x06: err = "TTL expired"; break;

                        case 0x07: err = "Command not supported"; break;

                        case 0x08: err = "Address type not supported"; break;

                        default: err = $"Socks Error {buf[1]:X}"; break;
                        }
                        throw new IOException(err);
                    }
                    var rdest = string.Empty; // TOFIX : usefull ????
                    switch (buf[3])
                    {
                    case 0x01:     // IPv4
                        networkStream.Read(buf, 0, 4);
                        var v4 = BitConverter.ToUInt32(buf, 0);
                        rdest = new IPAddress(v4).ToString();
                        break;

                    case 0x03:     // Domain name
                        networkStream.Read(buf, 0, 1);
                        if (buf[0] == 0xff)
                        {
                            throw new IOException("Invalid Domain Name");
                        }
                        networkStream.Read(buf, 1, buf[0]);
                        rdest = Encoding.ASCII.GetString(buf, 1, buf[0]);
                        break;

                    case 0x04:     // IPv6
                        var octets = new byte[16];
                        networkStream.Read(octets, 0, 16);
                        rdest = new IPAddress(octets).ToString();
                        break;

                    default:
                        throw new IOException("Invalid Address type");
                    }
                    networkStream.Read(buf, 0, 2);
                    var rport = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(buf, 0));

                    Stream readStream = null;
                    if (Uri.UriSchemeHttps == requestUri.Scheme)
                    {
                        SslStream ssl;
                        if (ValidateServerCertificateSocksProxy)
                        {
                            ssl = new SslStream(networkStream);
                        }
                        else
                        {
                            ssl = new SslStream(networkStream, false, IgnoreValidateServerCertificate);
                        }
                        ssl.AuthenticateAsClient(requestUri.DnsSafeHost);
                        readStream = ssl;
                    }
                    else
                    {
                        readStream = networkStream;
                    }

                    string requestString = BuildHttpRequestMessage(requestUri, http1SubVers);

                    var request = Encoding.ASCII.GetBytes(requestString);
                    readStream.Write(request, 0, request.Length);
                    readStream.Flush();

                    var buffer = new byte[client.ReceiveBufferSize];

                    var readlen = 0;
                    do
                    {
                        readlen = readStream.Read(buffer, 0, buffer.Length);
                        response.AddRange(buffer.Take(readlen));
                    } while (readlen != 0);

                    readStream.Close();
                }

                var webResponse = new SocksHttpWebResponse(requestUri, response.ToArray());

                if ((int)webResponse.StatusCode >= 200 && (int)webResponse.StatusCode < 300) // optim : most probable case done in first in a if
                {
                    return(webResponse);
                }
                else if (webResponse.StatusCode == HttpStatusCode.Moved || webResponse.StatusCode == HttpStatusCode.MovedPermanently || webResponse.StatusCode == HttpStatusCode.Found) // found and moveds are similear
                {
                    string redirectUrl = webResponse.Headers["Location"];
                    if (string.IsNullOrEmpty(redirectUrl))
                    {
                        throw new WebException("Missing location for redirect");
                    }
                    if (AllowAutoRedirect)
                    {
                        requestUri = new Uri(requestUri, redirectUrl); // set only if used for next try
                        if (!RefuseOtherDomainRedirect || requestUri.DnsSafeHost == RequestUri.DnsSafeHost)
                        {
                            continue;
                        }
                        else
                        {
                            throw new WebException(webResponse.StatusDescription, null, WebExceptionStatus.ProtocolError, webResponse);
                        }
                    }
                    else
                    {
                        throw new WebException(webResponse.StatusDescription, null, WebExceptionStatus.ProtocolError, webResponse);
                    }
                }
                else if (webResponse.StatusCode == HttpStatusCode.BadRequest)
                {
                    var msg = webResponse.GetResponseString();
                    if (msg != null && msg.StartsWith("HTTP/1.0") && http1SubVers == 1) // HTTP 1.1 may not be supported, try HTTP 1.0
                    {
                        http1SubVers = 0;                                               // retry same URL in HTTP 1.0 instread of HTTP 1.1
                        continue;
                    }
                }
                throw new WebException(webResponse.StatusDescription, null, WebExceptionStatus.UnknownError, webResponse);
            }
            throw new WebException("Too many redirects", null, WebExceptionStatus.ProtocolError, SocksHttpWebResponse.CreateErrorResponse(HttpStatusCode.BadRequest));
        }