`
asdf314159265
  • 浏览: 246233 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

C语言写的linux socks Proxy

 
阅读更多
C语言写的Linux平台socks5代理程序

信息来源:邪恶八进制信息安全团队(www.eviloctal.com)

前几天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\n", 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\n", 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\npassword: %s\n", 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
{
return 0;
}
}
else
{
auth_response->result = 0x01;
send( sock, auth_response, sizeof(AUTH_RESPONSE), 0 );

close( sock );
return -1;
}
}

// parse command, and try to connect real server.
// return socket for success, -1 for failed.
int ParseCommand( int sock )
{
char recv_buffer[BUFF_SIZE] = { 0 };
char reply_buffer[BUFF_SIZE] = { 0 };

SOCKS5_REQUEST *socks5_request;
SOCKS5_RESPONSE *socks5_response;

// recv command
int ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
if( ret <= 0 )
{
perror( "recv connect command error" );

close( sock );
return -1;
}

socks5_request = (SOCKS5_REQUEST *)recv_buffer;
if( (socks5_request->version != VERSION) || (socks5_request->cmd != CONNECT) ||
(socks5_request->address_type == IPV6) )
{
//printf( "connect command error.\n" );
close( sock );
return -1;
}

// begain process connect request
struct sockaddr_in sin;

memset( (void *)&sin, 0, sizeof(struct sockaddr_in) );
sin.sin_family = AF_INET;

// get real server&#39;s ip address
if( socks5_request->address_type == IPV4 )
{
memcpy( &sin.sin_addr.s_addr, &socks5_request->address_type + sizeof(socks5_request->address_type) , 4 );
memcpy( &sin.sin_port, &socks5_request->address_type + sizeof(socks5_request->address_type) + 4, 2 );

//printf( "Real Server: %s %d\n", inet_ntoa( sin.sin_addr ), ntohs( sin.sin_port ) );
}
else if( socks5_request->address_type == DOMAIN )
{
char domain_length = *(&socks5_request->address_type + sizeof(socks5_request->address_type));
char target_domain[ 256] = { 0 };

strncpy( target_domain, &socks5_request->address_type + 2, (unsigned int)domain_length );

//printf( "target: %s\n", target_domain );

struct hostent *phost = gethostbyname( target_domain );
if( phost == NULL )
{
//printf( "Resolve %s error!\n" , target_domain );

close( sock );
return -1;
}
memcpy( &sin.sin_addr , phost->h_addr_list[0] , phost->h_length );

memcpy( &sin.sin_port, &socks5_request->address_type + sizeof(socks5_request->address_type) +
sizeof(domain_length) + domain_length, 2 );
}

// try to connect to real server
int real_server_sock = socket( AF_INET, SOCK_STREAM, 0 );
if( real_server_sock < 0 )
{
perror( "Socket creation failed\n");

close( sock );
return -1;
}

memset( reply_buffer, 0, sizeof(BUFF_SIZE) );

socks5_response = (SOCKS5_RESPONSE *)reply_buffer;

socks5_response->version = VERSION;
socks5_response->reserved = 0x00;
socks5_response->address_type = 0x01;
memset( socks5_response + 4, 0 , 6 );

ret = connect( real_server_sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in) );
if( ret == 0 )
{
socks5_response->reply = 0x00;
if( -1 == send( sock, socks5_response, 10, 0 ) )
{
close( sock );

return -1;
}
}
else
{
perror( "Connect to real server error" );
socks5_response->reply = 0x01;
send( sock, socks5_response, 10, 0 );

close( sock );
return -1;
}

return real_server_sock;
}

int ForwardData( int sock, int real_server_sock )
{
char recv_buffer[BUFF_SIZE] = { 0 };

fd_set fd_read;
struct timeval time_out;

time_out.tv_sec = 0;
time_out.tv_usec = TIME_OUT;

int ret = 0;

while( 1 )
{
FD_ZERO( &fd_read );
FD_SET( sock, &fd_read );
FD_SET( real_server_sock, &fd_read );

ret = select( (sock > real_server_sock ? sock : real_server_sock) + 1, &fd_read, NULL, NULL, &time_out );
if( -1 == ret )
{
perror( "select socket error" );
break;
}
else if( 0 == ret )
{
//perror( "select time out" );
continue;
}

//printf( "[DEBUG] testing readable!\n" );
if( FD_ISSET(sock, &fd_read) )
{
//printf( "client can read!\n" );
memset( recv_buffer, 0, BUFF_SIZE );
ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );
if( ret > 0 )
{
//printf( "%s", recv_buffer );
//printf( "recv %d bytes from client.\n", ret );
ret = send( real_server_sock, recv_buffer, ret, 0 );
if( ret == -1 )
{
perror( "send data to real server error" );
break;
}
//printf( "send %d bytes to client!\n", ret );
}
else if( ret == 0 )
{
//printf( "client close socket.\n" );
break;
}
else
{
//perror( "recv from client error" );
break;
}
}

else if( FD_ISSET(real_server_sock, &fd_read) )
{
//printf( "real server can read!\n" );
memset( recv_buffer, 0, BUFF_SIZE );
ret = recv( real_server_sock, recv_buffer, BUFF_SIZE, 0 );
if( ret > 0 )
{
//printf( "%s", recv_buffer );
//printf( "recv %d bytes from real server.\n", ret );
ret = send( sock, recv_buffer, ret, 0 );
if( ret == -1 )
{
perror( "send data to client error" );
break;
}
}
else if( ret == 0 )
{
//printf( "real server close socket.\n" );
break;
}
else
{
perror( "recv from real server error" );
break;
}
}
}

return 0;
}

int Socks5( void *client_sock )
{
int sock = *(int *)client_sock;

if( SelectMethod( sock ) == -1 )
{
//printf( "socks version error\n" );
return -1;
}

if( AuthPassword( sock ) == -1 )
{
//printf( "auth password error\n" );
return -1;
}

int real_server_sock = ParseCommand( sock );
if( real_server_sock == -1 )
{
//printf( "parse command error.\n" );
return -1;
}

ForwardData( sock, real_server_sock );

close( sock );
close( real_server_sock );

return 0;
}

int main( int argc, char *argv[] )
{
if( argc != 2 )
{
printf( "Socks5 proxy for test,code by YunShu\n" );
printf( "Usage: %s <proxy_port>\n", argv[0] );
printf( "Options:\n" );
printf( " <proxy_port> ---which port of this proxy server will listen.\n" );

return 1;
}

struct sockaddr_in sin;

memset( (void *)&sin, 0, sizeof( struct sockaddr_in) );
sin.sin_family = AF_INET;
sin.sin_port = htons( atoi(argv[1]) );
sin.sin_addr.s_addr = htonl(INADDR_ANY);

int listen_sock = socket( AF_INET, SOCK_STREAM, 0 );
if( listen_sock < 0 )
{
perror( "Socket creation failed\n");
return -1;
}

int opt = SO_REUSEADDR;
setsockopt( listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt) );

if( bind( listen_sock, (struct sockaddr*)&sin, sizeof(struct sockaddr_in) ) < 0 )
{
perror( "Bind error" );
return -1;
}

if( listen( listen_sock, MAX_USER ) < 0 )
{
perror( "Listen error" );
return -1;
}

struct sockaddr_in cin;
int client_sock;
int client_len = sizeof( struct sockaddr_in );

while( client_sock = accept( listen_sock, (struct sockaddr *)&cin, (socklen_t *)&client_len ) )
{
printf( "Connected from %s, processing......\n", inet_ntoa( cin.sin_addr ) );

pthread_t work_thread;
if( pthread_create( &work_thread, NULL, (void *)Socks5, (void *)&client_sock ) )
{
perror( "Create thread error..." );
close( client_sock );
}
else
{
pthread_detach( work_thread );
}
}
}
分享到:
评论

相关推荐

    Socks Proxy 源代码

    《C#实现Socks Proxy详解》 在计算机网络领域,代理服务器是一种常见的工具,它作为客户端与目标服务器之间的中介,可以提供多种网络服务,如负载均衡、匿名访问、网络安全等。其中,Socks Proxy(SOCKS协议)是一...

    socks proxy checker 1.14

    好用, 能够查询网上复制的sock 5地址和端口是否有效。

    socks5proxyclient-master_socks框架代码_socks5proxies下载_socks5proxy_f

    另一个代理客户端源码,基于c#,.net框架,代码相交简单。比较实用

    socksproxy

    命令行下的开socks5代理服务器的软件,没有windows界面,可以添加到服务里,设置成自动启动。用法: Run with paramater below list: -Install (Install the service) -Remove (Remove the service) ...

    IOS应用源码之【应用】-SOCKS Proxy for iPhone.rar

    【标题】"IOS应用源码之【应用】-SOCKS Proxy for iPhone.rar" 提供的是一个关于iOS平台上实现SOCKS代理的源代码。这个源码库专注于为iPhone设备构建一个SOCKS代理服务,这在进行网络调试、安全测试或者需要绕过特定...

    socks proxy for tomato

    Tomato无线路由的socks代理服务程序

    SocksProxy代理服务器

    c#编写的socks代理服务器 支持sock4 sock4a sock5 sock5支持tcp和udp sock5支持匿名模式和用户名密码验证模式 运行需.net framework 2.0 http://blog.csdn.net/laotse/archive/2011/04/07/6306767.aspx

    【应用】-SOCKS Proxy for iPhone.7z

    【应用】-SOCKS Proxy for iPhone 是一个针对iOS设备的源代码项目,它涉及到网络通信中的SOCKS代理协议。SOCKS(Socket Secure)代理是一种通用的网络传输协议,允许应用程序通过代理服务器与任意IP协议进行通信,...

    Linux socks 5代理软件

    Linux socks 5代理软件 dante socks5 server http://blogold.chinaunix.net/u/89/showart_1073546.html(安装方法)

    SS5 Linux 下开源的 Socket5 代理软件

    socks_port = 1080 ``` 为了确保安全性,通常会启用用户认证,添加用户名和密码: ``` user = user1:password1 user = user2:password2 ``` 配置完成后,需要重启SS5服务以应用新的设置: ``` sudo service ss5 ...

    Invoke-SocksProxy:使用Powershell的袜子代理和反向袜子服务器

    例子当地的在端口1080上创建Socks 4/5代理: Import-Module .\Invoke-SocksProxy.psm1Invoke-SocksProxy -bindPort 1080将最大线程数从200增加到400 Import-Module .\Invoke-SocksProxy.psm1Invoke-SocksProxy -...

    基于Linux平台的SOCKS5代理服务器.pdf

    基于Linux平台的SOCKS5代理服务器.pdf

    Node.js-hpts(http-proxy-to-socks)一个nodejs客户端将socks代理转换为http代理

    hpts(http-proxy-to-socks) 一个nodejs客户端将socks代理转换为http代理

    SocksProxy

    ,一个多功能Windows代理服务器的程序。这个程序支持HTTP、HTTPS、Telnet、Socks V4 V5。

    基于C语言的透明代理到Socks5代理转接器设计源码

    该项目为基于C语言的透明代理到Socks5代理转接器设计源码,包含91个文件,包括18个C语言源文件、17个头文件、9个文本文件、6个配置文件、3个Python脚本、2个PNG图片文件、2个密码文件、1个Git忽略文件、1个YAML文件...

    SocksOnline v3.0 beta1.zip

    现在,你可以使用Socks Online这个软件,就可以将HTTP Proxy或其他的Proxy变成Socks Proxy!而且该软件完全免费,而且支持Windows 95/98/NT/2000操作系统,而且使用非常简单,几乎不需要任何的设置即可使用。新版...

    socks5-proxy:socks5代理

    【标题】:Socks5代理服务的Netty实现 【描述】:Socks5代理是一种网络通信协议,它允许客户端通过代理服务器与任意其他网络服务进行通信。在本项目中,我们将关注Netty框架实现的Socks5代理服务。Netty是一个高...

    simple-proxy-agent:通过HTTP和SOCKS代理发送HTTP和HTTPS流量的简单代理

    通过HTTP和SOCKS代理的HTTP和HTTPS的简单代理 目录 安装 npm install simple-proxy-agent 用法 代理请求 const fetch = require ( 'node-fetch' ) ; const ProxyAgent = require ( 'simple-proxy-agent' ) ; fetch ...

    socks5 c#简单代理源码

    本文将深入探讨C#编程语言实现SOCKS5代理协议的基础知识。 SOCKS5是一种广泛使用的互联网协议,用于在客户端和目标服务器之间建立安全的隧道,以实现代理服务。它支持多种网络协议,如TCP和UDP,同时提供了身份验证...

Global site tag (gtag.js) - Google Analytics