public static async Task <StreamSocket> ConnectToSocks5Proxy(double timeout, StreamSocket s, DataWriter _dataWriter, DataReader _dataReader, string proxyAddress, ushort proxyPort, string destAddress, ushort destPort, string userName, string password) { var destIP = new HostName(destAddress); var proxyIP = new HostName(proxyAddress); var request = new byte[256]; var response = new byte[256]; ushort nIndex; // open a TCP connection to SOCKS server... //Connect(s, proxyEndPoint); await s.ConnectAsync(proxyIP, proxyPort.ToString(CultureInfo.InvariantCulture)).WithTimeout(timeout); nIndex = 0; request[nIndex++] = 0x05; // Version 5. request[nIndex++] = 0x02; // 2 Authentication methods are in packet... request[nIndex++] = 0x00; // NO AUTHENTICATION REQUIRED request[nIndex++] = 0x02; // USERNAME/PASSWORD Send(_dataWriter, request, 0, nIndex); var nGot = Receive(_dataReader, response, 0, response.Length); // Receive 2 byte response... if (nGot != 2) { throw new ConnectionException("Bad response received from proxy server."); } if (response[1] == 0xFF) { // No authentication method was accepted close the socket. s.Dispose(); throw new ConnectionException("None of the authentication method was accepted by proxy server."); } byte[] rawBytes; //Username/Password Authentication protocol if (response[1] == 0x02) { nIndex = 0; request[nIndex++] = 0x01; // Version 5. // add user name request[nIndex++] = (byte)userName.Length; rawBytes = Encoding.UTF8.GetBytes(userName); rawBytes.CopyTo(request, nIndex); nIndex += (ushort)rawBytes.Length; // add password request[nIndex++] = (byte)password.Length; rawBytes = Encoding.UTF8.GetBytes(password); rawBytes.CopyTo(request, nIndex); nIndex += (ushort)rawBytes.Length; // Send the Username/Password request Send(_dataWriter, request, 0, nIndex); nGot = Receive(_dataReader, response, 0, response.Length); if (nGot != 2) { throw new ConnectionException("Bad response received from proxy server."); } if (response[1] != 0x00) { throw new ConnectionException("Bad Usernaem/Password."); } } //// This version only supports connect command. //// UDP and Bind are not supported. // Send connect request now... nIndex = 0; request[nIndex++] = 0x05; // version 5. request[nIndex++] = 0x01; // command = connect. request[nIndex++] = 0x00; // Reserve = must be 0x00 // Destination adress in an IP. switch (destIP.Type) { case HostNameType.Ipv4: // Address is IPV4 format request[nIndex++] = 0x01; rawBytes = destIP.GetAddressBytes(); rawBytes.CopyTo(request, nIndex); nIndex += (ushort)rawBytes.Length; break; case HostNameType.Ipv6: // Address is IPV6 format request[nIndex++] = 0x04; rawBytes = destIP.GetAddressBytes(); rawBytes.CopyTo(request, nIndex); nIndex += (ushort)rawBytes.Length; break; //case HostNameType.DomainName: // // Dest. address is domain name. // request[nIndex++] = 0x03; // Address is full-qualified domain name. // request[nIndex++] = Convert.ToByte(destAddress.Length); // length of address. // rawBytes = Encoding.UTF8.GetBytes(destAddress); // rawBytes.CopyTo(request, nIndex); // nIndex += (ushort)rawBytes.Length; // break; } // using big-edian byte order byte[] portBytes = BitConverter.GetBytes(destPort); for (int i = portBytes.Length - 1; i >= 0; i--) { request[nIndex++] = portBytes[i]; } // send connect request. Send(_dataWriter, request, 0, nIndex); nGot = Receive(_dataReader, response, 0, response.Length); if (response[1] != 0x00) { throw new ConnectionException(errorMsgs[response[1]]); } // Success Connected... return(s); }