- socks5 代理的是 TCP, UDP 流量,无法代理 icmp 流量
auth_nego_request {
version(8)=0x05,
// The auth_method_count field contains the number of method identifier octets that
// appear in the auth_method_list field.
auth_method_count(8),
auth_method_list(auth_method_count),
}
auth_nego_repley {
version(8)=0x05,
method(8),
}
rfc 中定义的 method 方法:
| 值(Hex) | 名称 |
|---|---|
0x00 |
NO AUTHENTICATION REQUIRED |
0x01 |
GSSAPI |
0x02 |
USERNAME/PASSWORD |
0x03–0x7F |
IANA ASSIGNED |
0x80–0xFE |
RESERVED FOR PRIVATE METHODS |
0xFF |
NO ACCEPTABLE METHODS |
如果 reply msg 中的 method 是 0xFF ,说明 socks5 server 无法支持 client 的 auth method,client 要立刻断开连接.
dst_addr 是 domain ,先进行 DNS 解析,再尝试 tcp 连接,无论连接是成功还是失败,都会回复.proxy_request {
version(8)=0x05,
cmd(8)=0x01, // CONNECT
reserved(8)=0x00,
atyp(8),
[domain_length(8)],
dst_addr(..)
dst_port(16),
}
proxy_reply {
version(8)=0x05,
reply(8),
reserved(8)=0x00,
atyp(8),
[domain_length(8)],
bnd_addr(..),
bnd_port(..)
}
atyp
0x01 : IPv4 address0x03 : Domain0x04 : IPv6 addressreply 的值:
| 值(Hex) | 含义 |
|---|---|
0x00 |
succeeded |
0x01 |
general SOCKS server failure |
0x02 |
connection not allowed by ruleset |
0x03 |
Network unreachable |
0x04 |
Host unreachable |
0x05 |
Connection refused |
0x06 |
TTL expired |
0x07 |
Command not supported |
0x08 |
Address type not supported |
0x09–0xFF |
unassigned |
1. client ↔ socks: 建立 TCP
2. client → socks: CONNECT
3. socks → target: 建立 TCP
4. socks ↔ target: TCP 建立成功
5. socks → client: 成功响应
6. 开始双向转发:
client <-> socks <-> target
(只是复制 TCP payload,不解析、不修改)
proxy_request {
version(8)=0x05,
cmd(8)=0x03, // UDP ASSOCIATE
reserved(8)=0x00,
atyp(8),
[domain_length(8)],
dst_addr(..)
dst_port(16),
}
proxy_reply {
version(8)=0x05,
reply(8),
reserved(8)=0x00,
atyp(8),
[domain_length(8)],
bnd_addr(..),
bnd_port(..)
}
dst_addr/dst_port 表示:客户端在该 UDP associate 过程中准备用于发送 UDP 数据包的地址dst_addr/dst_port 可以用全零的端口号和地址dst_addr/dst_port 并不能真实的反应最终到达 socks5 server 的 UDP 数据包来源地址,所以此项在具体实现中建议使用全零的端口和地址bnd_addr/port 表示这个地址有一个已经工作的 udp relay server ,后续 client 必须发送 udp 报文到 udp relay server我感觉没有必要的,可能是为了方便解析器的实现吧.
bnd_addr/port 地址发送 UDP 报文relay_udp_header {
reserved(2)=0x00,
frag(1),
atyp(1),
dst_addr(..),
dst_port(..),
payload(..)
}
[udp_header][relay_udp_header][raw_payload]
0x00 的数据包.relay udp server 会维护两个东西
// 用于存放待组装的 udp 报文
REASSEMBLY QUEUE
// 计时器
REASSEMBLY TIMER
这个东西已经被时代淘汰了
所以,没有介绍