内容简介:通用即插即用(英语:Universal Plug and Play,简称 UPnP )是 1999 年由微软推出的,“通用即插即用论坛”(UPnP™ Forum)推广的一套网络协议。该协议的目标是使家庭网络(数据共享、通信和娱乐)和公司网络中的各种设备能够相互无缝连接,并简化相关网络的实现。UPnP通过定义和发布基于开放、因特网通讯网协议标准的UPnP设备控制协议来实现这一目标。UPnP 这个概念是从即插即用(Plug-and-play)派生而来的,即插即用是一种热拔插技术。
目录
什么是 UPnP ?
通用即插即用(英语:Universal Plug and Play,简称 UPnP )是 1999 年由微软推出的,“通用即插即用论坛”(UPnP™ Forum)推广的一套网络协议。该协议的目标是使家庭网络(数据共享、通信和娱乐)和公司网络中的各种设备能够相互无缝连接,并简化相关网络的实现。UPnP通过定义和发布基于开放、因特网通讯网协议标准的UPnP设备控制协议来实现这一目标。
UPnP 这个概念是从即插即用(Plug-and-play)派生而来的,即插即用是一种热拔插技术。
看以上的解释看着是不是觉得云里雾里,我们用通俗的话讲就是:
UPnP 是运行在 UDP 1900 端口上的,使用 XML/SOAP 对远程设备进行查询和控制的协议
该协议有以下的几个特点
- 协议设计于上世纪 90 年代到 20 世纪初 (意味着漏洞多多)
- 协议控制部分基于 SOAP(html+xml) (意味着简单)
- UPnP多用在物联网设备和智能路由器上 (意味着使用广泛)
为什么会有 UPnP 协议?
UPnP 最大的愿景是希望任何设备一旦连接上网络,所有在网络上的设备马上就能知道有新设备加入,这些设备彼此之间能互相通信,更能直接使用或者控制它,一切都不需要人工设置,完全的即插即用。
理想是丰满的,但现实很骨感,哪有这么十全十美的方案,从发布至今 UPnP 因在设计上的缺陷和各个厂家在协议具体实现上的错误导致出现了许许多多的安全漏洞,上文提到物联网设备和智能路由器多使用 UPnP,就拿几十块的路由器来说,他们的系统在出厂时就已经写死,虽然有更新功能,但是没人有这个意识去更新家里路由器的系统,于是发现漏洞时无法及时更新,导致一些很严重漏洞至今还充斥在暴露于互联网当中的物联网设备和智能路由器中,这也是我写本文的原因。
UPnP 实验环境搭建
为了进一步学习 UPnP 协议,我在 Alpine 操作系统里虚拟机安装了 MiniUPnP
Alpine Linux的包管理器为 apk
,安装 MiniUPnP 之前需要启用 edge
源:
编辑 /etc/apk/repositories
文件,去掉 http://mirrors.tuna.tsinghua.edu.cn/alpine/edge/community
前的 #
号
安装
apk install miniupnp
生成随机 uuid
cat /proc/sys/kernel/random/uuid
写入随机的 uuid 到 /etc/miniupnpd/miniupnpd.conf 里
我的配置文件内容如下
alpine:~# grep -v '^#\|^$' /etc/miniupnpd/miniupnpd.conf listening_ip=eth0 http_port=31337 enable_natpmp=yes enable_upnp=yes bitrate_up=1000000 bitrate_down=10000000 secure_mode=no system_uptime=yes notify_interval=60 clean_ruleset_interval=600 uuid=ffb9c20a-9c5e-4012-9cf1-03a5ca9a9820 serial=12345678 model_number=1 allow 1024-65535 192.168.0.0/24 1024-65535 allow 1024-65535 192.168.1.0/24 1024-65535 allow 1024-65535 192.168.0.0/23 22 allow 12345 192.168.7.113/32 54321 deny 0-65535 0.0.0.0/0 0-65535
启动 MiniUPnP
miniupnpd -f /etc/miniupnpd/miniupnpd.conf -i eth0 -d
UPnP 协议分析
相比于 OSI 七层模型(七层模型,亦称OSI(Open System Interconnection)参考模型,是参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系),UPnP 有 6 层
我们重点看其中的三个:发现、描述和控制。以下的图展示了这 3 层是如何组织在一起的:
这图看不懂没关系,先有个初步的印象,下文中会详细分析
UPnP 所有的内容已在官方文档的 1.1 和 2.0 版本中列出
发现
给定一个IP地址,UPnP网络中的第一步是发现。当一个设备被加入到网络中,UPnP检测协议允许该设备向控制点广播自己的服务。类似地,当一个控制点加入到网络中的时候,它也能够搜索到网络中存在的、感兴趣的设备相关信息。这两种类型的基础交互是一种仅包含少量、重要相关设备信息或者它的某个服务。比如,类型、标识和指向更详细信息的链接。
UPnP检测协议是基于简单服务发现协议的,简单服务发现协议(SSDP,Simple Service Discovery Protocol)是一种应用层协议,是构成通用即插即用(UPnP)技术的核心协议之一,SSDP 协议是在 HTTPU 和 HTTPMU 的基础上实现的协议( HTTPU 协议
是指在 UDP 基础上实现的通常在TCP上传送的HTTP协议。HTTPU 协议被主要运用在 UPnP 协议,特别是 UPnP协议簇中的 SSDP 协议)
MiniUPnP 启动后使用 wireshark 抓包会看到 MiniUPnP 会向专用组播地址 233.255.255.0
发出 SSDP
协议的 NOTIFY
请求来宣布他的存在
内容如下
NOTIFY * HTTP/1.1 HOST: 239.255.255.250:1900 CACHE-CONTROL: max-age=120 LOCATION: http://172.16.1.134:31337/rootDesc.xml SERVER: Linux/4.14.69-0-vanilla UPnP/1.1 MiniUPnPd/2.1 NT: upnp:rootdevice USN: uuid:ffb9c20a-9c5e-4012-9cf1-03a5ca9a9820::upnp:rootdevice NTS: ssdp:alive OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01 01-NLS: 1551501733 BOOTID.UPNP.ORG: 1551501733 CONFIGID.UPNP.ORG: 1337
因为 UDP 协议是不可靠的协议,所以他会发送多次, LAN 测并没有 UPnP 设备,因此 NOTIFY 请求不会得到回应
这就是 UPNP 协议的 发现阶段
描述
UPnP 网络的下一步是描述。当一个控制点检测到一个设备时,它对该设备仍然知之甚少。为了使控制点了解更多关于该设备的信息或者和设备进行交互,控制点必须从设备发出的检测信息中包含的 URL 获取更多的信息。某个设备的 UPnP 描述是XML的方式,包括品牌、厂商相关信息,如型号名和编号、序列号、厂商名、品牌相关 URL 等。描述还包括一个嵌入式设备和服务列表,以及控制、事件传递和存在相关的 URL 。对于每种设备,描述还包括一个命令或动作列表,包括响应何种服务,针对各种动作的参数;这些变量描述出运行时设备的状态信息,并通过它们的数据类型、范围和事件来进行描述
当 LAN 侧主机搜索 UPnP 主控设备时,会向组播地址发送 M-SEARCH 包,而路由器收到包之后,会返回一个包来通知LAN侧主机
我们使用 UDP 协议向组播地址 233.255.255.0 的 1900 端口发送组播, python 代码如下:
import socket M_SEARCH = b'M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.255.250:1900\r\nST:urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\nMAN:"ssdp:discover"\r\nMX:3\r\n\r\n' def m_search(ip, M_SEARCH): data = '' with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: s.connect((ip, 1900)) s.settimeout(3) try: s.sendall(M_SEARCH) while True: data = s.recv(4096) print(data.decode()) if not data: break except socket.timeout as timeout: pass else: print(response) s.close() if __name__ == "__main__": m_search('223.255.255.0', M_SEARCH)
使用 wireshark 抓包,过滤 SSDP 协议,我们会看到 MiniUPnP 回应了我们的组播
编号为 1 的包是我们发出的组播包,编号为 6 的包是 MiniUPnP 回应我们的包,如下图所示
组播包发送的 SSDP 请求内容是:
M-SEARCH * HTTP/1.1 HOST:239.255.255.255.250:1900 ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1 MAN:"ssdp:discover" MX:3
收到的 SSDP 协议响应内容是:
HTTP/1.1 200 OK CACHE-CONTROL: max-age=120 ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1 USN: uuid:ffb9c20a-9c5e-4012-9cf1-03a5ca9a9820::urn:schemas-upnp-org:device:InternetGatewayDevice:1 EXT: SERVER: Linux/4.14.69-0-vanilla UPnP/1.1 MiniUPnPd/2.1 LOCATION: http://172.16.1.134:31337/rootDesc.xml OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01 01-NLS: 1551501733 BOOTID.UPNP.ORG: 1551501733 CONFIGID.UPNP.ORG: 1337
UPnP 规范 1.1 和 2.0 版本中都记录了以上各个字段的作用和解释等所有内容
我们在本文中只关心 SSDP 响应内容中的 LOCATION
,在这里为 http://172.16.1.134:31337/rootDesc.xml
浏览器打开访问,内容如下:
<?xml version="1.0"?> <root xmlns="urn:schemas-upnp-org:device-1-0" configId="1337"> <specVersion> <major>1</major> <minor>1</minor> </specVersion> <device> <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType> <friendlyName>Linux router</friendlyName> <manufacturer>Linux</manufacturer> <manufacturerURL>http://www.kernel.org/</manufacturerURL> <modelDescription>Linux router</modelDescription> <modelName>Linux router</modelName> <modelNumber>1</modelNumber> <modelURL>http://www.kernel.org/</modelURL> <serialNumber>12345678</serialNumber> <UDN>uuid:ffb9c20a-9c5e-4012-9cf1-03a5ca9a9820</UDN> <serviceList> <service> <serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1</serviceType> <serviceId>urn:upnp-org:serviceId:L3Forwarding1</serviceId> <SCPDURL>/L3F.xml</SCPDURL> <controlURL>/ctl/L3F</controlURL> <eventSubURL>/evt/L3F</eventSubURL> </service> </serviceList> <deviceList> <device> <deviceType>urn:schemas-upnp-org:device:WANDevice:1</deviceType> <friendlyName>WANDevice</friendlyName> <manufacturer>MiniUPnP</manufacturer> <manufacturerURL>http://miniupnp.free.fr/</manufacturerURL> <modelDescription>WAN Device</modelDescription> <modelName>WAN Device</modelName> <modelNumber>20181224</modelNumber> <modelURL>http://miniupnp.free.fr/</modelURL> <serialNumber>12345678</serialNumber> <UDN>uuid:ffb9c20a-9c5e-4012-9cf1-03a5ca9a9821</UDN> <UPC>000000000000</UPC> <serviceList> <service> <serviceType>urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1</serviceType> <serviceId>urn:upnp-org:serviceId:WANCommonIFC1</serviceId> <SCPDURL>/WANCfg.xml</SCPDURL> <controlURL>/ctl/CmnIfCfg</controlURL> <eventSubURL>/evt/CmnIfCfg</eventSubURL> </service> </serviceList> <deviceList> <device> <deviceType>urn:schemas-upnp-org:device:WANConnectionDevice:1</deviceType> <friendlyName>WANConnectionDevice</friendlyName> <manufacturer>MiniUPnP</manufacturer> <manufacturerURL>http://miniupnp.free.fr/</manufacturerURL> <modelDescription>MiniUPnP daemon</modelDescription> <modelName>MiniUPnPd</modelName> <modelNumber>20181224</modelNumber> <modelURL>http://miniupnp.free.fr/</modelURL> <serialNumber>12345678</serialNumber> <UDN>uuid:ffb9c20a-9c5e-4012-9cf1-03a5ca9a9822</UDN> <UPC>000000000000</UPC> <serviceList> <service> <serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType> <serviceId>urn:upnp-org:serviceId:WANIPConn1</serviceId> <SCPDURL>/WANIPCn.xml</SCPDURL> <controlURL>/ctl/IPConn</controlURL> <eventSubURL>/evt/IPConn</eventSubURL> </service> </serviceList> </device> </deviceList> </device> </deviceList> <presentationURL>http://172.16.1.134/</presentationURL> </device> </root>
这个 XML 文件就是此 UPnP 设备的描述文件,该文件详细描述了设备的各类信息,结构如下
我们重点看 service
标签, 内容如下
<service> <serviceType>urn:schemas-upnp-org:service:WANIPConnection:1</serviceType> <serviceId>urn:upnp-org:serviceId:WANIPConn1</serviceId> <SCPDURL>/WANIPCn.xml</SCPDURL> <controlURL>/ctl/IPConn</controlURL> <eventSubURL>/evt/IPConn</eventSubURL> </service>
其中
WANIPConnection /WANIPCn.xml /ctl/IPConn
我们访问其中的 SCPDURL
, 内容太多,我只留了一个省略了其他标签,内容如下:
<scpd> <specVersion> <major>1</major> <minor>1</minor> </specVersion> <actionList> <action>...</action> <action> <name>GetStatusInfo</name> <argumentList> <argument> <name>NewConnectionStatus</name> <direction>out</direction> <relatedStateVariable>ConnectionStatus</relatedStateVariable> </argument> <argument> <name>NewLastConnectionError</name> <direction>out</direction> <relatedStateVariable>LastConnectionError</relatedStateVariable> </argument> <argument> <name>NewUptime</name> <direction>out</direction> <relatedStateVariable>Uptime</relatedStateVariable> </argument> </argumentList> </action> <action>...</action> </actionList> <serviceStateTable> <stateVariable>...</stateVariable> <stateVariable sendEvents="no"> <name>Uptime</name> <dataType>ui4</dataType> </stateVariable> <stateVariable>...</stateVariable> </serviceStateTable> </scpd>
此 SCPD xml 文件中需要重点关注的是 actionList
里的 action
,这些action都是可以调用的
在上面的 xml 文件里 action 的名称为 GetStatusInfo
,他有一个参数叫 NewUptime
,参数的 direction
标签的值为 out,这说明 NewUptime
是返回参数,如果为 in
,则请求该 action
时我们需要提供此参数。
在 serviceStateTable
里的 stateVariable
又出现了一次 Uptime
stateVariable
说明了 action
的返回参数或请求参数的数据类型, ui4
为 Unsigned 4 Byte int
无符号4字节整数
这就是 UPNP 协议的 描述阶段
控制
UPnP网络的下一步是控制。当一个控制点获取到设备描述信息之后,它就可以向该设备发送指令了。为了实现此,控制点发送一个合适的控制消息至服务相关控制 URL(包含在设备描述中)。控制消息也是通过简单对象访问协议(SOAP)用 XML 来描述的。类似函数调用,服务通过返回动作相关的值来回应控制消息。动作的效果,如果有的话,会反应在用于刻画运行中服务的相关变量
我们对上文中的 GetStatusInfo
action 发起 SOAP 请求,SOAP请求实际上就是 HTTP+xml
请求内容如下:
POST /ctl/IPConn HTTP/1.1 Accept-Encoding: gzip, deflate Content-Length: 315 Soapaction: "urn:schemas-upnp-org:service:WANIPConnection:1#GetStatusInfo" Connection: close User-Agent: Python-urllib/2.7 Host: 172.16.1.134:31337 Content-Type: text/xml; charset=UTF-8 <?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/ SOAP-ENV="urn:schemas-upnp-org:service:WANIPConnection:1"> <SOAP-ENV:Body> <m:GetStatusInfo xmlns:m="http://schemas.xmlsoap.org/soap/envelope"> </m:GetStatusInfo> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
调用结果如下:
返回内容中 uptime 的值为 91315
, 我们使用 python 转换为可读形式
1 day, 1:21:55
这时我们可以看出调用 GetStatusInfo
方法可获取该 UPnP 设备的运行时间,该设备运行了 1天1小时21分钟55秒
这就是 UPnP 的控制层
至此 UPnP 协议的 发现、描述、控制 层都已经按照具体实例讲解完毕
我把此次实验所用的虚拟机已打包成 ova
文件上传到了 网盘 登陆用户名: root
,密码: alpine
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
jQuery基础教程 (第4版)
[美] Jonathan Chaffer、[美] Karl Swedberg / 李松峰 / 人民邮电出版社 / 2013-10 / 59.00
本书由jQuery API网站维护者亲自撰写,第一版自2008上市以来,一版再版,累计重印14次,是国内首屈一指的jQuery经典著作! 作为最新升级版,本书涵盖jQuery 1.10.x和jQuery 2.0.x。本书前6章以通俗易懂的方式讲解了jQuery的核心组件,包括jQuery的选择符、事件、动画、DOM操作、Ajax支持等。第7章和第8章介绍了jQuery UI、jQuery M......一起来看看 《jQuery基础教程 (第4版)》 这本书的介绍吧!