public static SocksHttpWebResponse CreateErrorResponse(HttpStatusCode statusCode) { var response = new SocksHttpWebResponse { StatusCode = statusCode }; return response; }
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; }
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)); }