UDP穿透

415 阅读5分钟
    1. 需求

    • 不公开IP和端口的前提下,让不同局域网内的PC端建立连接。
    1. 现实的网络环境

    • 如下图,我们的家庭设备(PC/手机/Pad)连接外网,需要先通过光猫拨号(PPPoE)连接到运营商,由运营商验证、分配临时IP后发送请求到外网中的域名服务器(DNS),再由域名服务器将请求转发到具体的服务器。

      • 这其中,外网提供访问的服务器会购买固定IP发布到域名服务器,域名服务器通过「域名-IP」对应表解析用户访问的域名,转发到固定IP的服务器。
      • 通过拨号上网的一方由运营商随机分配临时IP组建局域网,在断网后临时IP被回收,再联网未必是上一个IP。
      • 在同一时间段内,无论局域网内有几台联网设备,对外网来说都是一个临时IP,同一局域网内的设备连接外网只是端口不同。
    1. 网络环境引出的问题

    • 1> 若通讯双方都是PC拨号连接上网(临时IP),

      • 如何知道对方主机的内网IP(局域网内共用一个临时IP,如何区分哪个是目标主机)?
      • 临时IP发生变化时, 连接怎么保持?
    • 2> 猫/路由器的防火墙默认不允许PC在外网当服务器(把内网的IP信息暴露给外网),也不允许外网外网IP主动连接内网。即便可以将内网IP暴露出去,也要面临:

      • 你公布的临时IP并没有发布到域名服务器,若想访问,只能让域名服务器之间不断发出查询,直到查到你的运营商才能建立反馈,这个过程是非常缓慢的。
      • 安全风险很高,这意味着各种软件、程序甚至不发请求都可能由此访问、控制你的机器。
    • 那是否有一种方法可以临时地、隐蔽地、方便地建立连接进行大数据量传输?👇
    1. 从协议入手解决问题 --- 通讯双方都是拨号上网

    • TCP方式要求只有双方TCP能够直连时才能运作,但往往真实的情况是双方很难达成一个直连。

      • 临时ip的问题。不知道对方主机的内网IP和端口无法建立连接;临时IP变更后每次都得重新建立连接。
      • 防火墙。防火墙禁止外网IP主动连接内网,握手的信息都放不进来。
      • ip公开后的安全性隐患。
      • 效率低,每次操作需要应答。因此TCP方式在频繁的、有实时性要求的数据传输中(如: 屏幕监控)存在隐患。
    • 虽然UDP不安全,但又提供一个很好的契机 --- 猫后面的主机和服务器建立UDP连接后,数据的传输是可以穿透猫精准地传输到我们的主机。
    • 通过UDP通信,客户端完全不关心数据是从哪来的,这就是UDP不安全不可靠的点,无需三次握手第一次发连接包就可以带数据过去,即便面对的是个非法服务器。因此倘若服务器内部是通过UDP与用户建立通信,这样的接口会被默认为不安全的,不能在这上进行如用户登录这类的校验(如人在西安, 模拟在武汉登录, UDP通信是发现不了的)。
    • UDP常用于传输音视频数据(效率高,实时性要求高),如:IP电话、视频会议、直播。如果有缺帧(丢包)的情况,可以向服务端请求重新发丢失的帧;若不请求就默认收到,服务端会接着发后续的帧 --- 高效率。
    1. UDP穿透的方案和原理

    • 必须有台公网服务器,以UDP方式开IP和端口
    • 主机通过UDP连接到服务器,登录,服务器获取到该主机的IP和端口。
    • 从属机通过UDP连接到服务器,服务器是手拿主、从机的IP和端口的。
    • 服务器可以把从属机的ip和端口告诉主机,此时主机就可以直接精准地向从属机发送数据传输,从属机并不知道这个数据是从服务器发来的还是从机。当然服务器也可以把主机信息告诉从机,这样能就实现主从机互发(此时服务器只用保持与主从机的连接即可, 与任一断开可能导致它的端口消失. 这也是穿透的根本原理)。

      • 对主机从机来说, 防火墙要开个口子允许接收你主动连接的服务器发送的应答数据(注意, 主动连接, 说明防火墙放行的这个连接是由内网的人主动发起的, 外网的主动向内网发起请求就会被防火墙拦截, 说明发起这步它是单向的),主机或从机在接收服务器应答后,不关闭套接字即可持续交互。
      • 对公网服务器来说,IP和端口都是公开的,服务器之间可以很随意地互相通信.
    • 若再有同局域网从属机连进来会重新开ip或端口(一般是端口区别),因此不会混淆。
    • 通过这种方式实现两台机器在跨网段和跨网络的情况下进行互联,这就是UDP打洞。
  • 现实中一般是UDP和TCP结合使用:

    • 一般会通过TCP方式建立连接(像http这种就遵循TCP协议, 因此还是需要用到TCP),播放音视频时,建立UDP连接来发送数据。
    • 这其中隔一段时间通过TCP向服务端发一次报告告诉服务端用户还在(这被称为"❤ 心跳"),服务端检测到有心跳后就会不断下发。