写一个简易的socks5代理服务器,负责转发网络数据包,要能够使用它来上网。

SOCKS5 是一个代理协议,它在使用TCP/IP协议通讯的前端机器和服务器机器之间扮演一个中介角色,使得内部网中的前端机器变得能够访问Internet网中的服务器,或者使通讯更加安全。SOCKS5 服务器通过将前端发来的请求转发给真正的目标服务器, 模拟了一个前端的行为。在这里,前端和SOCKS5之间也是通过TCP/IP协议进行通讯,前端将原本要发送给真正服务器的请求发送给SOCKS5服务器,然后SOCKS5服务器将请求转发给真正的服务器。

socks5协议认证步骤:

1、客户端连接到服务器,向服务器发送一个版本标识/方法选择报文:

+-------+------------------+----------------+

|  VER | NMETHODS | METHODS |

+-------+------------------+----------------+

|     1    |          1          |     1~255     |

+-------+------------------+----------------+

VER:客户端的协议版本号(socks5:0x05 socks4:0x04)

NMETHODS:客户端所支持认证方式的长度

METHODS:客户端支持的认证方式

目前定义的METHOD有以下几种:
  0x00  无需认证
  0x01  通用安全服务应用程序
  0x02  用户名/密码
  0x03- 0x7F IANA 分配
  0x80- 0xFE 私人方法保留
  0xFF  无可接受方法

2、服务器从客户端报文中选择一种方式,并发送一个方式选择报文:

+----+----------+
    |VER | METHOD |
    +----+----------+
    | 1  |   1    |
    +----+----------+

VER:服务端的协议版本号(socks5:0x05 socks4:0x04)

METHOD:服务端选择的认证方式

3、客户端向服务器发送连接目的服务器的请求报文:

+----+-----+-------+------+------------+----------+
    |VER | CMD|   RSV | ATYP | DST.ADDR | DST.PORT |
    +----+-----+-------+------+------------+----------+
    | 1   |   1  |   1   |   1   | Variable |    2     |
    +----+-----+-------+------+------------+----------+

VER:客户端协议版本号(socks5:0x05 socks4:0x04)

CMD:请求类型(CONNECT:0x00 BIND:0x01 UDP:0x02)

RSV:保留位(要求为0x00)

ATYP:IP类型(IPV4:0x01 IPV6:0X04 域名:0x03)

DST.ADDR:目的服务器地址

DST.ADDR:目的服务器端口

4、服务器向客户端回应连接请求

+----+-----+-------+------+-------------+-----------+
    |VER | REP |   RSV  | ATYP | BND.ADDR | BND.PORT |
    +----+-----+-------+------+-------------+-----------+
    | 1  |   1   |   1   |   1   | Variable |    2     |
    +----+-----+-------+------+----------+--------------+

VER:服务端协议版本号(socks5:0x05 socks4:0x04)

REP:应答结果

1. 0x00        成功
      2. 0x01        一般性失败
      3. 0x02        规则不允许转发
      4. 0x03        网络不可达
      5. 0x04        主机不可达
      6. 0x05        连接拒绝
      7. 0x06        TTL超时
      8. 0x07        不支持请求包中的CMD
      9. 0x08        不支持请求包中的ATYP
      10. 0x09-0xFF   未定义

RSV:保留位(要求为0x00)

ATYP:指明后面的地址类型

BND.ADDR:客户端请求报文中CMD的回应地址(CMD为0x01时)

BND.PORT:客户端请求报文中CMD的回应端口(CMD为0x01时)

程序主要步骤:

第一步:建立客户端和代理服务器连接,TCP连接

第二步:socks5协议认证

第三步:代理服务器连接目的服务器

第四步:转发数据

代码

#include <unistd.h>
#include <arpa/inet.h> //因特网地址结构体相关
#include <sys/socket.h> //socket相关
#include <time.h>  //时间相关
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/epoll.h>#define BUFF_SIZE 1024   //设置转发缓冲区
#define TIME_OUT 6000000 //设置复用IO延时
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*///++++++++++++     sock5协议结构体定义     ++++++++++++++/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*
一、客户端认证请求+----+----------+----------+|VER | NMETHODS | METHODS  |+----+----------+----------+| 1  |    1     |  1~255   |+----+----------+----------+二、服务端回应认证+----+--------+|VER | METHOD |+----+--------+| 1  |   1    |+----+--------+三、客户端连接请求(连接目的网络)+----+-----+-------+------+----------+----------+|VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |+----+-----+-------+------+----------+----------+| 1  |  1  |   1   |  1   | Variable |    2     |+----+-----+-------+------+----------+----------+四、服务端回应连接+----+-----+-------+------+----------+----------+|VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |+----+-----+-------+------+----------+----------+| 1  |  1  |   1   |  1   | Variable |    2     |+----+-----+-------+------+----------+----------+*///以下为协议结构体定义//一、客户端认证请求
typedef struct client_license_request{char ver;       // 客户端的协议版本号  0x05:socks5 0x04:socks4char nmethods;    // 客户端所支持认证方式的长度char methods[255];  //客户端支持的认证方式(可以有255种)}client_license_request;//二、服务端回应认证
typedef struct server_license_response{char ver;     // 服务端的协议版本号char method;  //服务端选择的认证方式
}server_license_response;//三、客户端连接请求
typedef struct client_connect_request{char ver;    //客户端协议版本号char cmd;    //连接方式char rsv;    //保留位0x00char type;   //类型char addr[4]; //目的服务器ipchar port[2]; //目的服务器端口}client_connect_request;//四、服务端回应连接
typedef struct server_connect_response{char ver; //版本char rep; //连接状态char rsv; //保留0x00char type; //类型char addr[4]; //bind ipchar port[2]; //bind port}server_connect_response;int socketfd_tcp;  //TCP监听套接字//转发
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;printf("线程%u-开始进行数据转发\n",(int)pthread_self());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 ){break;}else if( 0 == ret ){continue;}if( FD_ISSET(sock, &fd_read) ){memset( recv_buffer, 0, BUFF_SIZE );ret = recv( sock, recv_buffer, BUFF_SIZE, 0 );if( ret >0 ){ret = send( real_server_sock, recv_buffer, ret, 0 );if( ret == -1 ){break;}}else if( ret == 0 ){break;}else{break;}}else if( FD_ISSET(real_server_sock, &fd_read) ){memset(recv_buffer,0,BUFF_SIZE );ret = recv( real_server_sock, recv_buffer, BUFF_SIZE, 0 );if( ret > 0 ){ret = send( sock, recv_buffer, ret, 0 );if( ret == -1 ){break;}}else if(ret==0){break;}else{break;}}}return 0;
}//创建TCP套接字
void tcp_creat()
{socketfd_tcp=socket(AF_INET,SOCK_STREAM,0);if(socketfd_tcp==-1){perror("socketfd_tcp");exit(-1);}struct sockaddr_in addr_tcp;bzero(&addr_tcp,sizeof(addr_tcp));addr_tcp.sin_family=AF_INET;addr_tcp.sin_port=htons(2018);addr_tcp.sin_addr.s_addr=INADDR_ANY;int re=bind(socketfd_tcp,(struct sockaddr *)&addr_tcp,sizeof(addr_tcp));if(re==-1){perror("bind");exit(-1);}re=listen(socketfd_tcp,100);  //队列长度设为100if(re==-1){perror("listen");exit(-1);}}//代理服务器连接目的服务器
int connect_dest_server(client_connect_request * connect_request)
{int fd=socket(AF_INET,SOCK_STREAM,0);if(fd==-1){perror("socketfd_tcp");return -1;}struct sockaddr_in sin_server;bzero(&sin_server,sizeof(sin_server));sin_server.sin_family=AF_INET;//目的服务器ip填入结构体memcpy(&sin_server.sin_addr,&connect_request->addr,sizeof(connect_request->addr));//目的服务器的端口号填入结构体memcpy(&sin_server.sin_port,&connect_request->port,sizeof(connect_request->port));/*2 连接服务器*/int re=connect(fd,(struct sockaddr *)&sin_server,sizeof(sin_server));if(re==-1){// printf("目的服务器连接失败\n");return -1;}// printf("目的服务器连接成功\n");return fd;
}//socks5认证连接
int sock5_license(struct sockaddr_in *addr_client,socklen_t len,int fd)
{//接收认证信息char buffer[30]={0};read(fd,buffer,sizeof(buffer));client_license_request * license_request=(client_license_request *)buffer; //验证认证信息// printf("客户端版本%d\n",license_request->ver);if(license_request->ver!=0x5){// printf("协议版本错误\n");return 0;}// printf("客户认证信息通过,回应认证请求\n");server_license_response license_response;license_response.ver=0x5;license_response.method=0x0;char buff[2]={0};memcpy(buff,&license_response,sizeof(buff));//回应认证信息write(fd,buff,sizeof(buff));// printf("已发送回应请求\n");//接收连接请求bzero(&buffer,sizeof(buffer));// printf("等待接收客户连接请求\n");read(fd,buffer,sizeof(buffer));client_connect_request * connect_request=(client_connect_request *)buffer; //认证连接请求if(connect_request->ver!=0x5){// printf("连接请求协议版本错误\n");return 0;}if(connect_request->cmd!=0x1){// printf("连接请求命令错误(非TCP)\n");return 0;}if(connect_request->type!=0x01){// printf("连接请求类型错误(非IPV4)\n");return 0;}//连接客户端指定的目的地址int dest_fd=connect_dest_server(connect_request);if(dest_fd==-1){return -1;}//成功连接则发送回应信息//回应连接信息char buffer1[10]={0};bzero(&buffer,sizeof(buffer1));server_connect_response connect_response;bzero(&connect_response,sizeof(connect_response));connect_response.ver=0x5;connect_response.rep=0x00;  //连接成功标志connect_response.rsv=0x00;connect_response.type=0x01;memcpy(buffer1,&connect_response,sizeof(connect_response));//服务端回应数据 设置版本号与结果位,ip与端口号未使用write(fd,buffer1,sizeof(buffer1));// printf("已发送回应请求\n");//全部认证连接建立完成//执行转发程序ForwardData(fd,dest_fd);}//等待TCP连接,每个客户端分出一条线程,跳转执行socks5认证函数↑↑↑
void * pthread_tcp(void * arg)
{printf("线程%u-正在运行\n",(int)pthread_self());struct sockaddr_in addr_client;socklen_t len=sizeof(addr_client);bzero(&addr_client,sizeof(addr_client));int fd=accept(socketfd_tcp,(struct sockaddr *)&addr_client,&len);pthread_t  pid2;pthread_create(&pid2,NULL,pthread_tcp,NULL);//打印客户端信息char ip[20]={0};unsigned short port;inet_ntop(AF_INET,&addr_client.sin_addr,ip,len);port=ntohs(addr_client.sin_port); //转换为本机字节序printf("%s:%hu已连接\n",ip,port);//执行socks5认证sock5_license(&addr_client,len,fd);printf("线程%u-退出\n",(int)pthread_self());return NULL;}int main(void)
{//创建TCP套接字tcp_creat();printf("初始化完成等待连接\n");while(1){printf("主线程%u-正在运行\n",(int)pthread_self());pthread_tcp(NULL);}}

使用socks5实现简易代理服务器相关推荐

  1. 腾讯云搭建Socks5一系列及相关内容

    腾讯云搭建Socks5多IP代理服务器实现游戏单窗口单IP 腾讯云多IP Socks5搭建教程 配合代理工具实现 单窗口单IP 1.多IP服务器选择 2.服务器购买 3.创建弹性网卡,绑定弹性公网IP ...

  2. redsocks+iptables+socks5服务商

    前言 为了防止代收邮件服务被加入邮件服务商的黑名单,而导致代收失败,将代收服务不定时的更换ip出口. 代理厂商 要想实现多Ip出口,只能购买代理厂商的资源.其中又分为国内厂商与国外厂商.国外厂商支持的 ...

  3. 单窗口单IP,驱动级socks5,socks5驱动,模拟器不同IP,每个进程不同IP,局部及全局代理实现方案!

    在国内玩国外的游戏或者电信与网通移动这些网络通信,大家应该都遇到一种情况,就是网速好卡是吧,我们今天就是来解决这类问题的. 这是因为两端网络不同,传输距离过远,路由过滤等因素. 为了游戏或者不同网络环 ...

  4. ProxyChains

    proxychains-ng:https://github.com/rofl0r/proxychains-ng proxychains:https://github.com/haad/proxycha ...

  5. PhantomJS命令行选项

    支持命令行选项有: --help或-h列出所有可能的命令行选项.立即停止,不会运行一个脚本作为参数传递. --version或-v打印的版本PhantomJS.立即停止,不会运行一个脚本作为参数传递. ...

  6. 转:为 setuptools 开路搭桥

    为 setuptools 开路搭桥 赖勇浩(http://laiyonghao.com) 在 这里,我们有些网站无法访问.其中对我影响比较大的一个就是安装某些 Python 模块的时候,easy_in ...

  7. LSP技术 注入技术 劫持

    链接 https://www.cnblogs.com/freesec/p/6541725.html https://blog.csdn.net/sspdfn/article/details/86520 ...

  8. 为 setuptools 开路搭桥

    赖勇浩(http://laiyonghao.com) 关键字:python, easy_install, setuptools, Bitvise Tunnelier, polipo, windows, ...

  9. 394计算机毕业设计

    ASP.NET基于BS结构的工厂设备管理系统的设计与开发(开题报告,毕业论文,程序,源码).rar http://dl.vmall.com/c07ibk51r0 一种远程管理Linux系统工具(程序, ...

最新文章

  1. 安装MySQLdb for Python3.7
  2. CentOS7.2基于LNMP搭建Wordpress
  3. linux设备模型,bus,device,driver,实验遇到的问题
  4. 手机打开python文件_使用python在计算机和手机之间通过wifi进行简单的文件传输...
  5. 为什么我喜欢Spring bean别名
  6. Metapath2vec:Scalable Representation Learning for Heterogeneous Networks(结构化深度网络特征表示)
  7. 软件工程—个人作业(8)
  8. 电脑联网了但不能上网_电脑联网不能用,求助
  9. Android 4.0 ICS SystemUI浅析——StatusBar加载流程分析
  10. pandas 字符串切片后保存_我擦~字符串转字节切片后,切片的容量竟然千奇百怪...
  11. HDU 6044 Limited Permutation 读入挂+组合数学
  12. 这世上最快的捷径就是脚踏实地
  13. python 获取网页元素_记一次python提取网页标签元素的坑
  14. Nagios监控Linux主机
  15. PDF图形(PDF graphics)
  16. 最新新游社iApp源码+后台对接的hybbs内核
  17. java基于ssm的农产品网上销售系统
  18. 十次方:机架式服务器和塔式服务器有什么区别?
  19. Fall 2020 Berkeley cs61a hw03答案
  20. 屏幕录像专家----百度百科

热门文章

  1. 简单实用颈椎操,办公室里面的你有救啦
  2. 改注册表实现解禁部分系统功能
  3. 店招新品之创意LED显示屏之LED魔方屏的特点
  4. Java---注解、类加载器-加强-实现运行任意目录下class中加了@MyTest的空参方法
  5. 如何在Windows上体验MacOS系统
  6. 身份证号码格式说明(仅供学习使用)
  7. Connection reset by peer的常见原因
  8. mysql 两个分组合并_mysql分组合并GROUP_CONCAT-阿里云开发者社区
  9. 服务器系统盘 FOREIGN,DELL服务器raid盘foreign问题
  10. 百度地图jsp源码(直接复制使用)