使用netty实现socks5协议
一、socks5协议简介
SOCKS是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递。
SOCKS是”SOCKetS”的缩写[注 1]。 当防火墙后的客户端要访问外部的服务器时,就跟SOCKS代理服务器连接,这个代理服务器控制客户端访问外网的资格,允许的话,就将客户端的请求发往外部的服务器。
SOCKS 协议第 4 版本为基于 TCP 协议的 C/S 应用,包括 TELNET, FTP 和 使用广泛的信息发现协议如 HTTP 、 WAIS 提供了不保证安全性的防火墙穿透服务。
SOCKS 5 扩展了第 4 版本,加入了 UDP 协议支持,在框架上加入了强认证功能,并且地址信息也加入了域名和 IPV6 的支持。
SOCKS协议不提供加密。
socks5协议适用如下几种场景:
- 局域网内只有某台机器被授权访问网络,其它机器需要连接外部网络,但是未被授权,这时候可以在被授权机器上运行socks5协议的服务端,其它局域网内未被授权的机器上运行socks5客户端程序通过被授权机器上网。
- 网络管理。socks5代理服务器会代理所有流量,所以能获取所有客户端想要访问的目标地址和端口号,这时候代理服务器可以自主决定是否允许客户端访问目标服务器。
- 其它。懂的自然懂,但是由于流量特征明显而且未加密,所以一旦开始用,立马会被封掉服务器,不要玩火,这里仅作为技术研究使用。
二、socks5协议交互过程
socks5协议大体上会经过两个或者三个交互过程,这取决于是否有认证流程。以用户名密码认证方式为例,完整的流程如下图所示
1、版本和认证方式交互
第一步,客户端向代理服务器发送代理请求,其中包含了代理的版本和认证方式:
+----+----------+----------+
|VER | NMETHODS | METHODS |
+----+----------+----------+
| 1 | 1 | 1 to 255 |
+----+----------+----------+
如果是socks5代理,第一个字段VER
的值是0x05
,表明是socks代理的第5个版本。
第二个字段NMETHODS
表示支持的认证方式,第三个字段是一个数组,包含了支持的认证方式列表:
0x00
: 不需要认证0x01
: GSSAPI认证0x02
: 用户名和密码方式认证0x03
: IANA认证0x80-0xfe
: 保留的认证方式0xff
: 不支持任何认证方式
服务端收到客户端的代理请求后,选择双方都支持的认证方式回复给客户端:
+----+--------+
|VER | METHOD |
+----+--------+
| 1 | 1 |
+----+--------+
这个过程完成之后,服务端知道了客户端想要使用的socks版本号,告诉客户端是否使用认证;客户端则通过请求服务端,得知下一步是否需要认证。
2、认证交互
如果上一步版本和认证方式交互的结果,服务器不需要认证,则可以跳过该步骤,否则需要进行认证交互。
上一步协商好了使用的认证方式,这里以使用用户名和密码交互方式为例,接下来客户端需要发送用户名和密码给服务端让服务端进行认证,请求格式如下所示
+----+------+----------+------+----------+
|VER | ULEN | UNAME | PLEN | PASSWD |
+----+------+----------+------+----------+
| 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+----+------+----------+------+----------+
- VER:固定长度一个字节,固定值X'01'表示用户名密码认证
- ULEN:用户名长度,固定一个字节大小
- UNAME:用户名,不固定大小,但是其长度和ULEN一致
- PLEN:密码长度,固定一个字节大小
- PASSWD:密码,不固定大小,但是其长度和PLEN一致
服务端会进行用户名和密码的校验,然后做出如下响应
+----+--------+
|VER | STATUS |
+----+--------+
| 1 | 1 |
+----+--------+
如果服务器响应STATUS的值为X'00',表示认证成功;其它状态表示认证失败,这时候客户端需要关闭连接。
3、数据交互
如果上一步用户名密码认证成功,或者无用户名密码认证,则会进入数据交互阶段,这阶段会进行真正的数据传输。首先,客户端会发送一个请求告诉服务端本次请求的信息,格式如下所示
+----+-----+-------+------+----------+----------+
|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
- VER 是SOCKS版本,0x05;
- CMD 是SOCK的命令码
- 0x01 表示CONNECT请求
- 0x02 表示BIND请求
- 0x03 表示UDP转发
- RSV 0x00,保留
- ATYP DST.ADDR类型
- 0x01 IPv4地址
- 0x03 域名类型
- 0x04 IPv6地址
- DST.ADDR 目标服务地址,如果是IPv4类型,则固定4个字节长度;如果是域名类型,第一个字节是域名长度,剩余的内容为域名内容;如果是IPv6类型,固定16个字节长度。
- DST.PORT 目标服务端口,固定两个字节长度
代理服务在接收到该连接报文后,会创建和目标服务器的连接,同时返回和目标服务建立连接的结果报文
+----+-----+-------+------+----------+----------+
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | 0x00 | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
- VER是SOCKS版本,0x05;
- REP应答字段,表示和目标服务建立连接的结果
- 0x00 表示成功
- 0x01 普通SOCKS服务器连接失败
- 0x02 现有规则不允许连接
- 0x03 网络不可达
- 0x04 主机不可达
- 0x05 连接被拒
- 0x06 TTL超时
- 0x07 不支持的命令
- 0x08 不支持的地址类型
- 0x09 - 0xFF未定义
- RSV 0x00,保留
- ATYP BND.ADDR类型
- 0x01 IPv4地址,DST.ADDR部分4字节长度
- 0x03 域名,DST.ADDR部分第一个字节为域名长度,DST.ADDR剩余的内容为域名,没有0结尾。
- 0x04 IPv6地址,16个字节长度。
- BND.ADDR 目标服务地址
- BND.PORT 目标服务端口
至此,Socks5协议的“握手”部分完成,可以开始发送数据。代理服务器只需要将收到的客户端数据“盲目”的转发到目标服务,同时将收到的目标服务数据转发给客户端,只是一个中继(Relay)的角色。
三、netty实现
1.基本实现
netty作为使用java实现的高级网络编程框架,实现socks5协议最终作为代理服务器程序再合适不过了。从上面的交互流程上来看,整个过程还是稍稍有些复杂的,netty框架的特色之一就是实现了各种协议的编解码器给开发人员使用,开箱即用,非常方便。
netty提供了三个解码器和一个编码器帮助开发人员实现socks5协议的服务端的绝大多数功能。
编码器 | 作用 |
---|---|
io.netty.handler.codec.socksx.v5.Socks5ServerEncoder | socks5协议交互过程中编码服务端给客户端的响应 |
解码器 | 作用 |
---|---|
io.netty.handler.codec.socksx.v5.Socks5InitialRequestDecoder | 版本和认证方式交互阶段解码客户端请求 |
io.netty.handler.codec.socksx.v5.Socks5PasswordAuthRequestDecoder | 认证交互阶段解码客户端认证请求 |
io.netty.handler.codec.socksx.v5.Socks5CommandRequestDecoder | 数据交互阶段解码客户端连接请求 |
这几个解码器解决了从抽象的协议请求到对象的转换;而编码器解决了对象到抽象的协议转换。所以这些编解码器只是解决了这些问题还是不够的,剩下的逻辑需要自己实现才行。所以对应着三个解码器,有三个后续的自定义的入栈处理器与其一一对应
处理器 | 作用 |
---|---|
Socks5InitialRequestInboundHandler | 响应版本和认证方式交互阶段客户端请求 |
Socks5PasswordAuthRequestInboundHandler | 响应认证交互阶段客户端认证请求 |
Socks5CommandRequestInboundHandler | 响应数据交互阶段客户端连接请求 |
在第三阶段,在收到客户端发起连接请求后,代理服务器连接目标服务器,这时候涉及到转发客户端的请求到目标服务器以及转发目标服务器的响应到客户端,所以这里设计了两个入栈处理器
处理器 | 作用 | 绑定的Channel |
---|---|---|
Client2DestInboundHandler | 转发客户端请求到目标服务器 | 客户端与代理服务器之间的Channel |
Dest2ClientInboundHandler | 转发目标服务器响应到客户端 | 代理服务器和目标服务器之间的Cahnnel |
2.黑名单处理
这里想要实现一个功能,就是在黑名单中的地址不允许连接,如果是http请求,则直接返回错误页面;https请求或者其它类型协议则直接断开连接。
这个功能在第三阶段连接阶段实现,因为只有这时候才知道客户端想要访问的网络地址。
//检查黑名单
if (inBlackList(msg.dstAddr())) {
log.info("{} 地址在黑名单中,拒绝连接", msg.dstAddr());
//假装连接成功
DefaultSocks5CommandResponse commandResponse = new DefaultSocks5CommandResponse(Socks5CommandStatus.SUCCESS, socks5AddressType);
ctx.writeAndFlush(commandResponse);
ctx.pipeline().addLast("HttpServerCodec", new HttpServerCodec());
ctx.pipeline().addLast(new BlackListInboundHandler());
ctx.pipeline().remove(Socks5CommandRequestInboundHandler.class);
ctx.pipeline().remove(Socks5CommandRequestDecoder.class);
return;
}
这里自定义了BlackListInboundHandler
处理http请求类型并返回在黑名单中的友好页面提示。
四、项目地址和使用说明
项目地址:https://gitee.com/kdyzm/socks5-netty
使用方法:由于在windows环境下系统并非天然支持socks5协议,所以需要借助Proxifier工具使其支持socks5;另外,如果出现了连接速度缓慢,有些网页打不开的现象,是Proxifier没设置好,一定要注意使用代理的dns设置,菜单:Profile->Name Resolution 取消Detect DNS settings automatically
选项,勾选Resolve hostnames through proxy
,之后就好了。
五、参考文档
https://zh.wikipedia.org/wiki/SOCKS
https://cloud.tencent.com/developer/article/1781560
https://www.dyxmq.cn/network/socks5.html
https://www.quarkay.com/code/383/socks5-protocol-rfc-chinese-traslation
https://blog.csdn.net/qq_33215972/article/details/105657960
https://segmentfault.com/a/1190000038498680
https://tools.ietf.org/html/rfc1928
https://tools.ietf.org/html/rfc1929
https://tools.ietf.org/html/rfc1961
使用netty实现socks5协议的更多相关文章
- netty系列之:netty对SOCKS协议的支持
目录 简介 SocksMessage Socks4Message Socks5Message 总结 简介 SOCKS是一个优秀的网络协议,主要被用来做代理,它的两个主要版本是SOCKS4和SOCKS5 ...
- [转]netty对http协议解析原理
本文主要介绍netty对http协议解析原理,着重讲解keep-alive,gzip,truncked等机制,详细描述了netty如何实现对http解析的高性能. 1 http协议 1.1 描述 标示 ...
- dubbo源码分析4-基于netty的dubbo协议的server
dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...
- netty 对 protobuf 协议的解码与包装探究(2)
netty 默认支持protobuf 的封装与解码,如果通信双方都使用netty则没有什么障碍,但如果客户端是其它语言(C#)则需要自己仿写与netty一致的方式(解码+封装),提前是必须很了解net ...
- netty对http协议解析原理解析
本文主要介绍netty对http协议解析原理,着重讲解keep-alive,gzip,truncked等机制,详细描述了netty如何实现对http解析的高性能. 1 http协议 1.1 描述 标示 ...
- HTTP协议和SOCKS5协议
HTTP协议和SOCKS5协议 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们平时上网的时候基本上是离不开浏览器的,尤其是搜索资料的时候,那么这个浏览器是如何工作的呢?用的又是 ...
- SOCKS5 协议解析
代理 根据 HTTP 1.1 的定义,proxy 是: An intermediary program which acts as both a server and a client for the ...
- netty支持的协议
流经网络的数据总是具有相同的类型:字节.这些字节是如何流动的主要取决于我们所说的 网络传输--一个帮助我们抽象底层数据传输机制的概念.用户并不关心这些细节:他们只想确保他们的字节被可靠地发送和接收. ...
- netty对http协议解析原理解析(转载)
本文主要介绍netty对http协议解析原理,着重讲解keep-alive,gzip,truncked等机制,详细描述了netty如何实现对http解析的高性能. 1 http协议 1.1 描述 标示 ...
随机推荐
- 开发过程中遇到的js知识点总结,面试题等,持续更新
1.Object.freeze() 方法用于冻结一个对象,即将对象设置为不可扩展.将对象的所有自有的属性和方法(包括Symbol值的属性和方法)配置为不可配置,不可写. Object.freeze( ...
- 设计模式系列之享元模式(Flyweight Pattern)——实现对象的复用
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- cve-2018-2893 weblogic -WLS核心组件反序列化
漏洞分析 https://www.freebuf.com/column/178103.html https://www.freebuf.com/vuls/177868.html 攻击者可以在未授权的情 ...
- P1092 虫食算 题解(搜索)
题目链接 P1092 虫食算 解题思路 好题啊!这个搜索好难写...... 大概是要考虑进位和考虑使用过某个数字这两个东西,但就很容易出错...... 首先这个从后往前搜比较好想,按照从后往前出现的顺 ...
- MySQL入门(5)——运算符
MySQL入门(5)--运算符 算术运算符 MySQL支持的算数运算符包括加.减.乘.除.求余. 符号 作用 + 加法运算 - 减法运算 * 乘法运算 / 除法运算 % 求余运算 DIV 除法运算,返 ...
- WorkSkill整理之 技能体系
- TextRank算法及生产文本摘要方法介绍
TextRank 算法是一种用于文本的基于图的排序算法,其基本思想来源于谷歌的 PageRank算法,通过把文本分割成若干组成单元(句子),构建节点连接图,用句子之间的相似度作为边的权重,通过循环迭代 ...
- 【linux】制作deb包方法 **
目录 前言 概念 ** 创建自己的deb包 文件源码 前言 制作deb的方式很多 使用 dpkg-deb 方式 使用 checkinstall 方式 使用 dh_make 方式 修改原有的 deb 包 ...
- java例题_22 用递归求阶乘 5!
1 /*22 [程序 22 递归求阶乘] 2 题目:利用递归方法求 5!. 3 程序分析:递归公式:fn!=fn*4! 4 */ 5 6 /*分析 7 * 递归:如果其中每一步都要用到前一步或前几步的 ...
- vue+django实现websocket连接
一.概述 在项目中,需要使用websocket,来展示一些实时信息. 这里使用django 3.1.5 二.django项目 安装模块 pip3 install django-cors-headers ...