Asio 在连接代理后需要完成 SOCKS5 交换
把 SOCKS5 当作 Asio 套接字之上的协议状态机:完整读取、校验应答,并且只有在 CONNECT 成功后才与目标进行 TLS。
把 Asio 的 TCP 套接字连接到 SOCKS5 监听端口,只完成了一步:与该监听端口之间的 TCP 连接。它并没有要求代理去连接最终服务器。对于获准的公开目标测试,SOCKS5 代理列表为这个最初的 TCP 端点提供候选;连接器仍然必须完成下面的交换。
随后 SOCKS5 连接器必须执行协议交换:
- 发送版本 5 的问候,列出客户端支持的认证方法。
- 读取所选方法,并在需要时执行其认证交换。
- 发送 CONNECT,携带目标地址类型、地址和网络字节序的端口。
- 读取应答,检查版本与结果码,并读取完整的变长绑定地址和端口。
- 把建立的流交给应用协议。
名为 socks5::async_proxy_connect 的辅助函数属于提供该辅助函数的 SOCKS 实现。把它与 boost::asio 并列提及,并不会让它成为 Asio TCP 套接字接口的一部分。
TCP 读取可能只返回应答的一部分。按所需字节数组合读取,再从地址类型字段确定剩余长度。不要假定每个服务器应答都是固定的 IPv4 布局。
对于 HTTPS,只在 SOCKS CONNECT 成功之后才与目标进行 TLS 握手,并保留目标的 SNI 与主机名校验。仅凭代理应答成功并不能认证网站。
在整个建立过程中保持取消与超时。TCP 连接建立超时后,后续的问候、认证和 CONNECT 交换就会失去时限。