当前位置:编程学习 > 网站相关 >>

Linux平台socks5代理

by 云舒
2008-1-25
http://www.ph4nt0m.org

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

这是头文件:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Socks5代理头文件,定义协议相关数据包结构
// 版本 0.1,作者 云舒
// 2007年1月9日凌晨1点15分,GF回家已经11天了。
// 2008年1月25日修改,今年GF一直在我身边,哈哈
//
// 参考:
// http://www.rfc-editor.org/rfc/rfc1928.txt
// http://www.rfc-editor.org/rfc/rfc1929.txt
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef SOCKS5_H
#define SOCKS5_H

#define VERSION 0x05
#define CONNECT 0x01
#define IPV4 0x01
#define DOMAIN 0x03
#define IPV6 0x04

typedef struct _method_select_response // 协商方法服务器响应
{
 char version; // 服务器支持的Socks版本,0x04或者0x05
 char select_method;// 服务器选择的方法,0x00为匿名,0x02为密码认证
} METHOD_SELECT_RESPONSE;

typedef struct _method_select_request // 协商方法服务端请求
{
 char version; // 客户端支持的版本,0x04或者0x05
 char number_methods; // 客户端支持的方法的数量
 char methods[255]; // 客户端支持的方法类型,最多255个,0x00为匿名,0x02为密码认证
} METHOD_SELECT_REQUEST;

typedef struct _AUTH_RESPONSE // 用户密码认证服务端响应
{
 char version;// 版本,此处恒定为0x01
 char result;// 服务端认证结果,0x00为成功,其他均为失败
} AUTH_RESPONSE;

typedef struct _AUTH_REQUEST //用户密码认证客户端请求
{
 char version; // 版本,此处恒定为0x01
 char name_len; // 第三个字段用户名的长度,一个字节,最长为0xff
 char name[255]; // 用户名
 char pwd_len;// 第四个字段密码的长度,一个字节,最长为0xff
 char pwd[255]; // 密码
} AUTH_REQUEST;

typedef struct _SOCKS5_RESPONSE // 连接真实主机,Socks代理服务器响应
{
 char version; // 服务器支持的Socks版本,0x04或者0x05
 char reply; // 代理服务器连接真实主机的结果,0x00成功
 char reserved; // 保留位,恒定位0x00
 char address_type; // Socks代理服务器绑定的地址类型,IP V4为0x01,IP V6为0x04,域名为0x03 
 char address_port[1]; // 如果address_type为域名,此处第一字节为域名长度,其后为域名本身,无0字符结尾,域名后为Socks代理服务器绑定端口
}SOCKS5_RESPONSE; 

typedef struct _SOCKS5_REQUEST // 客户端请求连接真实主机
{
 char version; // 客户端支持的Socks版本,0x04或者0x05
 char cmd; // 客户端命令,CONNECT为0x01,BIND为0x02,UDP为0x03,一般为0x01
 char reserved; // 保留位,恒定位0x00
 char address_type; // 客户端请求的真实主机的地址类型,IP V4为0x00,IP V6为0x04,域名为 0x03 char address_port[1]; // 如果address_type为域名,此处第一字节为域名长度,其后为域名本身,无0字符结尾,域名后为真实主机绑定端口

}SOCKS5_REQUEST; 
#endif 

主程序来了: 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Socks5程序,只支持TCP代理
// 版本 0.1,作者 云舒
// 2007年1月9日凌晨1点15分,GF回家已经11天了。
// 2008年1月25日修改,今年GF一直在我身边,哈哈
//
// 参考:
// http://www.rfc-editor.org/rfc/rfc1928.txt
// http://www.rfc-editor.org/rfc/rfc1929.txt
//编译:
// gcc -o socks5 -O2 Socks5.c -lpthread( RedHat AS5测试 )
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#include "Socks5.h"

#define MAX_USER 10
#define BUFF_SIZE 1024

#define AUTH_CODE 0x02

#define TIME_OUT 6000000

#define USER_NAME "yunshu"
#define PASS_WORD "ph4nt0m"

// Select auth method, return 0 if success, -1 if failed
int SelectMethod( int sock )
{
 char recv_buffer[BUFF_SIZE] = { 0 };
 char reply_buffer[2] = { 0 };

 METHOD_SELECT_REQUEST *method_request;
 METHOD_SELECT_RESPONSE *method_response;
 
 // recv METHOD_SELECT_REQUEST
 int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
 if( ret <= 0 )
 {
 perror( "recv error" );
 close( sock );

 return -1;
 }

//printf( "SelectMethod: recv %d bytes ", ret );

 // if client request a wrong version or a wrong number_method
 method_request = (METHOD_SELECT_REQUEST *)recv_buffer;
 method_response = (METHOD_SELECT_RESPONSE *)reply_buffer;

 method_response->version = VERSION;
 
 // if not socks5
 if( (int)method_request->version != VERSION )
 {
 method_response->select_method = 0xff;

 send( sock, method_response, sizeof(METHOD_SELECT_RESPONSE), 0 );
 close( sock );
 
 return -1;
 }

 method_response->select_method = AUTH_CODE;
 if( -1 == send( sock, method_response, sizeof(METHOD_SELECT_RESPONSE), 0 ) )
 {
 close( sock );
 return -1;
 }
 
 return 0;
}

// test password, return 0 for success.
int AuthPassword( int sock )
{
 char recv_buffer[BUFF_SIZE] = { 0 };
 char reply_buffer[BUFF_SIZE] = { 0 };

 AUTH_REQUEST *auth_request;
 AUTH_RESPONSE *auth_response;
 
 // auth username and password
 int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
 if( ret <= 0 )
 {
 perror( "recv username and password error" );
 close( sock );
 return -1;
 }
 //printf( "AuthPass: recv %d bytes ", ret );

 auth_request = (AUTH_REQUEST *)recv_buffer;

 memset( reply_buffer, 0, BUFF_SIZE );
 auth_response = (AUTH_RESPONSE *)reply_buffer;
 auth_response->version = 0x01;

 char recv_name[256] = { 0 };
 char recv_pass[256] = { 0 };

 // auth_request->name_len is a char, max number is 0xff
 char pwd_str[2] = { 0 };
 strncpy( pwd_str, auth_request->name + auth_request->name_len, 1 );
 int pwd_len = (int)pwd_str[0];

 strncpy( recv_name, auth_request->name, auth_request->name_len );
 strncpy( recv_pass, auth_request->name + auth_request->name_len + sizeof(auth_request->pwd_len), pwd_len );

 //printf( "username: %s password: %s ", recv_name, recv_pass );
 // check username and password
 if( (strncmp( recv_name, USER_NAME, strlen(USER_NAME) ) == 0) &&
 (strncmp( recv_pass, PASS_WORD, strlen(PASS_WORD) ) == 0)
 )
 {
 auth_response->result = 0x00;
 if( -1 == send( sock, auth_response, sizeof(AUTH_RESPONSE), 0 ) )
 {
 close( sock );
 return -1;
 }
 else

补充:综合编程 , 安全编程 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,