RTSP协议,全称实时流协议(Real Time Streaming Protocol),前文已经简单介绍了RTSP相关协议;
RTSP和RTP(RTCP)
这里再提一下RTSP和RTP/RTCP、RSVP的关系;如图:
RTSP和HTTP
- 相似性:RTSP和HTTP协议都使用纯文本来发送消息,而且RTSP协议的语法也类似于HTTP。 RTSP一开始就是这样设计的,主要是为了能兼容使用之前编写的HTTP协议分析代码。
- 区别:RTSP是有状态的,需要知道当前处于什么状态,也就是说RTSP的命令总是按照顺序发送,某个命令总在另一个命令之前发送。无论处于什么状态,RTSP都不会断开连接。而HTTP则无状态,发送一个命令后,连接就会断开,命令之间没有依赖性。另外,RTSP协议使用554端口,HTTP使用80端口。
RTSP交互过程
#mermaid-svg-uBf7VV3KpimwDymM {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-uBf7VV3KpimwDymM .error-icon{fill:#552222;}#mermaid-svg-uBf7VV3KpimwDymM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uBf7VV3KpimwDymM .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-uBf7VV3KpimwDymM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uBf7VV3KpimwDymM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uBf7VV3KpimwDymM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uBf7VV3KpimwDymM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uBf7VV3KpimwDymM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uBf7VV3KpimwDymM .marker.cross{stroke:#333333;}#mermaid-svg-uBf7VV3KpimwDymM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uBf7VV3KpimwDymM .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-uBf7VV3KpimwDymM text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-uBf7VV3KpimwDymM .actor-line{stroke:grey;}#mermaid-svg-uBf7VV3KpimwDymM .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-uBf7VV3KpimwDymM .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-uBf7VV3KpimwDymM #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-uBf7VV3KpimwDymM .sequenceNumber{fill:white;}#mermaid-svg-uBf7VV3KpimwDymM #sequencenumber{fill:#333;}#mermaid-svg-uBf7VV3KpimwDymM #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-uBf7VV3KpimwDymM .messageText{fill:#333;stroke:#333;}#mermaid-svg-uBf7VV3KpimwDymM .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-uBf7VV3KpimwDymM .labelText,#mermaid-svg-uBf7VV3KpimwDymM .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-uBf7VV3KpimwDymM .loopText,#mermaid-svg-uBf7VV3KpimwDymM .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-uBf7VV3KpimwDymM .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-uBf7VV3KpimwDymM .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-uBf7VV3KpimwDymM .noteText,#mermaid-svg-uBf7VV3KpimwDymM .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-uBf7VV3KpimwDymM .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-uBf7VV3KpimwDymM .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-uBf7VV3KpimwDymM .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-uBf7VV3KpimwDymM .actorPopupMenu{position:absolute;}#mermaid-svg-uBf7VV3KpimwDymM .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-uBf7VV3KpimwDymM .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-uBf7VV3KpimwDymM .actor-man circle,#mermaid-svg-uBf7VV3KpimwDymM line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-uBf7VV3KpimwDymM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
RTSP Client
RTSP Server
OPTIONS request--询问S有哪些方法可用
OPTIONS response--S回应信息中包括提供的所有可用方法
DESCRIBE request--要求得到S提供的媒体初始化描述信息
DESCRIBE response--S回应媒体初始化描述信息,主要是sdp
SETUP request--设置会话的属性,以及传输模式,提醒S建立会话
SETUP response--S建立会话,返回会话标识符,以及会话相关信息
PLAY request--(with Session ID)C请求播放
PLAY response--S回应该请求的信息
Streaming Data (RTP over UDP/TCP)
PAUSE request (with Session ID)--C请求关闭会话
PAUSE response
TEARDOWN request (with Session ID)
TEARDOWN response
RTSP Client
RTSP Server
RTSP交互过程的请求数据解析
由于RTSP跟HTTP的相似,除了在wireshark上捕获RTSP请求,burpsuite一类http流量的测试工具也可以捕获RTSP流量;
OPTIONS
请求服务器提供的可用方法;
OPTIONSrtsp://192.170.1.1/xxx RTSP/1.0CSeq:34
User-Agent:VLC media player(LIVE555 Streaming Media v2005.11.10)
服务器返回对应的可用方法,常见包含OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, SCALE,GET_PARAMETER
RTSP/1.0200OKCSeq:34Date: Tue, May 07202407:32:10GMTPublic:OPTIONS,DESCRIBE,SETUP,TEARDOWN,PLAY,PAUSE,SCALE,GET_PARAMETER//服务器提供的可用的方法
DESCRIBE
请求会话描述信息(SDP)
DESCRIBErtsp://192.170.1.1/xxx RTSP/1.0CSeq:35
User-Agent:VLC media player(LIVE555 Streaming Media v2005.11.10)Accept: application/sdp
详细SDP信息参考SDP协议解析
RTSP/1.0200OKCSeq:35Date: Tue, May 07202407:32:11GMT
Content-Type: application/sdp
Content-length:414
Content-Base: rtsp://192.170.1.20/xxx/
v=0
o=StreamingServer 33314359481INIP4192.170.1.20
s=RTSP Session
c=INIP40.0.0.0
t=00
a=control:*
a=range:npt=0-
m=video 0RTP/AVP96
a=control:trackID=0
a=rtpmap:96H264/90000
a=fmtp:96 packetization-mode=1; profile-level-id=4D0033; sprop-parameter-sets=J00AM+dAPAET8s1AQEB8AAADAAQAAAMAyMQAAfoYAAF7k///wKA=,KO48gA==;
m=audio 0RTP/AVP97
a=control:trackID=1
b=as:32
a=rtpmap:97L16/16000/1
SETUP
客户端提醒服务器建立会话,并确定传输模式;通过trackID参数进行控制,0表示rtp包,1表示rtcp包
SETUP trackID=1RTSP/1.0CSeq:37
User-Agent:VLC media player(LIVE555 Streaming Media v2005.11.10)Transport:RTP/AVP/TCP;unicast;interleaved=2-3Session:1012;timeout=65
服务端返回会话标识,Session值;
RTSP/1.0200OKCSeq:37Date: Tue, May 07202407:32:11GMTTransport:RTP/AVP/TCP;unicast;destination=192.170.1.20;source=192.170.1.20;interleaved=2-3Session:1012;timeout=65
PLAY
播放请求;
PLAYrtsp://192.170.1.20/xxx/RTSP/1.0CSeq:38
User-Agent:VLC media player(LIVE555 Streaming Media v2005.11.10)Session:1012;timeout=65Range: npt=0.000-
返回流数据;
RTSP/1.0200OKCSeq:38Date: Tue, May 07202407:32:11GMTRange: npt=0.000-Session:1012RTP-Info: url=rtsp://192.170.1.20/;seq=0
$../....H.....tx'k..K4{s>/..f..BI.....22 .(`.o%....$.........tz.....E= ...........#$.......H.....tx(.<.$....`..H.....tx<.. ..F!.....1d.....%2.h 6...h%q.|.te.zs........u.5..X...)y..x...t.C....6s..SE..F.....m[..... .'b/.^.GbV..^n.E.5=7....g..v.ZD;..-z.-..S%.......4M..>E6.TK....I2pC.....aE.epb.....{......~..h*.7...MY...."..x....Om....|T.7...TI,B+DO+z.b.Z...E..3.-.|T..,.....P%.G.../...V.H.Y.....><...........]...1_qq......+[............?.c^....\...y.........*8T....3L.....>3_x.=.84.WG!r..k....V.......x#..a}./J..?t...C...2...W...U....X.[.CB...?v...e..
TEARDOWN
客户端发起关闭请求;
TEARDOWNrtsp://192.170.1.20/xxx/RTSP/1.0CSeq:38Session:1012
User-Agent:VLC media player(LIVE555 Streaming Media v2005.11.10)
服务器回应关闭会话;
RTSP/1.0200OKServer: UServer 0.9.7_rc1
Cseq:38Session:1012
SDP协议
SDP(Session Description Protocol)是一个描述多媒体通信会话的格式,用来在会话发起者和参与者之间交换会话的参数和能力。SDP 本身并不传送媒体数据,它只描述了媒体流的元数据,比如媒体类型(音频、视频、文本等)、格式、传输协议和网络地址。
v=0
o=StreamingServer 33314359481INIP4192.170.1.20
s=RTSP Session
c=INIP40.0.0.0
t=00
a=control:*
a=range:npt=0-
m=video 0RTP/AVP96
a=control:trackID=0
a=rtpmap:96H264/90000
a=fmtp:96 packetization-mode=1; profile-level-id=4D0033; sprop-parameter-sets=J00AM+dAPAET8s1AQEB8AAADAAQAAAMAyMQAAfoYAAF7k///wKA=,KO48gA==;
m=audio 0RTP/AVP97
a=control:trackID=1
b=as:32
a=rtpmap:97L16/16000/1
- v=(版本) - 指定SDP的版本号,目前通常为0。
- o=(所有者/创建者和会话ID) - 描述会话的所有者,包含用户名、会话ID、会话版本、网络类型、地址类型和所有者地址。
- s=(会话名称) - 会话的名字。
- c=(连接信息) - 网络类型、地址类型和连接地址。
- t=(时间描述) - 会话的开始和结束时间。
- a=(属性) - 会话属性描述(可选),可以是媒体属性或会话属性,不同的属性有不同的含义。
- m=(媒体描述) - 描述媒体类型、端口、协议和格式。
- *i=(会话信息) - 提供有关会话的额外信息(可选)。
i=A Seminar on the session description protocol
- u=(URI) - 描述与会话相关的更多信息的URI(可选)。
u=http://www.example.com/seminars/sdp.pdf
- e=(电子邮件地址) - 提供会话联系人的电子邮件地址(可选)。
[email protected]
- p=(电话号码) - 提供会话联系人的电话号码(可选)。
p=+1 617 555-6011
- b=(带宽信息) - 指定会话或媒体的带宽信息(可选)。
b=CT:384
- *r=(重复时间) - 会话的重复时间(可选)。
r=604800 3600 0 90000
- *z=(时区调整) - 会话的时区偏移量(可选)。
z=2882844526 -1h 2898848070 0
- *k=(加密密钥) - 指定媒体加密的密钥(可选且不推荐使用)。
k=clear:1234
以上是SDP协议中的一些主要字段。SDP是非常灵活的,可以包含多个媒体描述m和多个属性a,每个描述可以有自己的设置,如编解码器、带宽限制和其他媒体特定属性,业务上可以在这个参数上自定义使用。
RTSP安全测试
python脚本
import cv2
# RTSP URL of the video stream
rtsp_url ='rtsp://192.168.137.81:554/xxx'# Create a VideoCapture object
cap = cv2.VideoCapture(rtsp_url)# Check if the video stream is opened correctlyifnot cap.isOpened():print("Error: Could not open video stream.")else:print("Video stream opened successfully.")# Loop to display the frameswhile cap.isOpened():# Capture frame-by-frame
ret, frame = cap.read()# If frame is read correctly ret is Trueifnot ret:print("Can't receive frame (stream end?). Exiting ...")break# Display the resulting frame
cv2.imshow('RTSP Stream', frame)# Press 'q' on the keyboard to exitif cv2.waitKey(1)&0xFF==ord('q'):break# When everything is done, release the VideoCapture object
cap.release()# Closes all the frames
cv2.destroyAllWindows()
VLC等连接工具
burpsuite等http流量请求抓包工具
RTSP安全实践
使用RTSPS
观察RTSP的交互过程后,我们可以发现RTSP没有任何权限验证,也没有加解密过程(即使有加密,也是明文传输加密密钥)。因此,RTSP并不是一个安全的协议,与http类似,RTSP有自己的安全版本RTSPS,通过SSL/TLS进行通道加密,以确保传输数据的保密性和完整性。然而,RTSP常用于嵌入式设备摄像头中,这类IoT的场景由于性能等原因的限制,无法使用RTSPS。那么,针对这类场景,有哪些相对安全的方案可以使用呢?
身份验证
因为RTSP是基于HTTP实现的,所以也可以使用HTTP相关的认证服务,包括不限于
- HTTP基础认证(Basic Authentication)
- HTTP Digest 认证
- WS-Security(Web Services Security,简称WSS)
基本就是在服务之前添加一个认证授权,但是在局域网环境下,在配网阶段或者服务第一次开启的时候,需要让用户配置一个账号密码;
私有加密
获取RTSP流量后,主要包括视频和音频流。如果对数据进行加密处理,即使被获取,也无法解析播放。
常见的加密或数据处理方法包括:
- 数据偏移(非加密)
- 新增一个字段(非加密)
- 使用AES加密或其他常见的加密方案
虽然在私有加密中出现了多个非加密的方案,但由于视频流需要实时率,加上嵌入式设备的数据处理能力有限,视频流的数据量较大,因此前两种方法是常见的处理方案。
即使采用AES加密视频流数据,加密key也需要在发送端和接收端存储,且通常是固定的key。一旦被分析提取,其效果等同于未加密。在性能允许的情况下,相对安全的方案是通过用户在身份验证过程中配置的账号密码来衍生对应的加密key。这样,两端都有key并且key不是固定的,但在实际场景下这种方案较难实现。
其他
- 限制连接数
- 网络隔离
这里是有一些特定场景的限制,具体也要看业务需求;当然局域网服务本身就很难实现的不存在风险一说,这里也只是为了在有限的条件下达到最好的效果,如果还有其他更好的方案也可以交流。
版权归原作者 sam.li 所有, 如有侵权,请联系我们删除。