upnp原理

WANIPConnection

参考:http://upnp.org/specs/gw/UPnP-gw-WANIPConnection-v2-Service.pdf

  1. AddPortMapping()

  2. NAT

  3. upnp流程
    最多进行4层映射,第一层路由通过/proc/net/route获取本地网关,也就是route -n的功能,第一层映射成功后,可以根据GetExternalIPAddress获得该层路由出口ip,如果出口ip为内网ip,说明还有多层路由,traceroute可以跟踪路由信息,如traceroute -m 4 -w 1 -q 2 www.baidu.com,设置为各层路由的网关,使用出口ip作为NewInternalClient,发送upnp映射请求给各层路由的网关,尝试多层映射。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#define UPNP_MULTICAST "239.255.255.250"
#define UPNP_MULTICAST_PORT 1900
#define UPNP_SERVICE_WANIP "urn:schemas-upnp-org:service:WANIPConnection:1"
#define UPNP_SERVICE_WANPPP "urn:schemas-upnp-org:service:WANPPPConnection:1"

struct sockaddr_in addr = { 0 };
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(UPNP_MULTICAST);
addr.sin_port = htons(UPNP_MULTICAST_PORT);

//发送组播搜索路由器
char buf[1024] = { 0 };
snprintf(buf, sizeof(buf), "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 6\r\nST: %s\r\n\r\n", UPNP_SERVICE_WANPPP);
sendto(sock, buf, strlen(buf), 0, (sockaddr*)&addr, sizeof(addr);

memset(buf, 0, 1024);
snprintf(buf, sizeof(buf), "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 6\r\nST: %s\r\n\r\n", UPNP_SERVICE_WANIP);
sendto(sock, buf, strlen(buf), 0, (sockaddr*)&addr, sizeof(addr))

//还要循环发给各级网关
for (auto it = gatewaySet.begin(); it != gatewaySet.end(); ++it) {
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(it->c_str());
addr.sin_port = htons(UPNP_MULTICAST_PORT);

snprintf(buf, sizeof(buf), "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 6\r\nST: %s\r\n\r\n", UPNP_SERVICE_WANPPP);
sendto(sock, buf, strlen(buf), 0, (sockaddr*)&addr, sizeof(addr));

memset(buf, 0, 1024);
snprintf(buf, sizeof(buf), "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 6\r\nST: %s\r\n\r\n", UPNP_SERVICE_WANIP);
sendto(sock, buf, strlen(buf), 0, (sockaddr*)&addr, sizeof(addr))
}

//接收路由器的响应
char buf[4096] = { 0 };
socklen_t addrLen = sizeof(sockaddr_in);
recvfrom(sock, buf, sizeof(buf) - 1, 0, (sockaddr*)&addr, &addrLen);

解析流程如下:

  • GetExternalIPAddress,获取externalIp,作为下次映射的localIp
  • CheckPortMapping
  • DelPortMapping
  • AddPortMapping
  • CheckPortMapping

WANIPv6FirewallControl

参考:http://upnp.org/specs/gw/UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf

  1. AddPinhole()
  2. UpdatePinhole()
  3. DeletePinhole()
  4. GetOutboundPinholeTimeout()
  5. GetFirewallStatus()
  6. GetPinholePackets()
  7. CheckPinholeWorking()

在 IPv4 中,NAT(网络地址转换)是缓解 IPv4 地址短缺的流行服务。例如,NAT 允许私有网络上的多台主机使用单个公共 IP 地址访问 Internet。 IPv6 的设计部​​分是为了纠正 IPv4 中的某些缺陷。特别是,IPv6 地址空间比 IPv4 地址空间大得多,因此希望不存在 IPv6 地址短缺的风险。
因此,IPv6 不再需要 NAT,恢复了端到端的通信范式。然而,使用 IPv4 NAT 的副作用之一是许多供应商和用户认为 NAT 通过隐藏设备的 IP 地址来为设备提供一些基本的安全性,从而保护设备免受外部攻击。
许多专家对 NAT 的假定安全声明提出异议。然而,许多供应商和用户可能希望防火墙服务保护内部主机免受外部访问,以便内部设备继续具有抵御外部攻击的基本安全性。
在 IPv6 防火墙很常见的可能场景中,如果有一种类似于 NAT 穿越的方式来动态控制防火墙,那么对某些应用程序将是有益的。在这种情况下,IPv6 IGD 供应商可以实施 WANIPv6FirewallControl 服务(而不是 WANIPConnection 服务)以允许 UPnP 控制点控制 IGD 的防火墙。
对于使用以前的 WANIPConnection 服务的 UPnP CP,使用 WANIPv6FirewallControl 服务所需的返工量有望减少,因为这两种服务非常相似。





nephen wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
坚持原创技术分享,您的支持将鼓励我继续创作!