本文在于阐述我对WiFi网络中各站点之间加密方式的理解
提问
此前, 我有过这样一个疑惑:
wifi的数据传输形式为广播, 那么考虑一下, 当A站发送数据给B站时
- 如果A站和B站之间信号不直接可达, 那么数据将会先由A站流往AP(接入点/基站/路由器), 再由AP流往B站, 即靠AP做转发
- 如果A站和B站之间信号直接可达, 数据广播出去后, AP和B站都会收到这个数据, 那么B站是直接接受还是抛弃?又由于AP并不知道B站是否已经接收, 所以会坚持转发一次, 如果B站直接接受了, 岂不是会导致数据无条件重发?
在理解了wifi的数据加密形式后, 疑惑也被顺便解开了
PS: 说wifi其实不严谨, 802.11会更规范一点, 不过为了方便理解, 直接说wifi也无妨, 毕竟有挺多人尚不了解802.11和wifi的关系
共识
行文开始前先做一些概念约束以及一些我的个人观点
模式限定
探讨范围限定在AP模式, 也就是最流行的wifi接入模式, 不涉及Ad-hoc模式, 简要的描述就是:
- 有一个无线设备工作在AP模式, 承担基站的角色(路由器)
- 其他所有的设备全部和基站建立无线链路(手机,平板,笔记本…接入wifi)
- 所有站点之间的数据通信均通过基站进行转发, 类似于C/S模式
- 只要基站挂掉, 所有站点之间将无法互相通信
通信数据安全
一般而言, 通信数据的加密手段不同于数据存储, 对于数据存储, 通常采用对称加密, 且只用一把密钥, 而通信数据的做法大致是这样的:
- 通信双方共享一把高强度的初始密钥K
- 通信双方在(高强度算法+密钥K)创建的安全链路中协商出一把较低强度的密钥k
- 接下来的通信均使用较低强度的算法和密钥k加密(减轻计算负载)
- 每隔一定时间, 通信双方在(高强度算法+密钥K)创建的安全链路中重新协商出一把较低强度的新密钥k2, 替代上一次的密钥k, 进行接下来的通信
- 一直使用同一把密钥是很不安全的做法, 因为采集越多的密文样本, 对于破译密钥来说越是有利的, 所以通信数据加密通常都会采取定期更换密钥的做法来提高数据安全
广播报文与广播链路
在广播式链路上发送广播报文具有得天独厚的优势
- 古老的集线器也是广播式链路, 某站点要发送一个广播报文, 集线器不需要任何处理, 只需要把广播报文当成普通报文广播即可
- 交换机将集线器的广播式链路改成了点对点链路, 某站点要发送一个广播报文, 交换机只能将该报文从每一个端口发送一次
- wifi使用无线电通讯, 自然也是广播链路, 因此, 某站点要发送一个广播报文, AP只需要发送一次数据即可, 无需将广播报文挨个站点发送一次
流程
大致流程如下(忽略广播)
- AP和站点之间共享相同的初始密钥PMK(Pairwise Master Key), 关于PMK的来源后文会给出
- 每当有站点请求接入AP, AP和站点之间就会通过PMK生成出一把正式传输数据用到的密钥PTK(Pairwise Transient Key)
- AP和站点之间的通讯全部使用PTK加密
如果稍加留意, 你会发现, 每个站点和AP之间都维护着一个PTK, 但是站点和站点之间是不共享PTK的, 站点A和AP之间的通讯使用PTKa, 站点B和AP之间的通讯使用PTKb
因此, 站点A是没有能力和站点B直接通讯的, 必须经由AP做数据转发, 也就是说, 即使站点B接收到了站点A发出的帧中白纸黑字写着”接收方为站点B”, 站点B也不得不抛弃, 因为帧中的载荷数据是使用PTKa加密的, 而站点B并不知道PTKa, 只能等待AP解析此帧, 并换用PTKb加密后重新发送一个新帧, 站点B才可以看见来自站点A的数据
换言之, PTK的方式保证了站点和站点之间在链路上是”隔离”的, 任何站点都无法嗅探到不是发送给他的数据
接下来谈谈数据的广播, 如果站点A需要发送IP广播, 单借助PTK, 也是可以做到的: 站点A将广播包发送给AP, AP再将广播包重新编码逐个发给所有接入的站点, 但这种做法太愚蠢, 现实的流程如下
- AP启动后生成一个随机初始密钥, GMK(Group Master Key)
- AP使用GMK通过某种算法, 衍生出一个用于加密广播/组播数据的密钥GTK
- 每个接入AP的站点在得到了PTK后, AP将GTK使用PTK加密后发送给站点
换言之, 所有站点都持有相同的GTK, 那么站点发送IP广播的流程究竟是怎么样的呢?最容易想到的有两种
第一种, 站点直接通过GTK进行广播
- 站点A使用GTK加密广播包并发送
- 站点B接收到从站点A发出的广播包
- 站点C离A较远, 没能收到从站点A发出的广播包
- AP收到了从站点A发出的广播包, 然后做一次接力转发
- 所有站点接收到从AP转发的广播包
第二种, 由AP通过GTK进行广播
- 站点A使用PTKa加密广播包并发送
- AP接收到从站点A发出的广播包
- AP解码接收到的广播包, 并使用GTK加密该广播包, 再接力转发出去
- 所有站点接收到该AP转发的广播包
不难看出, 第二种方式是最优的, 因为模式简单且和单播方式统一, 而且第一种方式会造成站点重复接收广播包
事实上也的确采用的第二种方式. 所以, GTK对于站点来说, 只用于解密, 对于AP来说, 只用于加密
总结: wifi网络内的所有站点间的所有通信都必须交给AP转发, 站点和站点之间不存在任何直接通信行为
关于PMK
PMK是怎么来的呢?
简单的说, 接入wifi时需要你填的那个密码被称之为PSK(Pre-Shared Key), 将PSK使用一套算法进行一次转换, 就是所谓的PMK了
当然, PMK不仅仅可以通过PSK得到, 如果wifi使用802.11x的企业级证书认证方式(民用wifi很少支持这种认证方式), 那么, PMK就是标准的非对称密钥生成的对称密钥
关于GMK
此前我认为: GMK可能只是为了和PMK概念对称, 实际使用中, 感觉完全没有存在的必要, AP每次都生成一个随机串作为GTK就可以了
如今我认为: GMK的存在是有必要的, 在多AP协同工作时需要维持相同的GMK, 譬如无缝漫游功能