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); } }