实现SOCKS5协议

SOCKS5协议因为酸酸乳而出名,那么它到底是个什么样的协议呢?是否很复杂?答案是:一点也不复杂。

它是干嘛的?

它是个给代理用的协议。

描述一个场景:A要访问C,但是A和C之间网络不通;这时候出现了一个B,B可以和A联通,B也可以和C联通;那么,我们就可以让A把数据发给B,再由B发给C;同样的,当数据回程的时候,C把数据发给B,B再把数据发给A。

这就是代理的意义。

代理为什么需要一个协议?

假设我们是TCP通讯。

那么A首先要TCP连接B,B接着TCP连接C,这样就形成了一个数据的代理通路,可以双向流通数据了。

但是呢,我们A不仅要访问C啊,还要访问D、E、F等等。作为代理的B,怎么知道A要连的是C或E或F的哪个目标呢?

因为这个原因,A和B之间必须要有一个协商的过程,其核心目的:A要告诉B,希望连接的目标地址是什么。

所以,这种TCP代理是需要协议的,因此SOCKS5就是做这个事情的,可想而知它并不是什么复杂的事情。

同时我们也要意识到,SOCKS5协议其实对应用层协议(例如HTTP)是无感的,它是4层的代理协议。

SOCKS5协议具体什么样?

windows、mac的浏览器都支持SOCKS5代理。

因为它实在太简单了,简单到你看看维基百科就能理解:https://zh.wikipedia.org/wiki/SOCKS#SOCKS5,大家参考wiki继续读博客即可。

下面我说说整个流程,还是以A -> B -> C来说,协议以TCP代理为例(SOCKS5还支持UDP代理以击反向代理模式,就不展开了)。

第1步:A连接B

A创建tcp socket,连接到B即可。

第2步:A发送认证的协商请求给B

SOCKS5协议支持认证,也就是说B要校验一下A是否是合法用户。(B说:要通过我代理,也得看看我同意不同意啊!)

A连接到B后,首先按照SOCKS5协议发送一个协商请求到B,里面主要携带A希望的认证方式,比如:账号+密码。

B收到后协商请求后,B需要确认A希望的认证方式是否支持,选中其中一种认证方法返回给A。

  • 如果A和B协商的是账号+密码的认证方式,那么接下来A就要按SOCKS5协议发账号密码给B,由B认证后返回给A结果。
  • 如果A和B协商的是不需要认证,那么什么也不用做了。

第3步:A发送目标服务器地址给B

这一步作用前面说过了,A需要告诉B目标地址C,这样B才知道连接到C。

SOCK5S支持发送IPV4+PORT、IPV6+PORT、DOMAIN三种目标地址,在请求中叫做DST.ADDR、DST.PORT。

B收到目标地址C后,建立到C的TCP连接;连接成功/失败,通过给A返回一个应答来告知A。

在返回给A的应答里面需要填写BND.ADDR、BND.PORT,代表的是B连接C的时候,socket的本地地址(通过getsockname获取),这个信息实测中没有实际作用。根据协议理解,应该是为了让A知道自己实际连到的是哪个代理节点(如果我们部署了多个B节点),对代理过程自身没有什么实际意义。

第4步:A和C通过B转发数据

现在A和B之间,B和C之间的连接已配对打通。

后续A发送给B的数据,B直接转发给C;后续C发给B的数据,C直接转发给A。

SOCKS5与科学上网有什么关系?

说实话,SOCKS5与科学上网没有直接关系。

数据经过B转发一下就安全了吗?SOCK5仅仅多了一个协商过程啊,数据还是原样的proxy。

无论B节点放在国内还是国外,A到B之间一定经过国内的网络,何谈安全?

所以SOCKS5有什么用呢?SOCKS5只是解决代理的RFC标准化问题,也就是说所有操作系统、常用软件都支持SOCKS5代理模式。

要保证通讯安全与SOCKS5协议没有半毛钱关系,我们要做的是对TCP数据在国内外进行透明的加解密,也就是实现一个安全的隧道。

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~