文章参考的是Android 7.1的源码
本文主要研究EAP类型网络的身份验证过程,从而简化Android平台EAP类型网络的身份验证过程。
1. 什么是EAP
Extensible Authentication Protocol
,简称EAP,是一种支持多种验证方式的协议框架,EAP通常运行在链路层例如PPP和IEEE 802。EAP协议是IEEE 802.1x认证机制的核心,它将实现细节交由附属的EAP Method协议完成,如何选取EAP method由认证系统特征决定,这样实现了EAP的扩展性及灵活性(摘自”百度百科”)。这篇文章主要描述的场景是基于Radius服务器的EAP身份认证方式。
了解本文前,如果您的身边没有EAP网络环境,可以通过路由器和Radius进行搭建。
2. IOS和Android对EAP支持的区别
下图分别是IOS(左图)和Android(右图)连接EAP-TTLS加密方式网络的设置界面:
从上图看,IOS系统中,只需要用户输入用户名和密码,但是在Android系统上,则需要用户指定具体的EAP方法(默认使用PEAP),如果选择的EAP方法与AP认证服务器指定的不对应,则无论用户名和密码正确与否都会验证失败。
我们知道,在未开始连接前,设备是只知道这个AP是EAP加密方式,但不知道具体的EAP方法。那为什么IOS都没有选择具体EAP方法就可以连上这个TTLS加密方式的网络呢?而且,将AP的EAP方法改为PEAP,IOS同样可以连上,这点很奇怪!需要刨根问题追究缘由,则需要抓出认证过程中,IOS与认证服务器的交互包。
3. IOS EAP认证过程探究
设定Radius EAP方法为TTLS,开启Radius服务:
xyzc@xyzc-ul:~$ sudo radiusd -X
FreeRADIUS Version 3.0.16
Copyright (C) 1999-2017 The FreeRADIUS server project and contributors
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
...
Listening on auth address * port 1812 bound to server default
Listening on acct address * port 1813 bound to server default
Listening on auth address :: port 1812 bound to server default
Listening on acct address :: port 1813 bound to server default
Listening on auth address 127.0.0.1 port 18120 bound to server inner-tunnel
Listening on proxy address * port 43060
Listening on proxy address :: port 48623
Ready to process requests
在搭建了Radius服务的主机上开始抓取tcpdump
,并使用IPhone开始连接
xyzc@xyzc-ul:~/ulangch/eap$ sudo tcpdump -i any -w tcpdump-ios.pcap
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
实验完成后使用wireshark
分析IPhone连接过程中抓取Radius服务所在主机的tcpdump。
如下为tcpdump抓取的Radius协议数据包,这部分即代表了认证过程,192.168.1.1
和 192.168.1.100
分别代表了路由器网关IP和Radius服务主机IP。
179 2018-05-14 15:43:19.055587 192.168.1.1 192.168.1.100 RADIUS 201 Access-Request(1) (id=0, l=157)
180 2018-05-14 15:43:19.056882 192.168.1.100 192.168.1.1 RADIUS 124 Access-Challenge(11) (id=0, l=80)
192 2018-05-14 15:43:19.155723 192.168.1.1 192.168.1.100 RADIUS 215 Access-Request(1) (id=1, l=171)
193 2018-05-14 15:43:19.157221 192.168.1.100 192.168.1.1 RADIUS 108 Access-Challenge(11) (id=1, l=64)
195 2018-05-14 15:43:19.189098 192.168.1.1 192.168.1.100 RADIUS 368 Access-Request(1) (id=2, l=324)
196 2018-05-14 15:43:19.193632 192.168.1.100 192.168.1.1 RADIUS 1124 Access-Challenge(11) (id=2, l=1080)
197 2018-05-14 15:43:19.272446 192.168.1.1 192.168.1.100 RADIUS 213 Access-Request(1) (id=3, l=169)
198 2018-05-14 15:43:19.273774 192.168.1.100 192.168.1.1 RADIUS 1124 Access-Challenge(11) (id=3, l=1080)
199 2018-05-14 15:43:19.305511 192.168.1.1 192.168.1.100 RADIUS 213 Access-Request(1) (id=4, l=169)
200 2018-05-14 15:43:19.306681 192.168.1.100 192.168.1.1 RADIUS 781 Access-Challenge(11) (id=4, l=737)
203 2018-05-14 15:43:20.855671 192.168.1.1 192.168.1.100 RADIUS 343 Access-Request(1) (id=5, l=299)
204 2018-05-14 15:43:20.857646 192.168.1.100 192.168.1.1 RADIUS 163 Access-Challenge(11) (id=5, l=119)
205 2018-05-14 15:43:20.922293 192.168.1.1 192.168.1.100 RADIUS 266 Access-Request(1) (id=6, l=222)
206 2018-05-14 15:43:20.924311 192.168.1.100 192.168.1.1 RADIUS 173 Access-Challenge(11) (id=6, l=129)
207 2018-05-14 15:43:20.955585 192.168.1.1 192.168.1.100 RADIUS 286 Access-Request(1) (id=7, l=242)
208 2018-05-14 15:43:20.958304 192.168.1.100 192.168.1.1 RADIUS 213 Access-Accept(2) (id=7, l=169)
直接从192帧开始分析:
192 2018-05-14 15:43:19.155723 192.168.1.1 192.168.1.100 RADIUS 215 Access-Request(1) (id=1, l=171)
RADIUS Protocol
Code: Access-Request (1)
...
Attribute Value Pairs
AVP: l=9 t=User-Name(1): ulangch /** ulangch是我们输入的用户名*/
...
AVP: l=31 t=Called-Station-Id(30): 80-89-17-3D-E0-10:TPLINK-TTLS /** TPLINK-TTLS 是路由器名称*/
...
AVP: l=10 t=EAP-Message(79) Last Segment[1]
...
Extensible Authentication Protocol /** EAP协议定义的数据*/
Code: Response (2)
Id: 1
Length: 8 /** 注意这里的长度是8*/
Type: Legacy Nak (Response Only) (3)
Desired Auth Type: Protected EAP (EAP-PEAP) (25) /** 这里指定了期望认证类型为EAP-PEAP*/
...
第192帧是STA通过AP包装和转发给Radius服务器的一帧数据,Desired Auth Type: Protected EAP (EAP-PEAP) (25)
表明希望的加密方式,这与我们上面设定的EAP-TTLS不符合,那是否就会被Reject呢?下面继续看Radius的回应(第193帧):
193 2018-05-14 15:43:19.157221 192.168.1.100 192.168.1.1 RADIUS 108 Access-Challenge(11) (id=1, l=64)
RADIUS Protocol
Code: Access-Challenge (11)
...
Attribute Value Pairs
AVP: l=8 t=EAP-Message(79) Last Segment[1]
AVP Type: 79
AVP Length: 8
EAP fragment: 010200061520
Extensible Authentication Protocol /** EAP协议定义的数据*/
Code: Request (1)
Id: 2
Length: 6
Type: Tunneled TLS EAP (EAP-TTLS) (21) /** 表明支持的认证方式是TTLS*/
EAP-TLS Flags: 0x20
...
第193帧表明,在STA表明自己期望的EAP方法后,Radius发出方法是TTLS的认证挑战帧,Type: Tunneled TLS EAP (EAP-TTLS) (21)
表明认证服务器会采用TTLS进行接下来的认证。这样的响应是不容质疑的,毕竟Radius目前被设定为只支持该类型,继续看下一帧IPhone的响应(第195帧):
195 2018-05-14 15:43:19.189098 192.168.1.1 192.168.1.100 RADIUS 368 Access-Request(1) (id=2, l=324)
RADIUS Protocol
Code: Access-Request (1)
...
Attribute Value Pairs
AVP: l=9 t=User-Name(1): ulangch
...
AVP: l=163 t=EAP-Message(79) Last Segment[1]
AVP Type: 79
AVP Length: 163
EAP fragment: 020200a115800000009716030100920100008e03035af93e...
Extensible Authentication Protocol /** EAP协议定义的数据*/
Code: Response (2)
Id: 2
Length: 161
Type: Tunneled TLS EAP (EAP-TTLS) (21) /** 使用TTLS进行认证*/
EAP-TLS Flags: 0x80
EAP-TLS Length: 151
Secure Sockets Layer
TLSv1.2 Record Layer: Handshake Protocol: Client Hello /** Client Hello,申请进行握手,建立连接以便于接下来的数据传输*/
Content Type: Handshake (22)
Version: TLS 1.0 (0x0301)
Length: 146
Handshake Protocol: Client Hello
...
接下来就是握手交换秘钥的过程以及最终的身份和密码认证,直到第208帧,Radius服务认证通过:
208 2018-05-14 15:43:20.958304 192.168.1.100 192.168.1.1 RADIUS 213 Access-Accept(2) (id=7, l=169)
RADIUS Protocol
Code: Access-Accept (2)
Packet identifier: 0x7 (7)
Length: 169
Authenticator: ed1a896e29b2222b21cffcc5ad0c6b70
Attribute Value Pairs
AVP: l=58 t=Vendor-Specific(26) v=Microsoft(311)
AVP: l=58 t=Vendor-Specific(26) v=Microsoft(311)
AVP: l=6 t=EAP-Message(79) Last Segment[1]
AVP Type: 79
AVP Length: 6
EAP fragment: 03070004
Extensible Authentication Protocol /** EAP协议定义的数据*/
Code: Success (3) /** 认证通过*/
Id: 7
Length: 4
AVP: l=18 t=Message-Authenticator(80): de70821ccbfa78162d71f9e7e30c1cdf
AVP: l=9 t=User-Name(1): ulangch
从上面可以看出,IPhone和认证服务器通过AP包装和转发身份信息,EAP方法,Hash后的密码,最终成功完成认证,那么Android系统在连接这个AP时会出现什么情况呢,请看下节。
4. Android EAP认证过程探究
与上面测试IOS连接TPLINK-TTLS的过程相似,Android设备选择PEAP
的认证方式,身份和密码均与上面IOS的测试相同,主要分析Android设备连接EAP类型AP的认证过程。下面是Radius服务主机抓取的tcpdump:
38 2018-05-14 17:28:56.177797 192.168.1.1 192.168.1.100 RADIUS 201 Access-Request(1) (id=46, l=157)
39 2018-05-14 17:28:56.179016 192.168.1.100 192.168.1.1 RADIUS 124 Access-Challenge(11) (id=46, l=80)
40 2018-05-14 17:28:56.210892 192.168.1.1 192.168.1.100 RADIUS 213 Access-Request(1) (id=47, l=169)
43 2018-05-14 17:28:57.213237 192.168.1.100 192.168.1.1 RADIUS 88 Access-Reject(3) (id=47, l=44)
从上面第43帧就可以看出认证失败了,依葫芦画瓢,开始逐帧分析(跳过前两帧,从第40帧开始):
40 2018-05-14 17:28:56.210892 192.168.1.1 192.168.1.100 RADIUS 213 Access-Request(1) (id=47, l=169)
RADIUS Protocol
Code: Access-Request (1)
...
Attribute Value Pairs
AVP: l=9 t=User-Name(1): ulangch
...
AVP: l=8 t=EAP-Message(79) Last Segment[1]
AVP Type: 79
AVP Length: 8
EAP fragment: 020100060319
Extensible Authentication Protocol
Code: Response (2)
Id: 1
Length: 6 /** 注意这里的长度是6*/
Type: Legacy Nak (Response Only) (3)
Desired Auth Type: Protected EAP (EAP-PEAP) (25) /** 期望的加密类型是PEAP*/
AVP: l=18 t=State(24): 2cd24e092cd34a78fd556806a4506d3c
AVP: l=18 t=Message-Authenticator(80): 0476c2371dbd53be8bd91bc8d350af8f
第40帧看起来和上面测试IOS时的192帧好像没什么区别,但是为什么迎来的不是Access Challenge而是Access Reject呢(第43帧):
43 2018-05-14 17:28:57.213237 192.168.1.100 192.168.1.1 RADIUS 88 Access-Reject(3) (id=47, l=44)
RADIUS Protocol
Code: Access-Reject (3)
...
Attribute Value Pairs
AVP: l=6 t=EAP-Message(79) Last Segment[1]
AVP Type: 79
AVP Length: 6
EAP fragment: 04010004
Extensible Authentication Protocol
Code: Failure (4)
Id: 1
Length: 4
AVP: l=18 t=Message-Authenticator(80): ffc562cb3a29579e8b464e5767bdfad8
这样看起来就非常奇怪了,IOS和Android发给Radius服务表明自己的Desired Auth Type
都是PEAP,为什么得到的却是不一样的回应呢???
5. 揭晓神秘面纱
注意我上面的注释,在IOS的第192帧和Android的第40帧中,有一个微小的区别:
/** IOS*/
Extensible Authentication Protocol /** EAP协议定义的数据*/
Code: Response (2)
Id: 1
Length: 8 /** 注意这里的长度是8*/
Type: Legacy Nak (Response Only) (3)
Desired Auth Type: Protected EAP (EAP-PEAP) (25) /** 期望认证类型为是PEAP*/
/** Android*/
Extensible Authentication Protocol
Code: Response (2)
Id: 1
Length: 6 /** 注意这里的长度是6*/
Type: Legacy Nak (Response Only) (3)
Desired Auth Type: Protected EAP (EAP-PEAP) (25) /** 期望的加密类型是PEAP*/
看起来都相同,为什么长度还不一样呢,这里面是否有什么蹊跷?还是需要看下这两帧的字节流:
/** IOS*/
02 01 00 08 03 19 15 2b
/** Android*/
02 01 00 06 03 19
看到区别没有?IOS这一帧的EAP协议数据里多了两个字节!!!下面逐个字节分析一下:
02: 对应类型,Request 还是 Response
01: 对应Id
00 08: 两个字节对应EAP协议头长度
03: 对应Type
19 15 2b: 十进制分别是25 21 27,代表了3种EAP方法!
所以不难想象了,IOS中指定了3种EAP方法,分别是十进制的25
,21
,27
,筛了一下freeradius的代码,发现这三个数字分别代表了PEAP
,TTLS
,MAKE
。所以造成差异的原因就是IOS请求方发送了3种EAP方法供给认证服务进行选择并且其中包含了TTLS,而Android则只指定了一种,且不是TTLS,所以才会被Reject!造成困惑的罪魁祸首就是wireshark只识别出了PEAP!
下面可以总结一下EAP认证流程了(部分流程没有在上述tcpdump中体现,可以查看802.11协议或者抓取sniffer
来更详细了解EAP认证过程):
EAPoL-Start
帧来初始化EAP认证过程EAP-Request
来请求请求方的的身份EAP-Response
,其AVP中携带User-Name
和支持的Auth Type
EAP-Response
帧封装在RADIUS数据包中转发给认证服务器Auth Type
并将Access Challenge
帧封装在RADIUS数据包中802.11 EAP帧
形式转发Access Challenge
给STA802.11 EAP
帧形式发送给AP802.11 EAP
帧形式发送给STA,并完成认证过程IOS和Android在EAP网络认证过程上最重要的区别就是IOS的Auth Type
中包含了3中EAP方法,而Android只包含了一种,且Radius服务器不支持该EAP方法。