假期的时候把socks5代理的RFC全部读完了,有些体会不敢独享,在这里写出来大家一起评论评论,如有错误敬请提出。
下面假设使用TCP连接方式。首先需要和代理服务器之间建立连接,这里没什么复杂的,简单的connect(serverIP, serverPort)就可以了。连接成功之后,需要使用send()发送命令字,以便确定是否需要验证,下面是RFC里面的命令字格式:
项目 | 版本 | 方式数目 | 连接方式 | … |
项目长度 | 1 | 1 | 1-255 | … |
首先"版本"这一项固定是 X"05"(socks version 5),方式数目告诉server究竟提交了几种连接方式的请求,至于连接方式则可以有多个。下面就是方式列表:
连接方式 | 含义 |
X’00’ | 无需验证,直接继续 |
X’01’ | GSSAPI |
X’02’ | 需要用户名/密码 |
X’03’ to X’7F’ | IANA ASSIGNED |
X’80’ to X’FE’ | 保留方式,可以自己灵活选用 |
X’FF’ | 未包含符合要求的方式 |
接下来是server的回应:
项目 | 版本 | 允许的连接方式 |
项目长度 | 1 | 1 |
版本不必说,仍然固定是 X"05",允许的连接方式则是在你提交的众多连接方式中,由server选出一个可以接受的,然后返回来;如果没有,那么返回就是 X"FF"。其中一般用到的就是 X"00"和 X"02"了。它们之间的区别就在于 X"02"方式需要发送用户名/密码,验证通过后的过程则和 X"00"方式没有任何区别。
客户端识别到server返回 X"02"之后,发送下列格式验证字串:
项目 | VER | 用户名长度 | 用户名 | 密码长度 | 密码 |
项目长度 | 1 | 1 | 1-255 | 1 | 1-255 |
注意:这里的VER有别于上边,固定是 X"01"。用户名/密码最大长度是255。
server端验证完毕后返回结果:
项目 | VER | 验证结果 |
项目长度 | 1 | 1 |
验证结果是 X"00"的话,就表示验证通过,否则都是不过…
接下来的过程一样,就是发送请求命令字了:
项目 | 版本 | 命令字 | 保留 | 地址类型 | 地址 | 端口 |
项目长度 | 1 | 1 | X"00" | 1 | 不固定 | 2 |
版本固定 X"05";命令字分三种: CONNECT X"01",BIND X"02",UDP X"03"。CONNECT就是普通的TCP连接;BIND要求你的client支持接受server的连接请求(FTP协议就是一个典型的例子);UDP则是一个特例,我还没有完全理解… 保留项固定是 X"00"。
地址类型有三种:X"01"、X"03"、X"04",分别对应IP-V4、DOMAINNAME、IP-V6,而接下来的地址长度也根据地址类型的不同而变化。IP-V4的长度是4位,DOMAINNAME的长度则根据实际情况变化,但是地址的第一位的内容要设成域名字符串的长度,IP-V6就是16位。
端口长度固定两位,没什么可说的。
而server返回的内容格式也大致相同
项目 | 版本 | 返回值 | 保留 | 地址类型 | 地址(BND) | 端口 |
项目长度 | 1 | 1 | X"00" | 1 | 不固定 | 2 |
返回值可能是下列值中的一个:
连接方式 | 含义 |
X’00’ | 成功 |
X’01’ | general SOCKS server failure |
X’02’ | 连接不符合server规格 |
X’03’ | 目标网络无法到达 |
X’04’ | 目标主机无法到达 |
X’05’ | 连接拒绝 |
X’06’ | TTL expired |
X’07’ | 命令不支持 |
X’08’ | 地址格式不支持 |
X’09 to X’FF’ | 保留 |