关于socks5代理的编写

文章作者:WinEggDrop
信息来源:http://www.ph4nt0m.org/

 

邮箱中收到几封关于socks5代理编写的信,我也不知道来信者是不是这个论坛的,不过为了省却一个人回复的麻烦,就写个贴子当是全部回复了。

   socks5代理和sock4代理都是很相似的(sock4代理网上应该有很多代码,我也曾在这里放过sock4代理的代理),不同的就是sock5代理除了支持UDP协议的数据外,还支持多种验证模式.一般常用的只是无验证模式(NO AUTHENTICATION )和用户/密码模式(USERNAME/PASSWORD),其它模式就算加上了,应用程序也不支持的(你可以看看oicq,msn,flashfxp等软件,也都只是支持这两种模式的).socks5代理一般是三种模式的支持,TCP CONNECT,TCP BIND和UDP ASSOCIATE,这里最常用的是TCP CONNECT,因为绝大部分TCP协议的软件都是使用这种模式的,TCP BIND只会用在FTP的Active模式中(就是数据连接是由FTP服务连接回FTP客户),并不常用,而且我测试过flashfxp和cuteftp,两种都不支持TCP BIND的(就是说如果是用了代理的话,两种软件都不支持使用Active模式,一定要使用Passive模式和FTP服务进行数据交换),所以我们只简单地讨论一下TCP CONNECT和UDP ASSOCIATE两种模式.

 Socks5代理的请求和返回信息.
1.客户端发送到socks5代理至少三个字节的请求,第一个字节一定为5,第二个字节为使用多少种验证,第三个字节为验证模式代码.
例:如果要使用"USERNAME/PASSWORD",那么这三个字节为5 1 2

2.Sock5代理接到上面请求后,如果是支持"USERNAME/PASSORD"的验证模式,就会返回两个字节,第一字节为5,第二字节为2.

3.客户端然后就向socks5代理发送验证信息,信息第一字节不需要理会,第二字节为验证用户名的长度,第三字节开始是用户名和密码信息.

4.socks5代理验证用户名和密码成功后,向客户端返回两个字节,5和0,如果验证失败,返回0x05和0xff.

5.客户端开始向sock5代理发送第一个向远程目标进行操作的请求,请求模式如下:
第一位为5
第二位是使用模式,0x01代表TCP CONNECT,0x02代表TCP BIND,0x03代表UDP ASSOCIATE
第三位保留
第四位是地址使用模式:0x01代表IP V4地址;0x03代表域名;0x04代表IP V6地址(一般常见的只是0x01和0x03两种模式,因为很多软件都不支持IP V6的)
第五位开始就是目标的地址和端口.

6.socks代理开始处理这个请求,对于TCP CONNECT和UDP ASSOCIATE模式有不同的处理.
A.对于TCP CONNECT
将请求分析后,将目标地址和 目标端口从请求中解析出来(无论请求中带的地址是否以域名方式发送过来,最终要将地址转换为IPV4的地址),然后使用connect()连接到目标地址中的目标端口中去,如果成功连接,那就向客户端发送回10个字节的信息,第一字节为5,第二字节为0,第三字节为0,第四字节为1,其它字节都为0.
B.对于UDP ASSOCIATE(这个复杂很多了)
将请求分析后,先保存好客户端的连接信息(客户端的IP和连接过来的源端口),然后本地创建一个UDP的socket,并将socket使用bind()绑入本地所有地址中的一个UDP端口中去,然后得到本地UDP绑定的IP和端口,创建一个10个字节的信息,返回给客户端去.第一字节为0x05,第二和第三字节都为0,第四字节为0x01(IPV4地址),第五位到第8位是UDP绑定的IP(以DWORD模式保存),第9位和第10位是UDP绑定的端口(以WORD模式保存).

7.最后是数据的传送了,TCP CONNECT和UDP ASSOCIATE模式又有所不同
A.对于TCP CONNECT
很简单,从客户中读到的所有数据,马上发送到远程目标;从远程目标中读到的所有数据,马上全部发送到客户端
B.对于UDP ASSOCIATE(又是复杂),
有数据包时,首先将数据全部读取,然后判断数据是从客户端还是远程目标传送过来的(在读取时可以得到是从什么地址和端口读取到数据的,然后比较上面第6步时我们保存了下来的客户端的连接信息),如果数据是从客户端读取过来的,我们要将UDP头去掉.例如我们读取到的Buffer,Buffer[3]是1时,UDP头就是10个字节长度,如果Buffer[3]是3的话,UDP头长度是7+Buffer[4].例如我们得到UDP头是20位,我们接收到的Buffer是50位长度,那么我们发送到目标的数据包长度是30位,前20位不发送,只发送后面的30位.如果数据是
从远程目标发送来的,我们就要多发送多10位的UDP头,这10位的UDP头前三位都是0,第四位是0x01,第五到第八位是我们保存下来的客户端的IP,第9和第十位是客户端的端口.如果我们接收到的Buffer长度是50,那么我们发送到客户端的数据就要加上10位的UDP头,也就是一共要发送60位字节长度的数据.

支持验证,支持TCP CONNECT和UDP ASSOCIATE模式的sock5代理的基本编写就是这样。
http://www.faqs.org/rfcs/rfc1928.html 是socks5代理的rfc,不过是写得非常非常简单的。我也有时会质疑rfc为什么都这么简单和模糊,为什么不可以写详细一点,或加上几个简单的例子。FTP服务的rfc甚至连列举文件时,ftp服务向客户发送回去的每一行信息的标准都没有,所以大家可以看到几乎每一个ftp服务向客户端返回的文件列表都不一定是相同的。

有一点需要补充的,那就是socks5代理的超时。在刚连接和验证那段期间可以设置超时,例如用户连接后30秒都没有验证的,就将那连接关闭。但验证后,就不可以设置超时了(或者是可以设置的,但我实在不知道如何做)。不可以设置超时的原因有两个:

1.对于UDP的连接,因为UDP是无连接的,你很难确定用户是否还是连接着,还会继续发送数据过来的。有人说可以定时发送数据过去。这是一种办法,但是要考虑到,因为你不知道用户是使用什么软件在发送UDP数据过来,你乱发数据过去,很大可能是被客户软件认为是不合法的数据而过滤掉,如果sock5代理因为发过去的数据被过滤了而认为客户 是断开了,那么极容易就将没有断开的用户也踢下去了,而且现在的oicq还会使用使用两个连接,一个是UDP连接,另一个是TCP连接,UDP连接只是登陆上服务器时使用,TCP连接却是进行数据传输的,而UDP连接却是一直都不会有数据传输的了,如果socks5代理因为UDP连接长时间没有数据传输而将那个UDP连接关闭的话,oicq也会因为这样而掉线(你关闭了UDP连接,oicq以为代理是不可用了,自己会将TCP连接断开)

2.对于TCP连接,设置超时是很简单,但只是对于一般只是使用一个连接进行数据通讯的软件有效,对于FTP是完全失效。当FTP客户挂socks5代理时,当有数据传输,例如列文件,下载文件或上传文件时,就会需要两个TCP连接,一个是接收FTP客户或接收FTP服务器返回的信息的,另一个是进行数据交换的,如果在进行长时间的数据交换时,例如上传文件或下载文件,有可能是要进行几小时或更长的数据交换,接收FTP客户命令或接收FTP服务器返回信息的那个TCP连接,是一直都没有数据通过的,如果设置了超时,例如1小时没有数据通过就断开连接的话,你就会将那个TCP连接关闭了,如果你关闭了那个TCP连接的话,FTP客户端也会马上将数据交换的那个TCP连接马上关闭(因为FTP客户端会认为自己被断开了)。

就因为这两点,我自己认为无法设置超时.也测试过几个socks5代理软件,也是没有在验证后做超时的处理的。因为TCP连接正常断开还是非正常的断开,socks5代理都可以轻易检查到,但UDP连接就很难检查,所以在测试中都有发现一些不正常断开的UDP连接还是一直没被socks5代理关闭到(ccproxy,wingate,还有大家可能最熟悉的skserver也是这样).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值