Advertisement
AyrA

SOCKSclient

Aug 17th, 2013
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 12.85 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Threading;
  7.  
  8. namespace Server
  9. {
  10.     public delegate void SocksClosedHandler(SOCKSclient sc);
  11.  
  12.     /// <summary>
  13.     /// Various states, the socks client can be
  14.     /// </summary>
  15.     public enum SocksState
  16.     {
  17.         /// <summary>
  18.         /// Connected, but version not yet determined (no traffic)
  19.         /// </summary>
  20.         VersionSelection,
  21.         /// <summary>
  22.         /// Destination not yet selected
  23.         /// </summary>
  24.         Destination,
  25.         /// <summary>
  26.         /// Destination selected and connection open
  27.         /// </summary>
  28.         Open,
  29.         /// <summary>
  30.         /// Socket closed
  31.         /// </summary>
  32.         Closed
  33.     }
  34.  
  35.     public class SOCKSclient
  36.     {
  37.         #region BYTE_POS
  38.         private const int P_NMETHODS = 1;
  39.         private const int P_VER = 0;
  40.         private const int P_METHODS = 2;
  41.         private const int P_METHOD = 1;
  42.  
  43.         private const int P_CMD = 1;
  44.         private const int P_RSV = 2;
  45.         private const int P_ATYP = 3;
  46.         private const int P_DNSLEN = 4;
  47.         #endregion
  48.  
  49.         #region SOCKS4
  50.         private const int S4_IP = 4;
  51.         private const int S4_PORT = 2;
  52.         private const int S4_CTYPE = 1;
  53.         #endregion
  54.  
  55.         #region AUTH_METHODS
  56.         private const byte M_NO_AUTH_REQUIRED = 0x00;
  57.         private const byte M_GSSAPI = 0x01;
  58.         private const byte M_USERNAME_PASSWORD = 0x02;
  59.         private const byte M_NO_ACCEPTABLE_METHOD = 0xFF;
  60.         #endregion
  61.  
  62.         #region CMD_TYPE
  63.         private const byte CMD_TCP = 0x01;
  64.         private const byte CMD_SRV = 0x02;
  65.         private const byte CMD_UDP = 0x03;
  66.         #endregion
  67.  
  68.         #region A_TYPE
  69.         private const byte A_IP4 = 0x01;
  70.         private const byte A_DNS = 0x03;
  71.         private const byte A_IP6 = 0x04;
  72.         #endregion
  73.  
  74.         #region CON_ANSWERS
  75.         private const byte C_OK = 0;
  76.         private const byte C_SOCKS_ERROR = 1;
  77.         private const byte C_DENIED = 2;
  78.         private const byte C_NET_UNREACHABLE = 3;
  79.         private const byte C_HOST_UNREACHABLE = 4;
  80.         private const byte C_REFUSED = 5;
  81.         private const byte C_TTL_EXPIRED = 6;
  82.         private const byte C_CMD_INVALID = 7;
  83.         private const byte C_ATYP_INVALID = 8;
  84.         #endregion
  85.  
  86.         private List<byte> LoginSelection;
  87.         private EventSocket c;
  88.         private EventSocket r;
  89.         private Thread T;
  90.  
  91.         public event SocksClosedHandler SocksClosed;
  92.  
  93.         private SocksState Status;
  94.  
  95.         public SOCKSclient(EventSocket es)
  96.         {
  97.             SocksClosed += new SocksClosedHandler(SOCKSclient_SocksClosed);
  98.             LoginSelection = new List<byte>();
  99.             c = es;
  100.             r = null;
  101.             Status = SocksState.VersionSelection;
  102.             c.DataReceived += new DataTransferredHandler(c_DataReceived);
  103.             c.Disconnected += new DisconnectedHandler(c_Disconnected);
  104.         }
  105.  
  106.         ~SOCKSclient()
  107.         {
  108.             Close();
  109.         }
  110.  
  111.         void SOCKSclient_SocksClosed(SOCKSclient sc)
  112.         {
  113.             //NOOP EVENT
  114.         }
  115.  
  116.         public void Close()
  117.         {
  118.             Status = SocksState.Closed;
  119.             if (c != null)
  120.             {
  121.                 c.Disconnect(true);
  122.                 c = null;
  123.             }
  124.             if (r != null)
  125.             {
  126.                 r.Disconnect(true);
  127.                 r = null;
  128.             }
  129.             if (LoginSelection != null)
  130.             {
  131.                 LoginSelection.Clear();
  132.                 LoginSelection = null;
  133.             }
  134.             if (T != null)
  135.             {
  136.                 T.Join(2000);
  137.                 try
  138.                 {
  139.                     T.Abort();
  140.                 }
  141.                 catch
  142.                 {
  143.                 }
  144.             }
  145.             SocksClosed(this);
  146.         }
  147.  
  148.         void c_Disconnected(IPEndPoint Remote)
  149.         {
  150.             Console.WriteLine("SOCKS: LDisconnected");
  151.             Close();
  152.         }
  153.  
  154.         void c_DataReceived(byte[] data)
  155.         {
  156.             switch (Status)
  157.             {
  158.                 case SocksState.VersionSelection:
  159.                     LoginSelection.AddRange(data);
  160.                     if (LoginSelection.Count > 2)
  161.                     {
  162.                         switch(LoginSelection[P_VER])
  163.                         {
  164.                             case 5:
  165.                                 if (LoginSelection.Count > 2)
  166.                                 {
  167.                                     if (LoginSelection.Count == 2 + LoginSelection[P_NMETHODS])
  168.                                     {
  169.                                         for (int i = 0; i < LoginSelection[P_NMETHODS]; i++)
  170.                                         {
  171.                                             if (LoginSelection[2 + i] == M_NO_AUTH_REQUIRED)
  172.                                             {
  173.                                                 //Method ok, now in Destination select status
  174.                                                 c.send(new byte[] { 5, M_NO_AUTH_REQUIRED });
  175.                                                 LoginSelection.Clear();
  176.                                                 Status = SocksState.Destination;
  177.                                                 Console.WriteLine("Version 5 accepted");
  178.                                                 break;
  179.                                             }
  180.                                         }
  181.                                     }
  182.                                     else
  183.                                     {
  184.                                         c.send(new byte[] { 5, M_NO_ACCEPTABLE_METHOD });
  185.                                         Console.WriteLine("unacceptable v5 auth");
  186.                                         Close();
  187.                                     }
  188.                                 }
  189.                                 break;
  190.                             case 4:
  191.                                 //check for full data
  192.                                 if (LoginSelection.Count == 9)
  193.                                 {
  194.                                     //Remove null terminator
  195.                                     LoginSelection.RemoveAt(8);
  196.                                     byte[] FullData = LoginSelection.ToArray();
  197.                                     LoginSelection.Clear();
  198.                                     try
  199.                                     {
  200.                                         r = new EventSocket(ExtractDest(4,FullData));
  201.                                         Status = SocksState.Open;
  202.                                         r.DataReceived += new DataTransferredHandler(r_DataReceived);
  203.                                         r.Disconnected += new DisconnectedHandler(r_Disconnected);
  204.                                         FullData[P_VER] = 0;
  205.                                         FullData[S4_CTYPE] = 90;
  206.                                         c.send(FullData);
  207.                                         T = new Thread(new ThreadStart(checkCon));
  208.                                         T.IsBackground = true;
  209.                                         T.Start();
  210.                                         Console.WriteLine("Version 4 accepted");
  211.                                     }
  212.                                     catch
  213.                                     {
  214.                                         Close();
  215.                                     }
  216.                                 }
  217.                                 break;
  218.                             default:
  219.                                 Console.WriteLine("Unknown version");
  220.                                 Close();
  221.                                 break;
  222.                         }
  223.                     }
  224.                     break;
  225.                 case SocksState.Destination:
  226.                     LoginSelection.AddRange(data);
  227.                     if (LoginSelection.Count > 7)
  228.                     {
  229.                         if (LoginSelection[P_CMD] == CMD_TCP)
  230.                         {
  231.                             //Check if IPv4 or DNS name
  232.                             if ((LoginSelection.Count == 10 && LoginSelection[P_ATYP] == A_IP4) || (LoginSelection[P_ATYP] == A_DNS && LoginSelection.Count == 7 + LoginSelection[P_DNSLEN]))
  233.                             {
  234.                                 try
  235.                                 {
  236.                                     r = new EventSocket(ExtractDest(5, LoginSelection.ToArray()));
  237.                                     Status = SocksState.Open;
  238.                                     r.DataReceived += new DataTransferredHandler(r_DataReceived);
  239.                                     r.Disconnected += new DisconnectedHandler(r_Disconnected);
  240.                                     LoginSelection[P_CMD] = C_OK;
  241.                                     c.send(LoginSelection.ToArray());
  242.                                     T = new Thread(new ThreadStart(checkCon));
  243.                                     T.IsBackground = true;
  244.                                     T.Start();
  245.                                     Console.WriteLine("Version 5 open");
  246.                                 }
  247.                                 catch
  248.                                 {
  249.                                     LoginSelection[P_CMD] = C_HOST_UNREACHABLE;
  250.                                     c.send(LoginSelection.ToArray());
  251.                                     Close();
  252.                                 }
  253.                             }
  254.                             else
  255.                             {
  256.                                 LoginSelection[P_CMD] = C_ATYP_INVALID;
  257.                                 c.send(LoginSelection.ToArray());
  258.                                 Close();
  259.                             }
  260.                         }
  261.                         else
  262.                         {
  263.                             LoginSelection[P_CMD] = C_CMD_INVALID;
  264.                             c.send(LoginSelection.ToArray());
  265.                             Close();
  266.                         }
  267.                         LoginSelection.Clear();
  268.                     }
  269.                     break;
  270.                 case SocksState.Open:
  271.                     try
  272.                     {
  273.                         r.send(data);
  274.                     }
  275.                     catch
  276.                     {
  277.                         Close();
  278.                     }
  279.                     break;
  280.                 case SocksState.Closed:
  281.                     Close();
  282.                     break;
  283.             }
  284.         }
  285.  
  286.         void r_Disconnected(IPEndPoint Remote)
  287.         {
  288.             Console.WriteLine("SOCKS: RDisconnected");
  289.             Close();
  290.         }
  291.  
  292.         void r_DataReceived(byte[] data)
  293.         {
  294.             Console.WriteLine("SOCKS: RDATA");
  295.             c.send(data);
  296.         }
  297.  
  298.         void checkCon()
  299.         {
  300.             while (c!=null && r!=null && c.IsConnected && r.IsConnected)
  301.             {
  302.                 Thread.Sleep(500);
  303.             }
  304.             Close();
  305.         }
  306.  
  307.         private IPEndPoint ExtractDest(int Version,byte[] Data)
  308.         {
  309.             switch (Version)
  310.             {
  311.                 case 4:
  312.                     return new IPEndPoint(IPAddress.Parse(string.Format("{0}.{1}.{2}.{3}", Data[S4_IP], Data[S4_IP + 1], Data[S4_IP + 2], Data[S4_IP + 3])), Data[S4_PORT] * 256 + Data[S4_PORT + 1]);
  313.                 case 5:
  314.                     IPEndPoint tempEP = null;
  315.                     switch (Data[P_ATYP])
  316.                     {
  317.                         case 1:
  318.                             tempEP = new IPEndPoint(IPAddress.Parse(string.Format("{0}.{1}.{2}.{3}", Data[P_DNSLEN], Data[P_DNSLEN + 1], Data[P_DNSLEN + 2], Data[P_DNSLEN + 3])), Data[P_DNSLEN + 4] * 256 + Data[P_DNSLEN + 5]);
  319.                             break;
  320.                         case 3:
  321.                             byte[] DNSname = new byte[P_DNSLEN];
  322.                             Array.Copy(Data, P_DNSLEN + 1, DNSname, 0, Data[P_DNSLEN]);
  323.                             IPAddress[] ia = EventSocket.lookup(Encoding.ASCII.GetString(DNSname), true);
  324.                             if (ia != null)
  325.                             {
  326.                                 return new IPEndPoint(ia[0], Data[Data.Length - 2] * 256 + Data[Data.Length - 1]);
  327.                             }
  328.                             else
  329.                             {
  330.                                 Close();
  331.                             }
  332.                             break;
  333.                         case 4:
  334.                             //IPv6 not allowed
  335.                             break;
  336.                     }
  337.  
  338.                     return tempEP;
  339.                 default:
  340.                     return null;
  341.             }
  342.         }
  343.     }
  344. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement