public static SocketConnectionResult TryCreateTunnel(Socket socks5Socket, string destAddress, int destPort, ProxyInfo proxy, bool resolveHostnamesLocally) { try { // SEND HELLO socks5Socket.Send(BuildHelloMessage(proxy.Authenticate)); // RECEIVE HELLO RESPONSE - HANDLE AUTHENTICATION byte[] buffer = new byte[255]; if (socks5Socket.Receive(buffer) != 2) { return(SocketConnectionResult.InvalidProxyResponse); } if (buffer[0] != SocksVersion) { return(SocketConnectionResult.InvalidProxyResponse); } if (buffer[1] == (byte)Authentication.UsernamePassword) { if (!proxy.Authenticate) { // Proxy server is requesting UserPass auth even tho we did not allow it return(SocketConnectionResult.InvalidProxyResponse); } else { // We have to try and authenticate using the Username and Password // https://tools.ietf.org/html/rfc1929 socks5Socket.Send(proxy.AuthenticationMessage); if (socks5Socket.Receive(buffer) != 2) { return(SocketConnectionResult.InvalidProxyResponse); } if (buffer[0] != SubnegotiationVersion) { return(SocketConnectionResult.InvalidProxyResponse); } if (buffer[1] != 0) { return(SocketConnectionResult.AuthenticationError); } } } else if (buffer[1] != (byte)Authentication.NoAuthentication) { return(SocketConnectionResult.AuthenticationError); } if (resolveHostnamesLocally && Helpers.GetAddressType(destAddress) == AddressType.DomainName) { destAddress = destAddress.Resolve().ToString(); } // SEND REQUEST socks5Socket.Send(BuildRequestMessage(Command.Connect, Helpers.GetAddressType(destAddress), destAddress, destPort)); // RECEIVE RESPONSE int received = socks5Socket.Receive(buffer); if (received < 8) { return(SocketConnectionResult.InvalidProxyResponse); } if (buffer[0] != SocksVersion) { return(SocketConnectionResult.InvalidProxyResponse); } if (buffer[1] > 8) { return(SocketConnectionResult.InvalidProxyResponse); } if (buffer[1] != 0) { return((SocketConnectionResult)buffer[1]); } if (buffer[2] != 0) { return(SocketConnectionResult.InvalidProxyResponse); } if (buffer[3] != 1 && buffer[3] != 3 && buffer[3] != 4) { return(SocketConnectionResult.InvalidProxyResponse); } AddressType boundAddress = (AddressType)buffer[3]; if (boundAddress == AddressType.IPv4) { if (received != 10) { return(SocketConnectionResult.InvalidProxyResponse); } } else if (boundAddress == AddressType.IPv6) { if (received != 22) { return(SocketConnectionResult.InvalidProxyResponse); } } else { int domainLength = buffer[4]; if (received != 7 + domainLength) { return(SocketConnectionResult.InvalidProxyResponse); } } return(SocketConnectionResult.OK); } catch (SocketException ex) { return(ex.ToConnectionResult()); } catch { return(SocketConnectionResult.UnknownError); } }
public static SocketConnectionResult TryCreateTunnel(Socket socks5Socket, string destAddress, int destPort, ProxyInfo proxy, IDnsResolver dnsResolver = null) { try { // SEND HELLO byte[] SendByte = BuildHelloMessage(proxy.Authenticate); var s = ""; for (var i = 1; i <= SendByte.Length; i++) { s += SendByte[i - 1] + ","; } Console.WriteLine("[Socks5.cs]send:" + s); socks5Socket.Send(SendByte); // RECEIVE HELLO RESPONSE - HANDLE AUTHENTICATION byte[] GetByte = new byte[255]; var len = socks5Socket.Receive(GetByte); Console.WriteLine("[Socks5.cs]len:" + len); if (len != 2) { return(SocketConnectionResult.InvalidProxyResponse); } if (GetByte[0] != SocksVersion) { return(SocketConnectionResult.InvalidProxyResponse); } if (GetByte[1] == (byte)Authentication.UsernamePassword) { if (!proxy.Authenticate) { // Proxy server is requesting UserPass auth even tho we did not allow it return(SocketConnectionResult.InvalidProxyResponse); } else { // We have to try and authenticate using the Username and Password // https://tools.ietf.org/html/rfc1929 socks5Socket.Send(proxy.AuthenticationMessage); if (socks5Socket.Receive(GetByte) != 2) { return(SocketConnectionResult.InvalidProxyResponse); } if (GetByte[0] != SubnegotiationVersion) { return(SocketConnectionResult.InvalidProxyResponse); } if (GetByte[1] != 0) { return(SocketConnectionResult.AuthenticationError); } } } else if (GetByte[1] != (byte)Authentication.NoAuthentication) { return(SocketConnectionResult.AuthenticationError); } if (dnsResolver != null && Helpers.GetAddressType(destAddress) == AddressType.DomainName) { var ipAddress = dnsResolver.TryResolve(destAddress); if (ipAddress == null) { return(SocketConnectionResult.HostUnreachable); } destAddress = ipAddress.ToString(); } // SEND REQUEST socks5Socket.Send(BuildRequestMessage(Command.Connect, Helpers.GetAddressType(destAddress), destAddress, destPort)); // RECEIVE RESPONSE int received = socks5Socket.Receive(GetByte); if (received < 8) { return(SocketConnectionResult.InvalidProxyResponse); } if (GetByte[0] != SocksVersion) { return(SocketConnectionResult.InvalidProxyResponse); } if (GetByte[1] > 8) { return(SocketConnectionResult.InvalidProxyResponse); } if (GetByte[1] != 0) { return((SocketConnectionResult)GetByte[1]); } if (GetByte[2] != 0) { return(SocketConnectionResult.InvalidProxyResponse); } if (GetByte[3] != 1 && GetByte[3] != 3 && GetByte[3] != 4) { return(SocketConnectionResult.InvalidProxyResponse); } AddressType boundAddress = (AddressType)GetByte[3]; if (boundAddress == AddressType.IPv4) { if (received != 10) { return(SocketConnectionResult.InvalidProxyResponse); } } else if (boundAddress == AddressType.IPv6) { if (received != 22) { return(SocketConnectionResult.InvalidProxyResponse); } } else { int domainLength = GetByte[4]; if (received != 7 + domainLength) { return(SocketConnectionResult.InvalidProxyResponse); } } return(SocketConnectionResult.OK); } catch (SocketException ex) { return(ex.ToConnectionResult()); } catch { return(SocketConnectionResult.UnknownError); } }