socks5的RFC地址:
socks是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递。根据OSI七层模型来划分,SOCKS属于会话层协议,位于表示层与传输层之间。 当防火墙后的客户端要访问外部的服务器时,就跟socks代理服务器连接。该协议设计之初是为了让有权限的用户可以穿过过防火墙的限制,使得高权限用户可以访问外部资源。经过10余年的时间,大量的网络应用程序都支持socks5代理。 这个协议最初由David Koblas开发,而后由NEC的Ying-Da Lee将其扩展到版本4,最新协议是版本5,与前一版本相比,socks5做了以下增强:
socks协议的设计初衷是在保证网络隔离的情况下,提高部分人员的网络访问权限,但是对应网络安全来讲,更多的是利用socks5这个协议来访问到内部的网络,访问一些访问不到的资源,这也是对于网络攻防层面来讲,但是socks5的用途也是很多的。例如一般我们在大学里面,学校内网肯定提供了很多服务资源给学生,我们可以通过校园网在学校内部网络进行访问使用。但是如果我们假期回到家了就很难进入到学校的内网再访问到学校内部的资源,一般我们可以通过在公网上面的一个VPS搭建一个socks代理服务器,并且在内网搭建一台服务器和VPS建立socks通道。然后我们就可以通过连接到VPS提供的某个代理端口来访问到学校的内部资源了。
如果要与socks5服务器建立TCP连接,客户端需要先发起请求来对协议的版本及其认证方式。这里就是客户端请求服务器的请求格式:
目前支持的验证方式一共有:
以上的都是十六进制常量,比如X’00’表示十六进制0x00。 当服务器端收到了客户端的请求之后,就会在响应客户端的请求,服务端需要客户端提供哪种验证方式的信息。
这里举一个例子,例如我们这里是socks5的话接受的肯定就是0x05,并且我们设定不需要验证。那么就是0x00不需要验证
这里看到 https://github.com/shikanon/socks5proxy 项目的代码。这里就是做授权认证的代码。一开始就是先判断三个数据VER ,NMETHODS ,METHODS 。接着如下就没就是获取到客户端发送过来的模式,默认就是不需要密码的。
下面就是完整的代码:
如果客户端请求发送过去的信息是表明是请求到是0x02用户名、密码认证。下面就是认证的格式。
客户端发送请求过去之后,服务器鉴定之后就会发出如下回应。
下面代码就是实现了socks5的认证。一开始依然是判断socks协议版本,如果不正确的话依然会返回错误。接着在获取到对应的ULEN UNAME PLE PASSWD。可以看到如果验证成功就会返回如下数据给客户端。
Socket5的客户端和服务端进行双方授权验证通过之后,就开始建立连接了。连接由客户端发起,告诉Sokcet服务端客户端需要访问哪个远程服务器,其中包含,远程服务器的地址和端口,地址可以是IP4,IP6,也可以是域名。
接着客户端把要请求的远程服务器的信息都告诉Socket5代理服务器了,那么Socket5代理服务器就可以和远程服务器建立连接了,不管连接是否成功等,都要给客户端回应,其回应格式为:
服务端响应客户端连接成功就会返回如下的数据给客户端。
下面就是实现的完整代码:
最后完成链接之后就是需要进行数据转发了,这个操作和写端口转发的一样的,通过io.Copy()把两个端口的的流量进行转发即可
这个项目的地址如下,是一个小型的sock5代理工具,这个工具在socks5协议中调用了armon的go-socks5项目和调用了多路复用yamux项目。
这里调用了go-socks5这个包,这是一个socks5协议的api,是使用Go写的,所有可以直接调用即可原理和上面介绍的一样。这个包结构我修改了一下,这里是我的包结构
首先看一下服务端的代码,服务端的代码实现了一个方法ConnectForSocks()。 首先一开始就创建一个SOCKS5服务器,socks5.Config{} 适用于配置 Config的。用于设置和配置服务器
接着创建一个建立,用于连接客户端监听的端口,也就是对应客户端的 -listen 参数给的端口
接着就是通过把conn创建一个yamux多路复用的session。
接着就会用这个session来等待 yamux client 连接。在通过匿名函数利用yamux连接到的stream 来连接socks。
全部代码如下:
接着就是客户端的代码,客户端的代码实现了两个方法ListenForSocks()和ListenForClients()方法 ListenForSocks()这个方法是用来被服务端连接的方法,该方法监听一个端口用于服务端连接也就是-listen 参数的端口。他调用net.Listen()等待服务端的连接。接着等待到连接之后会创建yamux的客户端
ListenForClients()该方法开启一个socks5端口,等待用户使用socks5协议连接。一开始net.Listen的就是一般使用的1080的那个端口,客户连接过来进行流量代理的端口。最后会使用io.copy将conn的流量和stream(也就是多路服用创建的stream)进行流量copy转发过去。
完整的代码如下:
主函数这里就是定义一些命令行的参数。并且在对个个函数进行调用
这里我假设一个场景如下。A可以连接B,B也可以连接A,B可以连接C但是C不能连接A。也就是说我们需要通过B作为代理的中间人来对流量进行转发,中间通过的就是socks5协议。我这里的环境是两台电脑。C是在第一台电脑,A,B是二台电脑。A是VMware虚拟机,使用的NAT进行转换IP。并且B和C是在同一个wifi下。所以C不能通过VMware的路由访问到虚拟机A。
一开始我们需要在B机器上面进行操作,设置一点监听和一个socks。这里需要注意的是 -socks 参数后面带的IP地址不要换回地址 127.0.0.1 ,写本机地址即可,不然连接不到socks地址。
接着在内网机器中使用命令连接 listen :8080 端口即可。
接着就可以通过Proxifier连接到192.168.1.106:1080来访问到对方的内网了。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/7408.html