揭秘FaceTime背后的技术

视频与音频质量

视频与音频质量

每个视频FaceTime呼叫包含四个媒体流。上面说过,音频的编码为AAC-ELD,据观察,每个方向上的带宽为68kbps(双向共136kbps)。视频编码为H.264,视频质量取决于SIP上计算出的带宽,可能会有很大变化。我们知道SIP为H.264的总消耗带宽保留了余量,但FaceTime如何即时计算出能为消费者提供多少带宽,还尚不清楚。

在视频通话时,从wifi切换到手机流量就可以观察到这一行为,通常在切换的瞬间,视频压缩的效应会非常明显(但很有意思的是通话不会中断),得益于iOS内部的网络接口切换功能。但是音频通话就不会有这种行为,通话质量或是基本上能维持同等质量,或是完全中断,这证明了音频通话不是那么灵活(因为音频通话的带宽要求很低)。

如今的FaceTime还是如此吗?

我觉得应该还是如此,但我不太确定是否还有XMPP。但是在阅读了更多材料之后,我坚信它的工作原理依然如此,而且其中一大部分都是苹果iOS基础设施的工作原理。尽管关于FaceTime内部原理的文档并不多,但吸引我的注意的是这篇关于安全的文(https://support.apple.com/guide/security/facetime-security-seca331c55cd/1/web/1)。

FaceTime是苹果的视频和音频通话服务。就像iMessage一样,FaceTime通话使用了苹果的推送服务(APN),与用户的已注册设备建立初始连接。FaceTime的音频/视频内容由端到端加密保护,所以只有发送者和接收者能访问。苹果无法解密数据。

这很有意思,因为这表明许多苹果的底层技术都是XMPP,这非常令人惊讶,因为许多人都认为XMPP已经是一门过时的技术了。稍后我会讨论到,我不确定这是XMPP,还是恰好使用了同一个端口。那么,既然消息已经交换了,那么秘钥共享呢?这些通信都是加密的,但我并没有上传或共享我的公钥(也无法访问任何这类的秘钥)。

秘钥?我糊涂了,我们不是在讨论通话吗?

苹果的一大卖点就是安全性,而iMessage以其加密功能而著称。传统的短信访问是不加密的,大部分基于文本的通信(如电子邮件)也是不加密的。加密在计算上很昂贵,在苹果实现加密文本通信之前,一直都被认为没有必要。但为什么加密依然没有成为消费级计算机生态系统的主要组成部分?

简单来说,这是因为秘钥的管理很麻烦。如果我想发送加密信息给你,我必须先知道你的公钥。然后我才能加密信息,你才能解密信息。传统上这个过程需要大量手工操作,因此非常麻烦。

所以苹果一定有某种途径可以生成秘钥(很可能是在设备上进行)然后共享公钥。实际上他们确实这样做了,通过一个名为IDS(苹果身份服务)的范围。这个服务将你的电话号码或邮件地址与你的设备的公钥联系起来。

如下图所示:

据我看来,整个过程与FaceTime通话是一样的,只不过是用于iMessage,但依然带有一些音频/视频通道的气氛。这里的证书用来建立共享的秘密,实际的媒体通过SRTP传输。

苹果可能参考了SSL协议

SIP本身就有用于处理加密的机制,但FaceTime和iMessage从iPhone 4时代就可以使用了。所以虽然原理是正确的,但我完全不明白为什么安卓上没有iMessage的替代品。如果世界上有数十亿台苹果设备,绝大多数都依赖于客户端交涉,那么复制一个产品应该很容易吧?

这里就有些奇怪了。RFC5246描述了一种发送客户端证书的方法。似乎苹果以前使用了这种方法,但是他们改变了过程。现在是由应用程序负责发送,同时还会发送公有令牌、一个一次性随机数和一个签名。我们先来看看令牌和证书部分。

令牌

256位二进制字符串

服务器端生成

在设备APN激活过程中生成

证书请求发送到albert.apple.com

使用两个TLS扩展,APLN和Server名

为什么安卓应用没有采用这种方式?

据我所知,主要的问题有两个。首先,建立连接的协议是非标准的。苹果使用APLN来处理交涉,客户端使用apns-pack-v1协议来处理。所以,如果你想自己写一个应用程序来访问苹果服务器,首先需要获取x509证书(似乎是在激活时生成的)。然后需要使用APLN与服务器建立连接,传递服务器名称,我不知道安卓是否能支持该操作。而且,你也不能事先一次性生成,因为苹果只允许一台设备一个连接。所以,如果你想使用来自另一台真正的Mac或iOS设备的证书,就会导致真正的苹果设备掉线。如果Mac开始连接,你的假设备就会掉线。

那黑苹果是怎么做到的?黑苹果只不过是在x86机器上运行的MacOS。它们很可能拥有建立连接所要求的扩展,也可以生成必须的证书。这里就有一点奇怪了。似乎Mac的序列号在整个过程中非常重要,似乎需要在苹果一侧进行判断“这台设备是否允许连接”。

解决方案就是生成一个假的Mac序列号。整个过程看起来挺麻烦,它依赖于好几个因素。首先,Apple ID必须通过另一台设备激活过,而且ID的年龄很重要。似乎这涉及到某种权重系统,以避免系统被大量的假请求淹没。但是,似乎在苹果完成注册过程之前,它会查看设备的plist,然后试图决定“这是否真的是一台苹果设备”。

苹果设备的序列号并不是随机值,而是一段特殊的数据格式,包含了许多信息。很可能这是为了方便维修,这样AppleCare网站和苹果商店就可以迅速地确定设备型号和年限,而不需要检查某个“主序列号服务器”。旧的苹果序列号格式可以看这里:https://github.com/acidanthera/OpenCorePkg/blob/master/Utilities/macserial/FORMAT.md

我怀疑,序列号能被暴力破解,就是苹果决定改变序列号格式的原因之一。序列号从一个有意义的值变成了值和长度都完全随机的序列,苹果就能通过查询内部数据库,从而更加确信地判断“这是一台MacBook Pro,序列号是xxx”。这样,制造假序列号就基本上不可能了,因为同时猜中型号、MAC地址、主板ID和序列号极其困难。

有多安全?

不知是好是坏,这个序列号与苹果一样安全。苹果对设备的加入、令牌生成、证书验证以及TLS握手过程中的证书交换拥有完整的控制权。用户不可能提供自己的证书用于加密,但我惊讶的是,连显示用户秘钥的功能都没有。也许这是防范中间人攻击的一环。

所以,苹果完全有可能加入另一个邮件地址,并将其与某个Aple ID联系起来,并允许它接收FaceTime的APN通知或接受通话。我并不是说他们可能会这样做,只是说这在技术上是可行的(因为我们都知道,多台设备可以同时接受同一个FaceTime呼叫,而加入一个新的通知目标,仅依赖于Apple ID中的某个URI,不管是电话号码还是邮件地址)。

这究竟是不是XMPP?

在我看来,它的行为跟我预期的差不多,拥有一个大型的分布式消息队列。首先你需要连接到某个随机的APN服务器,rand(0,255)-courier.push.apple.com,开始TLS握手,然后消息就会推送到你的设备上。很可能在苹果的规模上,同时会有数十亿条消息,后台的处理会更复杂,但我认为许多概念都很简单。

总结

FaceTime是一个伟大的服务,它依靠的是苹果生态系统中的推送通知服务和Apple ID注册服务,这两部分都经过了实战的考验。推送通知(许多非苹果的应用程序也使用该服务来接收通知)可以让每台设备迅速地交涉客户端证书,开始一个安全的连接,并使用通常的网络协议,在苹果的帮助下绕过NAT,然后使用标准的SIP协议在设备之间建立连接。通话质量则是苹果自研的编码器的成果,设备能完全发挥该编码器的能力。

FaceTime与iMessage,加上Apple ID服务的其他部分,可以让用户将电话号码或邮件地址注册变成一个唯一的地址。

本文的很多内容可能并不太准确,也有可能已过时。获取有关信息很困难。欢迎大家批评指正,或提供相关的参考文档或资料。

参考链接:

https://matduggan.com/how-does-facetime-work/

CSDN疯狂盲盒来啦 !!!iPhone 12、机械键盘、Switch等你来拿!好运锦鲤将会花落谁家?

☞ 对话图灵奖得主、CNN之父Yann LeCun:我在中国看到了AI研究热潮

☞苹果藏在 iOS 14.3 中的新算法被发现,CSAM 检测技术再遭抗议!

☞ 苹果承认从2019年开始扫描用户邮件寻找虐童资料;新浪回应“花钱买热搜”传闻;李沐斯坦福《机器学习》课程上线|极客头条返回搜狐,查看更多

随便看看