Home > Uncategorized > Connecting to a #Socks5 proxy from C#

Connecting to a #Socks5 proxy from C#

socks5

Socks5 is a proxy server that operates on the TCP level, rather than the HTTP/S level, which makes it possible to proxy IP trafic such as email, FTP, voip, etc. Normally, you use a forwarding proxy like Squid, privoxy, or Polipo to bridge the HTTP / Socks5 layer, but you can also interface at socket level from C#

This example is modified from Zahmed on CodeProject, https://www.codeproject.com/articles/5954/c-class-for-connecting-via-a-socks-proxy-server – so credit due there.

So, here’s the modified helper class;

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.
* https://www.codeproject.com/articles/5954/c-class-for-connecting-via-a-socks-proxy-server
*/
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)
{
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++]=0x02; // 2 Authentication methods are in packet…
request[nIndex++]=0x00; // NO AUTHENTICATION REQUIRED
request[nIndex++]=0x00; // NO AUTHENTICATION REQUIRED
//request[nIndex++]=0x02; // USERNAME/PASSWORD
// 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;
// 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;
}
}
}

Which is the same as on codeproject, without the username/password requirement, and here’s how it’s called;

byte[] bytesReceived = new byte[1024];
Socket client;
client = LMKR.SocksProxy.ConnectToSocks5Proxy(“127.0.0.1”, 9050, “www.icanhazip.com”, 80);
string strGet = “GET /\r\n\r\n”;
client.Send(Encoding.ASCII.GetBytes(strGet));
var bytes = client.Receive(bytesReceived, bytesReceived.Length, 0);
var page = Encoding.ASCII.GetString(bytesReceived, 0, bytes);
Console.WriteLine(page);
client.Close();

 

Advertisements
Categories: Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: