说一下我的想法,现在还没时间验证,大家看看有没有可行性。[定义]
hostA           一处于内网的主机
local_ip_A      hostA的IP
natA            hostA的NAT网关
nat_ip_A        natA的IP
hostB           一处理内网的主机
local_ip_B      hostB的IP
natB            hostB的NAT网关
nat_ip_B        natB的IP
server          某公网主机,有固定IP
server          server的IP
X               表示任意值[约束]
1、NAT网关为非严格NAT网关(严格NAT另论)
2、hostA与hostB是可以进行UDP通讯的[实现]
1、hostA创建SOCK_DGRAM类型socket于(local_ip_A:3333)2、hostB创建SOCK_DGRAM类型socket于(local_ip_B:4444)3、hostA与server进行UDP连接,server获取到端口映射(nat_ip_A:33333)4、hostB与server进行UDP连接,server获取到端口映射(nat_ip_B:44444)5、hostA、hostB分别从server得到对方的端口映射6、hostA每30秒与server进行一次UDP通讯,以保持端口映射7、hostB同上8、hostA创建SOCK_STREAM类型socket于(local_ip_A:6666),且侦听9、hostB创建SOCK_STREAM类型socket于(local_ip_B:8888)
(注:通常创建时端口应该用0,这里为了方便讨论用固定值)10、hostA启动一ndis例程,拦截源地址为(nat_ip_B:XXXXX),目标地址为(local_ip_A:3333)的UDP包及源地址为(local_ip_A:6666),目标地址为(nat_ip_B:8888)的TCP包11、hostB启动一ndis例程,拦截源地址为(nat_ip_A:XXXXX),目标地址为(local_ip_B:4444)的UDP包及源地址为(local_ip_B:8888),目标地址为(nat_ip_A:6666)的TCP包12、hostB对地址(nat_ip_A:6666)进行连接13、hostB的ndis例程拦截到TCP包(SYN包),丢弃。生成源地址为(local_ip_B:4444),目的地址为(nat_ip_A:33333),数据为整个SYN包的UDP数据包(UDP包1),发送。14、hostA的ndis例程拦截到UDP包1,丢弃。生成源地址为(nat_ip_B:8888),目标地址为(local_ip_A:6666),数据部分为UDP包1的数据的TCP数据包,发送。15、hostA的TCP/IP收到SYN包,发出一个SYN+ACK包16、hostA的ndis例程拦截到TCP包(SYN+ACK包),丢弃。生成源地址为(local_ip_A:3333),目标地址为(nat_ip_B:44444),数据为整个SYN+ACK包的UDP包(UDP包2),发送。17、hostB的ndis例程拦截到UDP包2,丢弃。生成源地址为(nat_ip_A:6666),目标地址为(local_ip_B:8888),数据部分为UDP包2的数据的TCP数据包,发送。18、hostB的TCP/IP收到SYN+ACK包,发出ACK包19、同1320、同1421、至此三次握手完成[备注]
1、其实ndis拦截及重新生成的都是IP包,为了论述方便就直接指明了协议类型
2、hostA、hostB和server进行UDP通讯时端口分别为3333、4444,而后进行伪TCP通讯时也是同一端口,也许可以用不同的吧,没试过,不清楚。