以前编写的一个基于openfire服务器的即时通信软件,由于部署环境须要,须要增长代理登陆通讯的实现。整理了一下相关代理的知识分享一下。安全
一个基于TCP协议的客户端但愿与一个只能经过特定网络节点才能够联通的目标创建通信时,它必须在该节点搭建代理,先创建一个与SOCKS服务器上端口的TCP链接(TCP端口能够是1080)。当链接创建后,客户端和代理服务器进入协议的“握手(negotiation)”过程,握手经过事后,这时就创建了客户端和代理之间的链接。完成握手后代理能够看做一个透明的网络,向代理发送真正的请求协议便可实现代理请求。服务器
整个代理过程主要分两个重要的阶段“协议握手”、“代理请求”,代理请求由代理服务器上的代理服务处理,如今有不少成熟的代理软件,选一个便可。咱们主要实现的是基于代理软件的链接,或者说是实现基于SOCKS V5协议的链接过程(应用是代理IM的通讯),因此主要实践“协议握手(negotiation)”。网络
协议握手的过程:并发
客户端连到服务器后,而后就发送请求来协商版本和认证方法〔格式见下〕:spa
VER代理 |
NMETHODSci |
METHODS部署 |
1域名 |
1io |
1 to 255 |
SOCKS v5协议中,VER字段被设置成X'05'。NMETHODS字段包含了在METHODS字段中出现的方法标示的数目(以字节为单位)。 咱们发送请求商定版本和认证方式后(发送05 01 00),服务器从给定的方法中选择一个并发送一个方法选中的消息回客户端〔格式见下〕
VER |
METHOD |
1 |
1 |
返回的消息中若是是X’FF’,这表示客户端所列出的方法列表中没有一个方法被选中,客户端必须关闭链接。咱们须要关注的第二位的消息内容,返回的消息是05 00或者05 02(00 忽略验证 ;02 进行用户验证)。
下面咱们要了解的则是“0x02 用户名/密码”验证的过程。
当客户端发送带有0x02认证方法的报文(如:“0x05 0x01 0x02”)到服务端时,根据报文,服务端得知客户端支持用户名/密码认证(0x02),所以若是服务端须要验证,则发送“0x05 0x02”应答,这样客户端将会进入“用户名/密码”验证过程。
“0x02 用户名/密码”验证协议的报文格式是:
0x01 | 用户名长度(1字节)| 用户名(长度根据用户名长度域指定) | 口令长度(1字节) | 口令(长度由口令长度域指定)
因此报文的长度是根据用户名与密码的长度而定,好比如下报文:
0x01 0x02 0x41 0x42 0x02 0x43 0x43
则表示发送用户名为“AB”密码为“CC”的验证报文。
服务端接收到用户名/密码验证报文后进行相应处理并返回如下格式的应答报文:
0x01 | 验证结果标志
验证过程结束后,客户端就发送详细的请求信息。若是协商的方法中有以完整性检查和/或安全性为目的的封装,这些请求必须按照该方法所定义的方式进行封装。
协议握手完成以后,就须要发送一个请求链接,这个链接便是对远程服务器的链接,由于如今咱们直连的是代理服务器,因此须要告诉代理服务器,咱们要链接xxx地址。
请求的格式以下:
VER |
CMD |
RSV |
ATYP |
DST.ADDR |
DST.PROT |
1 |
1 |
X’00’ |
1 |
Variable |
2 |
注:
· VER 协议版本: X’05’
· CMD
· CONNECT:X’01’
· BIND:X’02’
· UDP ASSOCIATE:X’03’
· RSV 保留
· ATYP 后面的地址类型
· IPV4:X’01’
· 域名:X’03’
· IPV6:X’04’'
· DST.ADDR 目的地址
· DST.PORT 以网络字节顺序出现的端口号
ATYP字段中描述了地址字段(DST.ADDR,BND.ADDR)所包含的地址类型:
X'01':基于IPV4的IP地址,4个字节长;
X'03':基于域名的地址,地址字段中的第一字节是以字节为单位的该域名的长度,没有结尾的NUL字节;·
X'04':基于IPV6的IP地址,16个字节长。
Variable:表示该域的长度是可变的。
代理服务器这边会根据请求内容返回特定格式的消息(以下格式)。
VER |
REP |
RSV |
ATYP |
BND.ADDR |
BND.PORT |
1 |
1 |
X’00’ |
1 |
Variable |
2 |
注:标识为RSV的字段必须设为X’00’。
VER 协议版本: X’05’
REP 应答字段:
X’00’ 成功
X’01’ 普通的SOCKS服务器请求失败
X’02’ 现有的规则不容许的链接
X’03’ 网络不可达
X’04’ 主机不可达
X’05’ 链接被拒
X’06’ TTL超时
X’07’ 不支持的命令
X’08’ 不支持的地址类型
X’09’ – X’FF’ 未定义
RSV 保留
ATYP 后面的地址类型
IPV4:X’01’
域名:X’03’
IPV6:X’04’
BND.ADDR 服务器绑定的地址
BND.PORT 以网络字节顺序表示的服务器绑定的段口
返回的信息里面都看到,返回结果在第二个域,为0则表示成功。
验证请求成功后,Socket5整个TCP客户端的链接就完成了。这时候代理服务器就能够看做是一个透明的网络链接。