从零实现加密隧道(二):socks5 协议详解
socks的文档:https://www.ietf.org/rfc/rfc1928.txt
SOCKS5 是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递。SOCKS 是 "Sockets"的缩写。
SOCKS5 工作在比 HTTP 代理更低的层次。
是一个代理协议,它在使用TCP/IP协议通讯的前端机器和服务器机器之间扮演一个中介角色,使得内部网中的前端机器变得能够访问Internet网中的服务器,或者使通讯更加安全。SOCKS5 服务器通过将前端发来的请求转发给真正的目标服务器,模拟了一个前端的行为。在这里,前端和SOCKS5之间也是通过TCP/IP协议进行通讯,前端将原本要发送给真正服务器的请求发送给SOCKS5服务器,然后SOCKS5服务器将请求转发给真正的服务器。
一、第一步——客户端发送的报头
VERSION | METHODS_COUNT | METHODS |
---|---|---|
1字节 | 1字节 | 1到255字节,长度由METHODS_COUNT值决定 |
0x05 | 0x03 | …… |
VERSION:socks 版本,这里用的是 socks5,所以是0x05。
METHODS_COUNT: METHODS 部分的长度。
METHODS:代表客户端拥有的加密方式。每个方法占 1 字节。当前的定义是:
- 0x00 不加密
- 0x01 GSSAPI
- 0x02 用户名、密码认证
- 0x03 - 0x7F 由IANA分配(保留)
- 0x80 - 0xFE 为私人方法保留
- 0xFF 无可接受的方法
例如,客户端发送的 5 2 0 2,代表 版本5 有两种握手方式 “不加密”和“用户名、密码认证”供代理选择。
因为我们写的是服务器端,怎么发过来是客户端(浏览器)解决的,所以这里不用管。
二、第二步——代理服务器响应的报头
VERSION | METHODS |
---|---|
1字节 | 1字节 |
0x05 | 从客户端发送的加密方式里面选一个 |
- VERSION:socks 版本,这里用的是 socks5,所以是0x05。
- METHODS:代表代理服务器选择了一种握手方式。占 1 字节。
例如,代理服务器发送的 5 0,代表 版本5 选择了“不加密”的握手方式。
如果客户端的所有握手方式代理服务器都不满足,直接断开连接。
如果代理服务器发送 5 2,代表 版本5 选择了“用户名、密码认证”的握手方式。此时客户端会发送账号密码数据给代理服务器,再由代理服务器检验,并返回结果。格式如下:
VERSION | USERNAME_LENGTH | USERNAME | PASSWORD_LENGTH | PASSWORD |
---|---|---|---|---|
1字节 | 1字节 | 1-255字节 | 1字节 | 1-255字节 |
0x01 | 0x01 | …… | 0x01 | …… |
- VERSION:认证子协商版本(与 SOCKS 协议版本的0x05无关系)
- USERNAME_LENGTH:用户名长度
- USERNAME:用户名字节数组,长度为 USERNAME_LENGTH
- PASSWORD_LENGTH:密码长度
- PASSWORD:密码字节数组,长度为 PASSWORD_LENGTH
VERSION | USERNAME_LENGTH |
---|---|
1字节 | 1字节 |
0x01 | 0x01 |
- VERSION:认证子协商版本,与客户端 VERSION 字段一致
- STATUS:认证结果(0x00 认证成功 / 大于0x00 认证失败)
这里需要我们的服务器端做出回应。
char buf[4096];int len = recv(fd, buf, sizeof(buf), 0);if (len > 0) {char ret[2];ret[0] = 0x05;if (buf[0] == 0x05) { // 是 socks5ret[1] = 0x00; // 选择 不加密方式XORcode(ret, 2);send(fd, ret, sizeof(ret), 0);} else {// ...}} else {// ...}
第三步——客户端发送需要访问的IP和端口,以及协议
VERSION | COMMAND | RSV | ADDRESS_TYPE | DST.ADDR | DST.PORT |
---|---|---|---|---|---|
1字节 | 1字节 | 1字节 | 1字节 | 可变成长度 | 2字节 |
- VERSION:SOCKS 协议版本,固定 0x05
- COMMAND:命令
- 0x01:CONNECT请求,连接上游服务器(使用TCP)
- 0x02:BIND 绑定,客户端会接收来自代理服务器的链接,著名的FTP被动模式
- 0x03:UDP ASSOCIATE UDP 中继(UDP 转发)
- RSV:保留字段,无实际作用
- ADDRESS_TYPE:目标服务器地址类型
- 0x01:表示 IPv4 地址
- 0x03:域名地址(没有打错,就是没有0x02)
- 0x04:IPv6 地址
- DST.ADDR:目标服务器地址(如果是ipv6,该字段的第一个字节是域名长度,剩下字节为域名)
- DST.PORT:目标服务器端口
因为我们写的是服务器端,这一步在下一步里面进行判断即可。
第四步——代理服务器响应
VERSION | RESPONSE | RSV | ADDRESS_TYPE | BND.ADDR | BND.PORT |
---|---|---|---|---|---|
1字节 | 1字节 | 1字节 | 1字节 | 1-255字节 | 2字节 |
- VERSION:SOCKS 协议版本,固定 0x05
- RESPONSE:响应命令
- 0x00:代理服务器连接目标服务器成功
- 0x01:代理服务器故障
- 0x02:代理服务器规则集不允许连接
- 0x03:网络无法访问
- 0x04:目标服务器无法访问(主机名无效)
- 0x05:连接目标服务器被拒绝
- 0x06:TTL已过期
- 0x07:不支持的命令
- 0x08:不支持的目标服务器地址类型
- 0x09 - 0xFF:未分配
- RSV:保留字段
- ADDRESS_TYPE:后面的地址类型
- 0x01:ipv4
- 0x03:域名
- 0x04:ipv6
- BND.ADDR:代理服务器连接目标服务器成功后的代理服务器 IP
- BND.PORT:代理服务器连接目标服务器成功后的代理服务器端口
char buf[4096];int len = recv(fd, buf, 4, 0);if (len <= 0) return -1;if (len < 4) return 0;if (buf[0] != 0x05 || buf[2] != 0x00) return -1;char ip4[MAXLINE], port[5];if (buf[3] == 0x04) { // 如果是 ipv6// ...} else if (buf[3] == 0x01) { // 如果是 ipv4len = recv(fd, ip4, 4, 0);len = recv(fd, port, 2, 0);ip4[4] = '\0';port[2] = '\0';int client_fd = open_clientfd(ip4, port); // ...} else if (buf[3] == 0x03) { // 是用域名表示的// 域名字段中第一个字节是真实的域名的长度,后面才是真实的域名char doname_len;char doname[MAXLINE];len = recv(fd, &doname_len, 1, 0);if (len < 1) return 0;len = recv(fd, doname, doname_len, 0);doname[len] = '\0';struct hostent* host = gethostbyname(doname);memcpy(ip4, host->h_addr, host->h_length);len = recv(fd, port, 2, 0);int client_fd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in server;server.sin_family = AF_INET;memcpy(&server.sin_addr.s_addr, ip4, 4);server.sin_port = *((uint16_t*)port);connect(client_fd, (struct sockaddr*)&server, sizeof(server));return client_fd;} else {return -1;}
}
第五步——通信
把要发的内容,像正常的socket编程发过去即可。
参考:
https://www.jianshu.com/p/91979534b49d
https://www.ddhigh.com/2019/08/24/socks5-protocol.html
从零实现加密隧道(二):socks5 协议详解相关推荐
- 李昱:腾讯产品登录协议详解
写下这个标题的时候,您可能要问腾讯产品登录协议有什么用?很简单,qq所有产品都是采用统一的登录协议加密登录的.也就是说,当您能够通过使用它的协议来登录并获取到令牌后,那么就可以任意的使用qq的各项产品 ...
- socket 5协议详解
认证 首先客户端向服务端发送认证信息,结构如下 +----+----------+----------+ |VER | NMETHODS | METHODS | +----+----------+-- ...
- MQTT协议详解 二、MQTT控制包格式
文章目录 系列文章目录 前言 一.MQTT控制包格式 二.固定包头 控制包类型 控制包类型标识 剩余长度 三.可变包头 数据包标识 四.载荷 系列文章目录 MQTT协议详解 一.MQTT简介 MQTT ...
- NVMe协议详解(二)
NVMe协议详解(二) 2. PCIe寄存器配置 2.1 PCIe总线的基本结构 2.2寄存器配置 2.2.1 PCI header 2.2.2 PCI Capabilities 2.2.3 PCI ...
- 计算机网络应用层(二):DNS协议详解
DNS协议详解 前言 DNS协议概述 DNS工作原理 DNS缓存 DNS记录和报文 资源记录 DNS报文 总结 前言 DNS是计算机网络中应用层的一个协议,可能很多同学碰到过DNS被劫持的情况,我们现 ...
- 并发编程之CPU缓存架构缓存一致性协议详解(二)
并发编程之CPU缓存架构&缓存一致性协议详解 CPU高速缓存(Cache Memory) CPU高速缓存 在CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就 ...
- SSL/TLS协议详解(中)——证书颁发机构
SSL/TLS协议详解(中)--证书颁发机构 本文翻译自:https://www.wst.space/ssl-part-3-certificate-authority/ 上一篇中,我们讨论了关于Dif ...
- Linux网络-UDP/TCP协议详解
Linux网络-UDP/TCP协议详解 零.前言 一.UDP协议 二.TCP协议 1.应答机制 2.序号机制 3.超时重传机制 4.连接管理机制 三次握手 四次挥手 5.理解CLOSE_WAIT状态 ...
- 【5G系列】PDCP (Packet Data Convergence Protocol)协议详解
本人就职于国际知名终端厂商,负责modem芯片研发.在5G早期负责终端数据业务层.核心网相关的开发工作,目前牵头6G算力网络技术标准研究. 博客内容主要围绕: 5G协议讲解 算力网络讲解(云计算,边缘 ...
- 【计算机网络面试高频】-HTTP协议详解,HTTP协议常见问题
4.HTTP协议详解有关问题 4.1 HTTP请求 一个HTTP请求报文由请求行.请求头部.空行和请求数据四个部分组成. 1.请求行 请求行中有请求方法字段.URL字段和HTTP协议版本3个字段组成. ...
最新文章
- web app开发技巧总结
- 20、DELETE:删除数据
- 自动编译和提交脚本(结合svn和visual studio)
- [Java设计模式]期末作业参考
- 【操作系统复习】系统调用
- 快门光圈感光度口诀_光圈、快门、感光度之间的关系
- Leetcode529. 扫雷游戏
- 博文荐书:阿里运维、Java微服务、Scala编程
- vue app准备学习工作
- java 批量生成条形码,打包zip(springboot)
- 【2022天梯赛】L1-8 静静的推荐 L2-1 插松枝 L2-2 老板的作息表
- Creo二次开发 Creo4.0 Qt5 动态部署发布
- CCTV-TIME特别关注:深圳首届弘扬关公文化促进两岸统一忠义论坛
- 百度地图SDK无法定位到当前所在位置;一直显示天安门
- HCIP网工数通Datacom之网工拆分(1)理论和基础命令
- 在应急响应过程中,有什么好的方法可以寻找某一日期创建的文件?
- 学生成绩平均绩点计算:绩点计算器(5.0分制,Java、C实现)
- 如何用最低的成本成就最高流量系列 各种线上推广手段的投入产出比数字公布(IreSearch.cn/龚文祥)(推荐帖)
- 深度学习电脑配置选择
- 同济弱鸡21考研逆袭之路(四)