Created
March 2, 2016 18:40
-
-
Save NaokiStark/5479ec5d3c46ad0fedc0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Text; | |
/* | |
* zahmed | |
* Date 23 Jan 2004 | |
* Socks 5 RFC is available at http://www.faqs.org/rfcs/rfc1928.html. | |
*/ | |
namespace LMKR | |
{ | |
public class ConnectionException:ApplicationException | |
{ | |
public ConnectionException(string message) | |
:base(message) | |
{ | |
} | |
} | |
/// <summary> | |
/// Provides sock5 functionality to clients (Connect only). | |
/// </summary> | |
public class SocksProxy | |
{ | |
private SocksProxy(){} | |
#region ErrorMessages | |
private static string[] errorMsgs= { | |
"Operation completed successfully.", | |
"General SOCKS server failure.", | |
"Connection not allowed by ruleset.", | |
"Network unreachable.", | |
"Host unreachable.", | |
"Connection refused.", | |
"TTL expired.", | |
"Command not supported.", | |
"Address type not supported.", | |
"Unknown error." | |
}; | |
#endregion | |
public static Socket ConnectToSocks5Proxy(string proxyAdress, ushort proxyPort, string destAddress, ushort destPort, | |
string userName, string password) | |
{ | |
IPAddress destIP = null; | |
IPAddress proxyIP = null; | |
byte[] request = new byte[257]; | |
byte[] response = new byte[257]; | |
ushort nIndex; | |
try | |
{ | |
proxyIP = IPAddress.Parse(proxyAdress); | |
} | |
catch(FormatException) | |
{ // get the IP address | |
proxyIP = Dns.GetHostByAddress(proxyAdress).AddressList[0]; | |
} | |
// Parse destAddress (assume it in string dotted format "212.116.65.112" ) | |
try | |
{ | |
destIP = IPAddress.Parse(destAddress); | |
} | |
catch(FormatException) | |
{ | |
// wrong assumption its in domain name format "www.microsoft.com" | |
} | |
IPEndPoint proxyEndPoint = new IPEndPoint(proxyIP,proxyPort); | |
// open a TCP connection to SOCKS server... | |
Socket s = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); | |
s.Connect(proxyEndPoint); | |
nIndex = 0; | |
request[nIndex++]=0x05; // Version 5. | |
request[nIndex++]=0x01; // 1 Authentication methods are in packet... | |
request[nIndex++]=0x00; // NO AUTHENTICATION REQUIRED | |
// Send the authentication negotiation request... | |
s.Send(request,nIndex,SocketFlags.None); | |
// Receive 2 byte response... | |
int nGot = s.Receive(response,2,SocketFlags.None); | |
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.Close(); | |
throw new ConnectionException("None of the authentication method was accepted by proxy server."); | |
} | |
byte[] rawBytes; | |
if (response[1]==0x02) | |
{//Username/Password Authentication protocol | |
nIndex = 0; | |
request[nIndex++]=0x05; // Version 5. | |
// add user name | |
request[nIndex++]=(byte)userName.Length; | |
rawBytes = Encoding.Default.GetBytes(userName); | |
rawBytes.CopyTo(request,nIndex); | |
nIndex+=(ushort)rawBytes.Length; | |
// add password | |
request[nIndex++]=(byte)password.Length; | |
rawBytes = Encoding.Default.GetBytes(password); | |
rawBytes.CopyTo(request,nIndex); | |
nIndex+=(ushort)rawBytes.Length; | |
// Send the Username/Password request | |
s.Send(request,nIndex,SocketFlags.None); | |
// Receive 2 byte response... | |
nGot = s.Receive(response,2,SocketFlags.None); | |
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 | |
if (destIP != null) | |
{// Destination adress in an IP. | |
switch(destIP.AddressFamily) | |
{ | |
case AddressFamily.InterNetwork: | |
// Address is IPV4 format | |
request[nIndex++]=0x01; | |
rawBytes = destIP.GetAddressBytes(); | |
rawBytes.CopyTo(request,nIndex); | |
nIndex+=(ushort)rawBytes.Length; | |
break; | |
case AddressFamily.InterNetworkV6: | |
// Address is IPV6 format | |
request[nIndex++]=0x04; | |
rawBytes = destIP.GetAddressBytes(); | |
rawBytes.CopyTo(request,nIndex); | |
nIndex+=(ushort)rawBytes.Length; | |
break; | |
} | |
} | |
else | |
{// 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.Default.GetBytes(destAddress); | |
rawBytes.CopyTo(request,nIndex); | |
nIndex+=(ushort)rawBytes.Length; | |
} | |
// 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. | |
s.Send(request,nIndex,SocketFlags.None); | |
s.Receive(response); // Get variable length response... | |
if (response[1]!=0x00) | |
throw new ConnectionException(errorMsgs[response[1]]); | |
// Success Connected... | |
return s; | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment