[Go]udp打洞
为了能够进行udp打洞需要一台公网服务器,具体打洞步骤如下:
- clientA固定udp包发送端口1198,clientB股东udp包发送端口1198。
- clientA向server发起请求(此时NAT服务器绑定内外网端口),server端记录下clientA的外网IP和端口(1.1.1.1:111)
- clientB向server发起请求(此时NAT服务器绑定内外网端口),server端记录下clientB的外网IP和端口(2.2.2.2:222)
- 当clientA和clientB都接入后,server端把clientA的外网信息告知clientB,把clientB的外网信息告知clientA
- 开始打洞,clientA向2.2.2.2:222发送第一个udp包,NAT B不知道将这个包转发给谁,丢弃。clientB向1.1.1.1:111发送第一个udp包,NAT A将该包转发给clientA。此时打洞完成。clientA和clientB建立通讯。
以下为代码实现:
main.go
|
|
server.go
|
|
client.go
|
|
这一份代码实现只支持全锥型(Full Cone)NAT,且不能是受限锥型(Restricted Cone)和端口受限锥型(Port Restricted Cone),但可以对第一个用于打洞的udp包稍加改动建立通信。当有一方为对称型(Symmetric)也是可以用想办法打通的。但双端均为对称型NAT时或一端为端口受限型另一端为对称型则不可以打通。
本端类型 | 对端类型 | 是否可打通 |
---|---|---|
全锥型 | 全锥型 | √ |
全锥型 | 受限锥型 | √ |
全锥型 | 端口受限锥型 | √ |
全锥型 | 对称型 | √ |
受限锥型 | 受限锥型 | √ |
受限锥型 | 端口受限锥型 | √ |
受限锥型 | 对称型 | √ |
端口受限锥型 | 端口受限锥型 | √ |
端口受限锥型 | 对称锥型 | × |
对称锥型 | 对称锥型 | × |
关于NAT的四种类型可以参考以下这篇文章: NAT的四种类型