SlideShare a Scribd company logo
RTMFP简介
Changming
Sun<me@sunchangming.com>
Brief
• RTMFP - "Real-Time Media Flow Protocol”
• 是Flash与Flash之间的基于UDP的点对点传输协
议
• Adobe的专有协议。
• 2008年在Flash 10.0中首次发布
• 现在在我们每个人的浏览器中。
• 2012年12月提交RFC
• 发明人认为它是An replacement of TCP。
类似协议: webrtc、DCCP、DTLS、ICE(rfc5245).
A brief view(1)
Use it as rpc method:
var nc:NetConnection;
nc = new NetConnection()
nc.connect("rtmfp://127.0.0.1:1935/HelloWorld/");
nc.call("serverFunc1", new
Responder(onReply), ”hello”);
function onReply(result:Object):void {
dlog("onReply received value: " + result);
}
A brief view(2)
Attach Streams to RTMFP Connection:
var nc:NetConnection;
nc = new NetConnection()
nc.connect("rtmfp://127.0.0.1:1935/HelloWorld/");
sendStream = new
NetStream(nc,NetStream.DIRECT_CONNECTIONS);
sendStream.publish("media");
主要内容
• History and Why we need it?
• How to analyze it?
• Layers
– UDP层的Multiplex与加密解密
– 会话建立、密钥协商、NAT穿透
– 类TCP的功能(flow、分片、ACK与重传、拥塞
控制)
History
• 2004年,Matthew Kaufman 和 Michael Thornburgh
在美国加州Santa Cruz成立了Amicima公司,他们
设计了MFP
• 2005年8月1日,MFP开源
• 2006年,Amicima被Adobe收购,MFP变RTMFP
• 2008年,RTMFP在Adobe 10.0中发布
• 2010年6月,Matthew Kaufman跳槽去了Skype
• 2012年12月,Michael Thornburgh代表Adobe公司
向IETF提交了RTMFP协议草案。
Why we need it?
• “To securely deliver media flows over the
Internet”
• Peer to Peer video streaming
• 移动互联网环境下,延迟高,连接易断,IP
易变
• 层次化的组合设计(如tcp+ssl+http)导致建立
连接所需的TTL太多。
—> 在UDP的基础上重新实现TCP+SSL,以及
NAT穿透。
如何分析它?
方法比结论更重要。
Wireshark
Man in the Middle
• 密钥协商采用了Diffie–Hellman算法
• Diffie–Hellman 天生就有漏洞,容易受到中
间人攻击
• Cumulus 做了一个
https://github.com/OpenRTMFP/Cumulus
缺点:使用麻烦
并非处理了所有情况
反向工程(1)
反向工程(2)
Address Space Load Randomization
Address Space Load Randomization
Address Space Load Randomization
D:> dumpbin /headers flashplayer_11_sa_debug_32bit.exe
8140 DLL characteristics
Dynamic base
NX compatible
Terminal Server Aware
如果它的值是8140,就说明打开了”Dynamic base”。用VC的
链接器禁用掉它即可。
D:> link /edit /dynamicbase:NO flashplayer_11_sa_debug_32bit.exe
Tamarin
• Adobe 主导的开源项目
• Flash Player的AVM的核心源码
• 包含GC、bytecode、AMF相关内容
D:flairpcf avmplus.lib avmplus.pat
avmplus.lib: skipped 1731, total 14180
D:flairsigmake avmplus.pat avmplus.sig
avmplus.sig: modules/leaves: 8012/4207, COLLISIONS: 407
RTTI
• 利用RTTI根据从object pointer获取class
name
• 可惜flash player在所有平台下都没有打开
RTTI
• 但是Server有!
• 不仅有RTTI信息,还有大量调试代码,用于
输出调试日志。
Server的调试日志
• 2012-06-12 17:32:07 8328 (d)0000000 rtmfp send message,
session: 08F2F008 flow: 08F22EA0 rel: (-2,-2) kMsgCmd idByte=20
streamId=0 time=0 trxId=1 kEncodingAMF0 _result
cmdData=( kObjectType ( fmsVer= kStringType “FMS/4,5,0,297”,
capabilities= kNumberType 255, mode= kNumberType 1 ) )
arg0=( kObjectType ( level= kStringType “status”, code= kStringType
“NetConnection.Connect.Success”, description= kStringType
“Connection succeeded.”, objectEncoding= kNumberType 3, data=
kArrayType ( version= kStringType “4,5,0,297” ) ) ) -
• 2012-06-12 17:32:07 8328 (i)2581173 rtmfp recv message,
session: 08F2F008 flow: 05624900 kMsgCmdEx idByte=17
streamId=0 time=724 trxId=0 kEncodingAMF0 setPeerInfo
cmdData=( kNullType ) arg0=( kStringType “192.168.15.1:53804” )
arg1=( kStringType “192.168.146.1:53804” ) arg2=( kStringType
“10.4.8.84:53804” ) -
Hook DLL
• https://github.com/snnn/flash-rtmfp-hook
• 找到感兴趣的函数
• 制作DLL
• 注入它!
• Detours
缺点:只能适用于特定平台特定版本的flash
player
版本升级
分享分析结果
协议分层
协议分层
• Packet:Session标识、UDP层的Multiplex、
加密解密。
• Chunks:18种底层消息,用于Session建立、
密钥生成与交换、Keep-alive、NAT穿透、IP
移动、拥塞控制等
• Flow:Framing、Fragmentation、ACK、重传、
拥塞控制、优先级。
• 应用层: 分布式对象与RPC、音频流、视频
流、音视频编解码、Qos。
RTMFP Groups: 组播与P2P routing
Session multiplexing
• UDP Packet = scrambledSessionID + encPart
前4个字节是加扰后的session id
后面是AES加密后的数据
1. 加密是必须的而不是可选的
2. 用session id来关联一个Endpoint,而不是ip
address and port
加密与HMAC
1. Enc(SSEQ+ body), 然后算HMAC
2. ENC(checksum + body)
代表了保障消息完整性的两种模式
承载Chunks
timestamp: 2字节。它的值是从1970-01-01 00:00:00 +0000 (UTC)到现在的毫秒数除以4,
然后取最低2个字节。
timestamp-echo: 2字节。what the timestamp field of a packet received from the other end
would be at the time this packet was transmitted
Padding: 0xFF. Chunk id never be 0xFF.
Chunks类型
session
• initiator hello
• responder hello
• initiator Ikeying
• responder Ikeying
• Redirected IHello
• Forwarded IHello
• responder cookie
change
control
• Ping
• Ping Reply
• Session Close
Request
• Session Close
Ack
Flow
• User Data
• Next User Data
• Buffer Probe
• ACK
• Flow Exception
report
SESSION
会话建立
会话建立涉及的Chunks
• initiator hello
• responder hello
• initiator initial keying
• responder initial keying
• Redirected initiator Hello
• Forwarded Initiator Hello
• responder cookie change
Endpoint Discriminator
• 每个Endpoint有一个EPD
• 每个EPD由1个或多个identity组成
• Identity分两种
– 0xf, peerid
– 0x0a,server url
• PeerID=SHA256(Certificate)
• Certficate: Option List (含公钥等)
4次握手
密钥协商
• DH
• b = g^a (mod p)
• d= g^c (mod p)
• Shared = b^c = d^a = g^(a * c)
• 易受中间人攻击。
• g 和p的选择参考IPSec(rfc2412)和rfc3526
密钥协商
• byte[] sec; byte[] HMAC256(byte[] key,byte[] data);
• byte[] key1=HMAC256(sec,HMAC256(skrc,skic));
• byte[] key2=HMAC256(sec,HMAC256(skic,skrc));
session.encodekey = new SecretKeySpec(Arrays.copyOf(key1,
16), "AES"); //initiator的加密密钥
• session.decodekey = new SecretKeySpec(Arrays.copyOf(key2,
16), "AES"); //responder的加密密钥
NAT穿透
发送时:3种NAT
• Cone: 将src ip映射到一个固定的IP,并且将
src port映射到一个固定的Port,无论dst ip
和dst port是什么。
• Single IP address, symmetric:将src ip映射到
一个固定的IP,将src port映射到一个随机的
port,但是保证对于相同的(dst ip,dst port),
src port始终相同。
• Multiple IP address, symmetric:与上面类似,
但是src ip可能会被映射到多个IP中的一个。
接受时:3种
• Full Cone: 不对收到的包的IP端口做任何限
制. 这种NAT通常被称为static NAT,在外面
看就像是一个透明代理一样。
• Restricted Cone: Restricted Cone会对收到的
包的IP做限制。
• Port Restricted Cone: 它就是在Restricted
Cone的基础上对端口也做了限制。
• 连接性测试: http://cc.rtmfp.net/
打洞
打洞
打洞
打洞
打洞
打洞
Control Chunks
• Ping
• Ping Reply
• Session Close Request
• Session Close Acknowledgement
FLOW
Flow简介
• Flow是单向的
• 每个Flow都有自己的名字
• 建立Flow不需要单独的Chunk。Flow的meta
data随第一个数据包一起发送
• 保障顺序(或不)
• 保障一定送达(或不)
• 每个Flow有自己的窗口控制
Chunks
• User Data
• Next User Data
• Buffer Probe
• ACK
• Flow Exception report
UserData
• uint8_t flags;
varint64 flowid;
varint64 seq;
varint64 fsnOffset;
optional Options options; //当flags & 0x80 !=0
uint8_t data[];
• forwardSequenceNumber = seq- fsnOffset
MessageTypes
• kMsgUserCtrl
• kMsgVirtualUserControl
• kMsgAudio
• kMsgVideo
• kMsgDataEx
• kMsgContainerEx
• kMsgCmdEx
• kMsgData
• kMsgContainer
• kMsgCmd
• kMsgUDP
• kMsgAggregate
• kMsgPresent
ACK
• Data Acknowledgement Bitmap Chunk
– flowID
– bufAvail
– cumAck
– Bitmap (每一位对应一个seq number)
• Data Acknowledgement Ranges Chunk
与上面类似,但是把bitmap换成了rangs
参考资料:
• RFC草案: http://tools.ietf.org/html/draft-
thornburgh-adobe-rtmfp
• 2010年在IETF上的演讲:
http://www.ietf.org/proceedings/10mar/slides/ts
varea-1.pdf
• 2013年对Michael Thornburgh的访谈:
http://www.overdigital.com/2013/02/21/rtmfp-
and-the-ietf-qa-with-co-creator-michael-
thornburgh/
• http://www.sunchangming.com/docs/rtmfp.jsp

More Related Content

PPT
2010 5 d4d393f6
PPTX
Unix socket
PPTX
Mininet Learning Guide(Mininet 学习指南)
PDF
深入浅出Netty l.t
PDF
High performance browser network wired network
PPTX
服务器端性能优化 提升Qps、rt
PPTX
Introduction of netty
PDF
gRPC - 打造輕量、高效能的後端服務
2010 5 d4d393f6
Unix socket
Mininet Learning Guide(Mininet 学习指南)
深入浅出Netty l.t
High performance browser network wired network
服务器端性能优化 提升Qps、rt
Introduction of netty
gRPC - 打造輕量、高效能的後端服務

What's hot (20)

PDF
Juniper ScreenOS 基于Policy的
KEY
ZeroMQ简介
PPTX
部署並執行以太坊智能合約
PDF
OpenResty 项目模块化最佳实践
PDF
再生龍於雲端環境之應用
PDF
Openstack swift, how does it work?
PPTX
以太坊智能合約撰寫簡單教學
PPTX
Golangintro
PPTX
Openstack neutron 原理详解
PDF
Golang server design pattern
PDF
Golang 高性能实战
PPTX
Computer Network 1 TCP/IP
PDF
Golang advance
PPTX
lua & ngx_lua 的介绍与应用
PDF
图解分布式一致性协议Paxos 20150311
PPTX
Shell,信号量以及java进程的退出
PDF
发现和建立多设备之间的数据通信 | 豌豆荚实验室 孙桥
PPT
Jvm内存管理基础
PPT
Effective linux.2.(tools)
PDF
Network Simulator Generator TCL 2.1
Juniper ScreenOS 基于Policy的
ZeroMQ简介
部署並執行以太坊智能合約
OpenResty 项目模块化最佳实践
再生龍於雲端環境之應用
Openstack swift, how does it work?
以太坊智能合約撰寫簡單教學
Golangintro
Openstack neutron 原理详解
Golang server design pattern
Golang 高性能实战
Computer Network 1 TCP/IP
Golang advance
lua & ngx_lua 的介绍与应用
图解分布式一致性协议Paxos 20150311
Shell,信号量以及java进程的退出
发现和建立多设备之间的数据通信 | 豌豆荚实验室 孙桥
Jvm内存管理基础
Effective linux.2.(tools)
Network Simulator Generator TCL 2.1
Ad

Similar to Analysis of Adobe's RTMFP Protocol (20)

PDF
PHP 應用之一 socket funion : 偽 WEB Server
PPTX
Io t security-ameba-ppt
PPT
network2
PPT
智慧家庭 簡報
PPT
构建ActionScript游戏服务器,支持超过15000并发连接
PDF
Java线上应用问题排查方法和工具(空望)
PPT
第18讲 Hdlc和Ppp
DOC
Wbm9000动态库说明L
PPT
Syslog Ng
PPT
syslog&syslog-ng
PPT
intro syslog syslogng
PPT
高性能并发网络服务器设计与实现
PPTX
Track2 -刘继伟--openstack in gamewave
PDF
Showinnodbstatus公开
PDF
20201006 meta_coin 六角學院
PPT
第3讲 Tcpip协议栈
PPTX
Os讀書會20170415
PDF
CWMP TR-069 Training (Chinese)
PPT
CH1-5ed 概述.pptCH1-5ed 概述.pptCH1-5ed 概述.pptCH1-5ed 概述.pptCH1-5ed 概述.ppt
PPT
18 cpu02
PHP 應用之一 socket funion : 偽 WEB Server
Io t security-ameba-ppt
network2
智慧家庭 簡報
构建ActionScript游戏服务器,支持超过15000并发连接
Java线上应用问题排查方法和工具(空望)
第18讲 Hdlc和Ppp
Wbm9000动态库说明L
Syslog Ng
syslog&syslog-ng
intro syslog syslogng
高性能并发网络服务器设计与实现
Track2 -刘继伟--openstack in gamewave
Showinnodbstatus公开
20201006 meta_coin 六角學院
第3讲 Tcpip协议栈
Os讀書會20170415
CWMP TR-069 Training (Chinese)
CH1-5ed 概述.pptCH1-5ed 概述.pptCH1-5ed 概述.pptCH1-5ed 概述.pptCH1-5ed 概述.ppt
18 cpu02
Ad

Analysis of Adobe's RTMFP Protocol

  • 2. Brief • RTMFP - "Real-Time Media Flow Protocol” • 是Flash与Flash之间的基于UDP的点对点传输协 议 • Adobe的专有协议。 • 2008年在Flash 10.0中首次发布 • 现在在我们每个人的浏览器中。 • 2012年12月提交RFC • 发明人认为它是An replacement of TCP。 类似协议: webrtc、DCCP、DTLS、ICE(rfc5245).
  • 3. A brief view(1) Use it as rpc method: var nc:NetConnection; nc = new NetConnection() nc.connect("rtmfp://127.0.0.1:1935/HelloWorld/"); nc.call("serverFunc1", new Responder(onReply), ”hello”); function onReply(result:Object):void { dlog("onReply received value: " + result); }
  • 4. A brief view(2) Attach Streams to RTMFP Connection: var nc:NetConnection; nc = new NetConnection() nc.connect("rtmfp://127.0.0.1:1935/HelloWorld/"); sendStream = new NetStream(nc,NetStream.DIRECT_CONNECTIONS); sendStream.publish("media");
  • 5. 主要内容 • History and Why we need it? • How to analyze it? • Layers – UDP层的Multiplex与加密解密 – 会话建立、密钥协商、NAT穿透 – 类TCP的功能(flow、分片、ACK与重传、拥塞 控制)
  • 6. History • 2004年,Matthew Kaufman 和 Michael Thornburgh 在美国加州Santa Cruz成立了Amicima公司,他们 设计了MFP • 2005年8月1日,MFP开源 • 2006年,Amicima被Adobe收购,MFP变RTMFP • 2008年,RTMFP在Adobe 10.0中发布 • 2010年6月,Matthew Kaufman跳槽去了Skype • 2012年12月,Michael Thornburgh代表Adobe公司 向IETF提交了RTMFP协议草案。
  • 7. Why we need it? • “To securely deliver media flows over the Internet” • Peer to Peer video streaming • 移动互联网环境下,延迟高,连接易断,IP 易变 • 层次化的组合设计(如tcp+ssl+http)导致建立 连接所需的TTL太多。 —> 在UDP的基础上重新实现TCP+SSL,以及 NAT穿透。
  • 10. Man in the Middle • 密钥协商采用了Diffie–Hellman算法 • Diffie–Hellman 天生就有漏洞,容易受到中 间人攻击 • Cumulus 做了一个 https://github.com/OpenRTMFP/Cumulus 缺点:使用麻烦 并非处理了所有情况
  • 13. Address Space Load Randomization
  • 14. Address Space Load Randomization
  • 15. Address Space Load Randomization D:> dumpbin /headers flashplayer_11_sa_debug_32bit.exe 8140 DLL characteristics Dynamic base NX compatible Terminal Server Aware 如果它的值是8140,就说明打开了”Dynamic base”。用VC的 链接器禁用掉它即可。 D:> link /edit /dynamicbase:NO flashplayer_11_sa_debug_32bit.exe
  • 16. Tamarin • Adobe 主导的开源项目 • Flash Player的AVM的核心源码 • 包含GC、bytecode、AMF相关内容 D:flairpcf avmplus.lib avmplus.pat avmplus.lib: skipped 1731, total 14180 D:flairsigmake avmplus.pat avmplus.sig avmplus.sig: modules/leaves: 8012/4207, COLLISIONS: 407
  • 17. RTTI • 利用RTTI根据从object pointer获取class name • 可惜flash player在所有平台下都没有打开 RTTI • 但是Server有! • 不仅有RTTI信息,还有大量调试代码,用于 输出调试日志。
  • 18. Server的调试日志 • 2012-06-12 17:32:07 8328 (d)0000000 rtmfp send message, session: 08F2F008 flow: 08F22EA0 rel: (-2,-2) kMsgCmd idByte=20 streamId=0 time=0 trxId=1 kEncodingAMF0 _result cmdData=( kObjectType ( fmsVer= kStringType “FMS/4,5,0,297”, capabilities= kNumberType 255, mode= kNumberType 1 ) ) arg0=( kObjectType ( level= kStringType “status”, code= kStringType “NetConnection.Connect.Success”, description= kStringType “Connection succeeded.”, objectEncoding= kNumberType 3, data= kArrayType ( version= kStringType “4,5,0,297” ) ) ) - • 2012-06-12 17:32:07 8328 (i)2581173 rtmfp recv message, session: 08F2F008 flow: 05624900 kMsgCmdEx idByte=17 streamId=0 time=724 trxId=0 kEncodingAMF0 setPeerInfo cmdData=( kNullType ) arg0=( kStringType “192.168.15.1:53804” ) arg1=( kStringType “192.168.146.1:53804” ) arg2=( kStringType “10.4.8.84:53804” ) -
  • 19. Hook DLL • https://github.com/snnn/flash-rtmfp-hook • 找到感兴趣的函数 • 制作DLL • 注入它! • Detours 缺点:只能适用于特定平台特定版本的flash player
  • 23. 协议分层 • Packet:Session标识、UDP层的Multiplex、 加密解密。 • Chunks:18种底层消息,用于Session建立、 密钥生成与交换、Keep-alive、NAT穿透、IP 移动、拥塞控制等 • Flow:Framing、Fragmentation、ACK、重传、 拥塞控制、优先级。 • 应用层: 分布式对象与RPC、音频流、视频 流、音视频编解码、Qos。
  • 25. Session multiplexing • UDP Packet = scrambledSessionID + encPart 前4个字节是加扰后的session id 后面是AES加密后的数据 1. 加密是必须的而不是可选的 2. 用session id来关联一个Endpoint,而不是ip address and port
  • 26. 加密与HMAC 1. Enc(SSEQ+ body), 然后算HMAC 2. ENC(checksum + body) 代表了保障消息完整性的两种模式
  • 27. 承载Chunks timestamp: 2字节。它的值是从1970-01-01 00:00:00 +0000 (UTC)到现在的毫秒数除以4, 然后取最低2个字节。 timestamp-echo: 2字节。what the timestamp field of a packet received from the other end would be at the time this packet was transmitted Padding: 0xFF. Chunk id never be 0xFF.
  • 28. Chunks类型 session • initiator hello • responder hello • initiator Ikeying • responder Ikeying • Redirected IHello • Forwarded IHello • responder cookie change control • Ping • Ping Reply • Session Close Request • Session Close Ack Flow • User Data • Next User Data • Buffer Probe • ACK • Flow Exception report
  • 31. 会话建立涉及的Chunks • initiator hello • responder hello • initiator initial keying • responder initial keying • Redirected initiator Hello • Forwarded Initiator Hello • responder cookie change
  • 32. Endpoint Discriminator • 每个Endpoint有一个EPD • 每个EPD由1个或多个identity组成 • Identity分两种 – 0xf, peerid – 0x0a,server url • PeerID=SHA256(Certificate) • Certficate: Option List (含公钥等)
  • 34. 密钥协商 • DH • b = g^a (mod p) • d= g^c (mod p) • Shared = b^c = d^a = g^(a * c) • 易受中间人攻击。 • g 和p的选择参考IPSec(rfc2412)和rfc3526
  • 35. 密钥协商 • byte[] sec; byte[] HMAC256(byte[] key,byte[] data); • byte[] key1=HMAC256(sec,HMAC256(skrc,skic)); • byte[] key2=HMAC256(sec,HMAC256(skic,skrc)); session.encodekey = new SecretKeySpec(Arrays.copyOf(key1, 16), "AES"); //initiator的加密密钥 • session.decodekey = new SecretKeySpec(Arrays.copyOf(key2, 16), "AES"); //responder的加密密钥
  • 37. 发送时:3种NAT • Cone: 将src ip映射到一个固定的IP,并且将 src port映射到一个固定的Port,无论dst ip 和dst port是什么。 • Single IP address, symmetric:将src ip映射到 一个固定的IP,将src port映射到一个随机的 port,但是保证对于相同的(dst ip,dst port), src port始终相同。 • Multiple IP address, symmetric:与上面类似, 但是src ip可能会被映射到多个IP中的一个。
  • 38. 接受时:3种 • Full Cone: 不对收到的包的IP端口做任何限 制. 这种NAT通常被称为static NAT,在外面 看就像是一个透明代理一样。 • Restricted Cone: Restricted Cone会对收到的 包的IP做限制。 • Port Restricted Cone: 它就是在Restricted Cone的基础上对端口也做了限制。 • 连接性测试: http://cc.rtmfp.net/
  • 45. Control Chunks • Ping • Ping Reply • Session Close Request • Session Close Acknowledgement
  • 46. FLOW
  • 47. Flow简介 • Flow是单向的 • 每个Flow都有自己的名字 • 建立Flow不需要单独的Chunk。Flow的meta data随第一个数据包一起发送 • 保障顺序(或不) • 保障一定送达(或不) • 每个Flow有自己的窗口控制
  • 48. Chunks • User Data • Next User Data • Buffer Probe • ACK • Flow Exception report
  • 49. UserData • uint8_t flags; varint64 flowid; varint64 seq; varint64 fsnOffset; optional Options options; //当flags & 0x80 !=0 uint8_t data[]; • forwardSequenceNumber = seq- fsnOffset
  • 50. MessageTypes • kMsgUserCtrl • kMsgVirtualUserControl • kMsgAudio • kMsgVideo • kMsgDataEx • kMsgContainerEx • kMsgCmdEx • kMsgData • kMsgContainer • kMsgCmd • kMsgUDP • kMsgAggregate • kMsgPresent
  • 51. ACK • Data Acknowledgement Bitmap Chunk – flowID – bufAvail – cumAck – Bitmap (每一位对应一个seq number) • Data Acknowledgement Ranges Chunk 与上面类似,但是把bitmap换成了rangs
  • 52. 参考资料: • RFC草案: http://tools.ietf.org/html/draft- thornburgh-adobe-rtmfp • 2010年在IETF上的演讲: http://www.ietf.org/proceedings/10mar/slides/ts varea-1.pdf • 2013年对Michael Thornburgh的访谈: http://www.overdigital.com/2013/02/21/rtmfp- and-the-ietf-qa-with-co-creator-michael- thornburgh/ • http://www.sunchangming.com/docs/rtmfp.jsp