Linux平台socks5代理

导读:
  前几天MSN老上不去,我还以为是公司做了防火墙限制。于是把去年这个时候写得一个代理程序改了改,拿出来用。结果发现MSN是因为微软的问题,鄙视啊……
  因为写得比较急,这个只支持TCP代理,UDP的我没写,因为MSN用不上。这个代码可以随意修改分发,不过最好能给我一份。
  这是头文件:

  
  
  
  
  1.  
  2.   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////   
  3.   // Socks5代理头文件,定义协议相关数据包结构   
  4.   // 版本 0.1,作者 云舒   
  5.   // 2007年1月9日凌晨1点15分,GF回家已经11天了。   
  6.   // 2008年1月25日修改,今年GF一直在我身边,哈哈   
  7.   //   
  8.   // 参考:   
  9.   // http://www.rfc-editor.org/rfc/rfc1928.txt   
  10.   // http://www.rfc-editor.org/rfc/rfc1929.txt   
  11.   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////   
  12.   #ifndef SOCKS5_H   
  13.   #define SOCKS5_H   
  14.   #define VERSION 0x05   
  15.   #define CONNECT 0x01   
  16.   #define IPV4 0x01   
  17.   #define DOMAIN 0x03   
  18.   #define IPV6 0x04   
  19.   typedef struct _method_select_response // 协商方法服务器响应   
  20.   {   
  21.   char version; // 服务器支持的Socks版本,0x04或者0x05   
  22.   char select_method;// 服务器选择的方法,0x00为匿名,0x02为密码认证   
  23.   } METHOD_SELECT_RESPONSE;   
  24.   typedef struct _method_select_request // 协商方法服务端请求   
  25.   {   
  26.   char version; // 客户端支持的版本,0x04或者0x05   
  27.   char number_methods; // 客户端支持的方法的数量   
  28.   char methods[255]; // 客户端支持的方法类型,最多255个,0x00为匿名,0x02为密码认证   
  29.   } METHOD_SELECT_REQUEST;   
  30.   typedef struct _AUTH_RESPONSE // 用户密码认证服务端响应   
  31.   {   
  32.   char version;// 版本,此处恒定为0x01   
  33.   char result;// 服务端认证结果,0x00为成功,其他均为失败   
  34.   } AUTH_RESPONSE;   
  35.   typedef struct _AUTH_REQUEST //用户密码认证客户端请求   
  36.   {   
  37.   char version; // 版本,此处恒定为0x01   
  38.   char name_len; // 第三个字段用户名的长度,一个字节,最长为0xff   
  39.   char name[255]; // 用户名   
  40.   char pwd_len;// 第四个字段密码的长度,一个字节,最长为0xff   
  41.   char pwd[255]; // 密码   
  42.   } AUTH_REQUEST;   
  43.   typedef struct _SOCKS5_RESPONSE // 连接真实主机,Socks代理服务器响应   
  44.   {   
  45.   char version; // 服务器支持的Socks版本,0x04或者0x05   
  46.   char reply; // 代理服务器连接真实主机的结果,0x00成功   
  47.   char reserved; // 保留位,恒定位0x00   
  48.   char address_type; // Socks代理服务器绑定的地址类型,IP V4为0x01,IP V6为0x04,域名为0x03   
  49.   char address_port[1]; // 如果address_type为域名,此处第一字节为域名长度,其后为域名本身,无0字符结尾,域名后为Socks代理服务器绑定端口   
  50.   }SOCKS5_RESPONSE;   
  51.   typedef struct _SOCKS5_REQUEST // 客户端请求连接真实主机   
  52.   {   
  53.   char version; // 客户端支持的Socks版本,0x04或者0x05   
  54.   char cmd; // 客户端命令,CONNECT为0x01,BIND为0x02,UDP为0x03,一般为0x01   
  55.   char reserved; // 保留位,恒定位0x00   
  56.   char address_type; // 客户端请求的真实主机的地址类型,IP V4为0x00,IP V6为0x04,域名为 0x03 char address_port[1]; // 如果address_type为域名,此处第一字节为域名长度,其后为域名本身,无0字符结尾,域名后为真实主机绑定端口   
  57.   }SOCKS5_REQUEST;   
  58.   #endif   
  59.   主程序来了:   
  60.   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////   
  61.   // Socks5程序,只支持TCP代理   
  62.   // 版本 0.1,作者 云舒   
  63.   // 2007年1月9日凌晨1点15分,GF回家已经11天了。   
  64.   // 2008年1月25日修改,今年GF一直在我身边,哈哈   
  65.   //   
  66.   // 参考:   
  67.   // http://www.rfc-editor.org/rfc/rfc1928.txt   
  68.   // http://www.rfc-editor.org/rfc/rfc1929.txt   
  69.   //编译:   
  70.   // gcc -o socks5 -O2 Socks5.c -lpthread( RedHat AS5测试 )   
  71.   ///////////////////////////////////////////////////////////////////////////////////////////////////////////////   
  72.   #include   
  73.   #include   
  74.   #include   
  75.   #include   
  76.   #include   
  77.   #include   
  78.   #include   
  79.   #include   
  80.   #include   
  81.   #include   
  82.   #include   
  83.   #include   
  84.   #include   
  85.   #include "Socks5.h"   
  86.   #define MAX_USER 10   
  87.   #define BUFF_SIZE 1024   
  88.   #define AUTH_CODE 0x02   
  89.   #define TIME_OUT 6000000   
  90.   #define USER_NAME "yunshu"   
  91.   #define PASS_WORD "ph4nt0m"   
  92.   // Select auth method, return 0 if success, -1 if failed   
  93.   int SelectMethod( int sock )   
  94.   {   
  95.   char recv_buffer[BUFF_SIZE] = { 0 };   
  96.   char reply_buffer[2] = { 0 };   
  97.   METHOD_SELECT_REQUEST *method_request;   
  98.   METHOD_SELECT_RESPONSE *method_response;   
  99.      
  100.   // recv METHOD_SELECT_REQUEST   
  101.   int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );   
  102.   if( ret <= 0 )   
  103.   {   
  104.   perror( "recv error" );   
  105.   close( sock );   
  106.   return -1;   
  107.   }   
  108.   //printf( "SelectMethod: recv %d bytes\n", ret );   
  109.   // if client request a wrong version or a wrong number_method   
  110.   method_request = (METHOD_SELECT_REQUEST *)recv_buffer;   
  111.   method_response = (METHOD_SELECT_RESPONSE *)reply_buffer;   
  112.   method_response->version = VERSION;   
  113.      
  114.   // if not socks5   
  115.   if( (int)method_request->version != VERSION )   
  116.   {   
  117.   method_response->select_method = 0xff;   
  118.   send( sock, method_response, sizeof(METHOD_SELECT_RESPONSE), 0 );   
  119.   close( sock );   
  120.      
  121.   return -1;   
  122.   }   
  123.   method_response->select_method = AUTH_CODE;   
  124.   if( -1 == send( sock, method_response, sizeof(METHOD_SELECT_RESPONSE), 0 ) )   
  125.   {   
  126.   close( sock );   
  127.   return -1;   
  128.   }   
  129.      
  130.   return 0;   
  131.   }   
  132.   // test password, return 0 for success.   
  133.   int AuthPassword( int sock )   
  134.   {   
  135.   char recv_buffer[BUFF_SIZE] = { 0 };   
  136.   char reply_buffer[BUFF_SIZE] = { 0 };   
  137.   AUTH_REQUEST *auth_request;   
  138.   AUTH_RESPONSE *auth_response;   
  139.      
  140.   // auth username and password   
  141.   int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );   
  142.   if( ret <= 0 )   
  143.   {   
  144.   perror( "recv username and password error" );   
  145.   close( sock );   
  146.   return -1;   
  147.   }   
  148.   //printf( "AuthPass: recv %d bytes\n", ret );   
  149.   auth_request = (AUTH_REQUEST *)recv_buffer;   
  150.   memset( reply_buffer, 0, BUFF_SIZE );   
  151.   auth_response = (AUTH_RESPONSE *)reply_buffer;   
  152.   auth_response->version = 0x01;   
  153.   char recv_name[256] = { 0 };   
  154.   char recv_pass[256] = { 0 };   
  155.   // auth_request->name_len is a char, max number is 0xff   
  156.   char pwd_str[2] = { 0 };   
  157.   strncpy( pwd_str, auth_request->name + auth_request->name_len, 1 );   
  158.   int pwd_len = (int)pwd_str[0];   
  159.   strncpy( recv_name, auth_request->name, auth_request->name_len );   
  160.   strncpy( recv_pass, auth_request->name + auth_request->name_len + sizeof(auth_request->pwd_len), pwd_len );   
  161.   //printf( "username: %s\npassword: %s\n", recv_name, recv_pass );   
  162.   // check username and password   
  163.   if( (strncmp( recv_name, USER_NAME, strlen(USER_NAME) ) == 0) &&   
  164.   (strncmp( recv_pass, PASS_WORD, strlen(PASS_WORD) ) == 0)   
  165.   )   
  166.   {   
  167.   auth_response->result = 0x00;   
  168.   if( -1 == send( sock, auth_response, sizeof(AUTH_RESPONSE), 0 ) )   
  169.   {   
  170.   close( sock );   
  171.   return -1;   
  172.   }   
  173.   else   
  174.   {   
  175.   return 0;   
  176.   }   
  177.   }   
  178.   else   
  179.   {   
  180.   auth_response->result = 0x01;   
  181.   send( sock, auth_response, sizeof(AUTH_RESPONSE), 0 );   
  182.   close( sock );   
  183.   return -1;   
  184.   }   
  185.   }   
  186.   // parse command, and try to connect real server.   
  187.   // return socket for success, -1 for failed.   
  188.   int ParseCommand( int sock )   
  189.   {   
  190.   char recv_buffer[BUFF_SIZE] = { 0 };   
  191.   char reply_buffer[BUFF_SIZE] = { 0 };   
  192.      
  193.   SOCKS5_REQUEST *socks5_request;   
  194.   SOCKS5_RESPONSE *socks5_response;   
  195.   // recv command   
  196.   int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );   
  197.   if( ret <= 0 )   
  198.   {   
  199.   perror( "recv connect command error" );   
  200.   close( sock );   
  201.   return -1;   
  202.   }   
  203.      
  204.   socks5_request = (SOCKS5_REQUEST *)recv_buffer;   
  205.   if( (socks5_request->version != VERSION) || (socks5_request->cmd != CONNECT) ||   
  206.   (socks5_request->address_type == IPV6) )   
  207.   {   
  208.   //printf( "connect command error.\n" );   
  209.   close( sock );   
  210.   return -1;   
  211.   }   
  212.   // begain process connect request   
  213.   struct sockaddr_in sin;   
  214.   memset( (void *)&sin, 0, sizeof(struct sockaddr_in) );   
  215.   sin.sin_family = AF_INET;   
  216.   // get real server's ip address   
  217.   if( socks5_request->address_type == IPV4 )   
  218.   {   
  219.   memcpy( &sin.sin_addr.s_addr, &socks5_request->address_type + sizeof(socks5_request->address_type) , 4 );   
  220.   memcpy( &sin.sin_port, &socks5_request->address_type + sizeof(socks5_request->address_type) + 4, 2 );   
  221.   //printf( "Real Server: %s %d\n", inet_ntoa( sin.sin_addr ), ntohs( sin.sin_port ) );   
  222.   }   
  223.   else if( socks5_request->address_type == DOMAIN )   
  224.   {   
  225.   char domain_length = *(&socks5_request->address_type + sizeof(socks5_request->address_type));   
  226.   char target_domain[ 256] = { 0 };   
  227.   strncpy( target_domain, &socks5_request->address_type + 2, (unsigned int)domain_length );   
  228.   //printf( "target: %s\n", target_domain );   
  229.   struct hostent *phost = gethostbyname( target_domain );   
  230.   if( phost == NULL )   
  231.   {   
  232.   //printf( "Resolve %s error!\n" , target_domain );   
  233.   close( sock );   
  234.   return -1;   
  235.   }   
  236.   memcpy( &sin.sin_addr , phost->h_addr_list[0] , phost->h_length );   
  237.   memcpy( &sin.sin_port, &socks5_request->address_type + sizeof(socks5_request->address_type) +   
  238.   sizeof(domain_length) + domain_length, 2 );   
  239.   }   
  240.   // try to connect to real server   
  241.   int real_server_sock = socket( AF_INET, SOCK_STREAM, 0 );   
  242.   if( real_server_sock <0 )   
  243.   {   
  244.   perror( "Socket creation failed\n");   
  245.      
  246.   close( sock );   
  247.   return -1;   
  248.   }   
  249.   memset( reply_buffer, 0, sizeof(BUFF_SIZE) );   
  250.   socks5_response = (SOCKS5_RESPONSE *)reply_buffer;   
  251.   socks5_response->version = VERSION;   
  252.   socks5_response->reserved = 0x00;   
  253.   socks5_response->address_type = 0x01;   
  254.   memset( socks5_response + 4, 0 , 6 );   
  255.   ret = connect( real_server_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in) );   
  256.   if( ret == 0 )   
  257.   {   
  258.   socks5_response->reply = 0x00;   
  259.   if( -1 == send( sock, socks5_response, 10, 0 ) )   
  260.   {   
  261.   close( sock );   
  262.      
  263.   return -1;   
  264.   }   
  265.   }   
  266.   else   
  267.   {   
  268.   perror( "Connect to real server error" );   
  269.   socks5_response->reply = 0x01;   
  270.   send( sock, socks5_response, 10, 0 );   
  271.      
  272.   close( sock );   
  273.   return -1;   
  274.   }   
  275.      
  276.   return real_server_sock;   
  277.   }   
  278.   int ForwardData( int sock, int real_server_sock )   
  279.   {   
  280.   char recv_buffer[BUFF_SIZE] = { 0 };   
  281.      
  282.   fd_set fd_read;   
  283.   struct timeval time_out;   
  284.   time_out.tv_sec = 0;   
  285.   time_out.tv_usec = TIME_OUT;   
  286.      
  287.   int ret = 0;   
  288.      
  289.   while( 1 )   
  290.   {   
  291.   FD_ZERO( &fd_read );   
  292.   FD_SET( sock, &fd_read );   
  293.   FD_SET( real_server_sock, &fd_read );   
  294.   ret = select( (sock >real_server_sock ? sock : real_server_sock) + 1, &fd_read, NULL, NULL, &time_out );   
  295.   if( -1 == ret )   
  296.   {   
  297.   perror( "select socket error" );   
  298.   break;   
  299.   }   
  300.   else if( 0 == ret )   
  301.   {   
  302.   //perror( "select time out" );   
  303.   continue;   
  304.   }   
  305.      
  306.   //printf( "[DEBUG] testing readable!\n" );   
  307.   if( FD_ISSET(sock, &fd_read) )   
  308.   {   
  309.   //printf( "client can read!\n" );   
  310.   memset( recv_buffer, 0, BUFF_SIZE );   
  311.   ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );   
  312.   if( ret >0 )   
  313.   {   
  314.   //printf( "%s", recv_buffer );   
  315.   //printf( "recv %d bytes from client.\n", ret );   
  316.   ret = send( real_server_sock, recv_buffer, ret, 0 );   
  317.   if( ret == -1 )   
  318.   {   
  319.   perror( "send data to real server error" );   
  320.   break;   
  321.   }   
  322.   //printf( "send %d bytes to client!\n", ret );   
  323.   }   
  324.   else if( ret == 0 )   
  325.   {   
  326.   //printf( "client close socket.\n" );   
  327.   break;   
  328.   }   
  329.   else   
  330.   {   
  331.   //perror( "recv from client error" );   
  332.   break;   
  333.   }   
  334.   }   
  335.      
  336.   else if( FD_ISSET(real_server_sock, &fd_read) )   
  337.   {   
  338.   //printf( "real server can read!\n" );   
  339.   memset( recv_buffer, 0, BUFF_SIZE );   
  340.   ret = recv( real_server_sock, recv_buffer, BUFF_SIZE, 0 );   
  341.   if( ret >0 )   
  342.   {   
  343.   //printf( "%s", recv_buffer );   
  344.   //printf( "recv %d bytes from real server.\n", ret );   
  345.   ret = send( sock, recv_buffer, ret, 0 );   
  346.   if( ret == -1 )   
  347.   {   
  348.   perror( "send data to client error" );   
  349.   break;   
  350.   }   
  351.   }   
  352.   else if( ret == 0 )   
  353.   {   
  354.   //printf( "real server close socket.\n" );   
  355.   break;   
  356.   }   
  357.   else   
  358.   {   
  359.   perror( "recv from real server error" );   
  360.   break;   
  361.   }   
  362.   }   
  363.   }   
  364.      
  365.   return 0;   
  366.   }   
  367.   int Socks5( void *client_sock )   
  368.   {   
  369.   int sock = *(int *)client_sock;   
  370.   if( SelectMethod( sock ) == -1 )   
  371.   {   
  372.   //printf( "socks version error\n" );   
  373.   return -1;   
  374.   }   
  375.      
  376.   if( AuthPassword( sock ) == -1 )   
  377.   {   
  378.   //printf( "auth password error\n" );   
  379.   return -1;   
  380.   }   
  381.      
  382.   int real_server_sock = ParseCommand( sock );   
  383.   if( real_server_sock == -1 )   
  384.   {   
  385.   //printf( "parse command error.\n" );   
  386.   return -1;   
  387.   }   
  388.      
  389.   ForwardData( sock, real_server_sock );   
  390.   close( sock );   
  391.   close( real_server_sock );   
  392.      
  393.   return 0;   
  394.   }   
  395.   int main( int argc, char *argv[] )   
  396.   {   
  397.   if( argc != 2 )   
  398.   {   
  399.   printf( "Socks5 proxy for test,code by YunShu\n" );   
  400.   printf( "Usage: %s \n", argv[0] );   
  401.   printf( "Options:\n" );   
  402.   printf( " ---which port of this proxy server will listen.\n" );   
  403.      
  404.   return 1;   
  405.   }   
  406.   struct sockaddr_in sin;   
  407.   memset( (void *)&sin, 0, sizeofstruct sockaddr_in) );   
  408.   sin.sin_family = AF_INET;   
  409.   sin.sin_port = htons( atoi(argv[1]) );   
  410.   sin.sin_addr.s_addr = htonl(INADDR_ANY);   
  411.   int listen_sock = socket( AF_INET, SOCK_STREAM, 0 );   
  412.   if( listen_sock <0 )   
  413.   {   
  414.   perror( "Socket creation failed\n");   
  415.   return -1;   
  416.   }   
  417.   int opt = SO_REUSEADDR;   
  418.   setsockopt( listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt) );   
  419.   if( bind( listen_sock, (struct sockaddr*)&sin, sizeof(struct sockaddr_in) ) <0 )   
  420.   {   
  421.   perror( "Bind error" );   
  422.   return -1;   
  423.   }   
  424.   if( listen( listen_sock, MAX_USER ) <0 )   
  425.   {   
  426.   perror( "Listen error" );   
  427.   return -1;   
  428.   }   
  429.   struct sockaddr_in cin;   
  430.   int client_sock;   
  431.   int client_len = sizeofstruct sockaddr_in );   
  432.   while( client_sock = accept( listen_sock, (struct sockaddr *)&cin, (socklen_t *)&client_len ) )   
  433.   {   
  434.   printf( "Connected from %s, processing......\n", inet_ntoa( cin.sin_addr ) );   
  435.   pthread_t work_thread;   
  436.   if( pthread_create( &work_thread, NULL, (void *)Socks5, (void *)&client_sock ) )   
  437.   {   
  438.   perror( "Create thread error..." );   
  439.   close( client_sock );   
  440.   }   
  441.   else   
  442.   {   
  443.   pthread_detach( work_thread );   
  444.   }   
  445.   }   
  446.   }   

 

你可能感兴趣的:(linux,代理,职场,平台,休闲)