zoukankan      html  css  js  c++  java
  • Tcp and Udp NAT 穿越穿透打洞

    在网络上搜索了下,没有发现简介而全面的相关文章,下面将英文资料中获取的相关只是整理成此片,以飨乡邻。

    所用属于和代号。

    A : 私网中的主机,设私网IP为192.168.1.2

    B : 另一私网中的主机,设私网IP为192.168.245.10

    S : 公网中的主机,在此做中间服务器,设IP为223.11.11.11

    NAT: Net Address Transmission,在此可以理解为路由器

    NAT-A:A所在的私网路由器,假设公网IP为188.11.11.11

    NAT-B:B所在的私网路由器,假设公网IP为199.11.11.11

    打洞需要突破几个关键的壁垒,

    1. A,B互相无法知道对方公网IP,A,B也不知道自己公网IP。

        解决办法:借助公网服务器S牵线搭桥。

    2. NAT会阻挡不明来源的信息货连接。就是说,即使A知道B的公网地址(包括IP和端口)也无法给B连接请求或信息,因为NAT-B会阻挡不明来源的    信息或连接,此举是NAT过去阻挡SYN攻击的有效手段。

        解决办法:让B先突破NAT-B试图连接NAT-A后的A,当然此举会失败,但是会在NAT-B上留下一个印记:“NAT-A是可识别的地址”,所以,随后的

    A-->NAT-A-->NAT-B-->B就会被NAT-B放行。于是连接成功。

    3. 还有很多NAT不支持hairpin,即不支持曲线路由,即假设C,D处于同一内网的主机,那么他们不可通过NAT通信。即:    C-->(NAT-C-->NAT-D)--D是不行的。所以这种情况只能直接用私网地址通信C--->D。

        有幸的是,现在绝大部分NAT都支持将私网主机地址与NAT地址的稳固一致隐射,即:

        假设A(192.168.1.2::1000)第一次经由NAT-A时隐射到地址(188.11.11.11::1111)到达S,那么以后从A(192.168.1.2::1000)出来的信息或连接都会到NAT-A (188.11.11.11::1111)后,再到公网。也就是说,(188.11.11.11::1111)总是A(192.168.1.2::1000)的公网地址,这一映射会在NAT-A上保留一段时间(大于20秒),这使得穿越成为可能,不管是Tcp还是Udp,原理一样。

    Udp穿越步骤:

    1) A发Udp包给S,保重附带有A的私网地址(IP::Port),S又从Udp头中可以获得A的公网地址。

    2) B发Udp包给S,保重附带有A的私网IP地址,S又从Udp头中可以获得B的公网地址。

    3) S将A的公网地址和私网地址告诉B, 将B的公网地址和私网地址告诉A

    4) A,B分别向对方的公网和私网地址发送信息,并等待接受对方发过来的信息。最早返回回来的信息的源地址,将被采纳为对方的有效地址,不管是公网的还是私网的地址,此后就直接与这一有效地址通信。需要说明的是:假设A先于B发出了第一个消息,那么A的第一个消息会被NAT-B阻挡而失败,这一发出的消息会在NAT-A上留下印记,标明B的公网地址为可信的,然后B的任何消息就可以顺利到达A,同时B第一消息会在NAT-B上留下印记,标明A为可信地址,此后A的消息就可以到达B。

        这样,AB就可以正常通信。即使AB除以同一私网。

    Tcp穿越步骤:

        原理基本和Udp穿越类似,不同的是Tcp在使用私网IP发起连接(connect and recv)的同时,要在此私网地址上启动侦听:listen and Accept. 但是自XP Service Pack 2之后的Windows系统和所有Unix或linux系统的 socket都有属性SO_REUSEADDR,这就可以实现。对于不支持socket SO_REUSEADDR属性的系统,可以采用顺序连接来打洞的方式。即A与S连接通信之后,断开连接,然后尝试与B连接,失败后listen and AccpetB的连接。

    希望是对你有意义的一段文字。

        参考文档:

    http://www.brynosaurus.com/pub/net/p2pnat/#rfc3489


    这里有demo代码,可看看是怎么实现的。
    代码演示了udp打洞技术的实现;
    http://download.csdn.net/detail/supermagician/5945753

  • 相关阅读:
    ADO.NET(一)数据库连接串的几种写法
    C#事件Event--猫捉老鼠
    事件
    委托
    C# .Net List<T>中Remove()、RemoveAt()、RemoveRange()、RemoveAll()的区别,List<T>删除汇总
    上传下载
    验证数据
    RSADemo2
    随机数
    二维码生成类
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318743.html
Copyright © 2011-2022 走看看