UPnP (Universal Plug and Play) 定义了一组标准的网络协议,使网络里不同设备能够无缝连接、自动配置。
UPnP 最常用的使用场景是"动态端口映射",即根据内网设备的请求,在网关上自动并动态地创建到内网设备的端口映射。
Linux 设备通常使用 miniupnp 来实现 UPnP 协议。
miniupnp
miniupnp 是一组用户态程序,其包括几个程序:
- miniupnpd: daemon - an implementation of a UPnP IGD + NAT-PMP / PCP gateway。
- miniupnpc: client - an UPnP IGD control point
路由器等网关设备上运行的是服务端程序 miniupnpd,用于给内网设备动态创建端口映射。
How it works
内网主机的应用程序在需要进行内网穿透前,对路由器进行一次 UPnP 请求,请求映射一个外网端口(UDP或TCP)到内网主机的端口。路由器上运行的 miniupnpd 随后会执行若干条 iptables 命令,最重要的是这条:(为演示原理,该命令已简化,事实上 miniupnpd 会在 NAT 表下另建一个链)
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 5000 -j DNAT --to-destination 192.168.1.3:5000
这样就动态地在路由器上创建了一个 "Full Cone NAT" 类型的端口映射,从路由器 WAN 网卡(这里是 eth0) IP 的 udp/5000 端口映射到内网设备 192.168.1.3 上的 udp/5000 端口。
UPnP 局限性
- UPnP 涉及 SSDP 组播发现过程,miniupnpd 的默认配置更是会向客户端返回全局映射表,相对而言不太安全,不适合应用于复杂的企业级大型网络及ISP入户网络。
- 一次UPnP请求只能进行一级NAT的映射,当然你也可以转发 UPnP 请求到上级NAT设备,但是似乎至今没有一款家用智能路由器会这么做。这意味着如果你在家使用两台以上的智能路由器级联上网(即双层或多层 NAT),仅通过 UPnP 是无法实现内网穿透的。