烦恼一般都是想太多了。

0%

关于Radius协议-RFC2865

Radius 是广为使用的一种远程认证授权协议,在 AAA 系统中广为使用。各大 ISP 一般都用的这,在 TCP/IP 协议详解中其实也看到过类似的介绍。但是,久不接触,都已经忘记得差不多了。

简介

rfc2865 有详细的介绍,这里只记录一些我关心的东西。不过,rfc 其实已经被后面的文档进行更新了很多内容了,相关 rfc 有:

  • rfc2865-Remote Authentication Dial In User Service (RADIUS).pdf
  • rfc2868-RADIUS Attributes for Tunnel Protocol Support.pdf
  • rfc3162- RADIUS and IPv6.pdf
  • rfc3575-IANA Considerations for RADIUS.pdf
  • rfc5080-Common Remote Authentication Dial In User Service (RADIUS) Implementation Issues and Suggested Fixes.pdf
  • rfc6929-Remote Authentication Dial-In User Service (RADIUS) Protocol Extensions.pdf
  • rfc8044-Data Types in RADIUS.pdf

一句话描述:rfc2865 描述了一个用来在期待对链路进行认证的网络访问服务器(NAS)与一个共享的认证服务器间携带认证、授权、配置信息协议

早期协议的使用 udp 1645 端口,不过这个与另外一个服务相冲突,所以就换成了 1812 端口。

前言

管理分散的串行线路和调制解调器池以处理大量 用户可能需要大量的管理支持。由于调制解调器池在定义上是到外界的链接,他们需要被很仔细小心的注意安全性,授权及计费。这可以通过维护一个用户数据库,允许用户进行认证(通过用户名和密码)及一些详细的配置信息,服务信息(PPP,SLIP等)。

RADIUS 的主要特点是:

C/S模式:

NAS 作为 RADIUS 客户端,就用户信息传输到 RADIUS 服务器,然后根据 RADIUS 服务器的响应来决定要进行的操作。

RADIUS 服务器的任务是接受用户的连接请求,进行用户的认证授权,然后将所有必要的配置信息传输给 NAS 客户端以使其为用户提供服务。

当然,RADIUS 服务器也可以充当成代理客户端。

网络安全性

在 NAS 和 RADIUS 间的通信通过一个预共享的密钥来进行授权,这个密钥永远不会在网络上传输。同时,所有的用户密码信息都会被加密后在 NAS 和 RADIUS 间进行传输。

灵活的认证机制

RADIUS 支持很多种机制来认证授权一个用户。他提供给 RADIUS 用户名和原始的密码时,其能支持 PPP, PAP,CHAP,UNIX login等认证授权机制。

可扩展的协议

所有的事务都由变长的 Attribute-Length-Value 三元组组成。添加新的属性不会打乱已经实现的协议。

术语

文档中经常提到三个概念:

  • service 服务:NAS 为拨号用户提供的一个服务,比如 PPP
  • session 会话:NAS 为每个用户提供的服务都有一个 session,session 的开始,定义为服务的首次提供,会话的结束标志着服务的结束。一个用户可能会有多个 session,(并行或者串行),只要 NAS 支持。
  • silently discard 静默丢弃:丢弃报文,不做任何处理。

操作

当有个客户端(NAS)被配置为使用 RADIUS 时,所有此客户端的用户都需要向客户端提供身份信息。这可能会包含一个自定义的登录提示让用户输入其用户名和密码。还有一种操作方式是,用户会使用一个 链路层协议(如PPP)来将这些身份信息放在认证报文内。

一旦客户端获取到信息,其可能会选择通过 RADIUS 进行认证。如果进行 RADIUS 认证,那么客户端就会创建一个 Access-Request ,其中大体会包含 用户名,密码,客户端的ID,用户访问的 Port ID 等信息 的报文。当包含密码的时候,会通过一个 RSA MD5 算法进行隐藏。

Access-Request 会被提交到 RADIUS。如果超过一定的时间没有响应,这个请求会被重传一定的次数。或者,客户端会选择将报文转发到另外一各 RADIUS,或者通过一定的调度算法选择 RADIUS 服务器。

RADIUS 收到请求后,会验证客户端。一个没有包含预共享的密钥的客户端报文应该被 静默丢弃。如果客户端的认证通过,那么 RADIUS 就会查询用户数据库来找到该用户名的用户信息。在用户数据库中的记录会对此用户进行一系列的限制,必须满足此类限制才能让此用户进行访问。通常会包含密码的验证,但也可以只认证客户端或者 端口,这样的用户就可以直通了。

RADIUS 也可以发送请求到其他服务器来做一些其他的事情。

如果在 Access-Request 包含任何 Proxy-State 相关的属性,这些属性必须无修改的,有序的复制到响应报文内。其他属性倒是没有这个要求,放在什么位置都行。

如果有些条件无法满足,RADIUS 就会发送一个 Access-Reject 响应来表示这个用户请求无效。RADIUS 可以包含一个文字信息在 Access-Reject 报文中来让客户端返回给用户。在 Access-Reject 报文中,除了 Proxy-State 属性,不允许其他任何属性存在。

如果所有的条件都已满足, RADIUS 希望发起一个用户必须响应的挑战话,RADIUS 发送一个 Access-Challenge 响应。其可能包含一个文字消息来让客户端返回给用户,提示用户对此挑战进行响应,也可能包含一个 State 属性。

当客户端收到一个 Access-Challenge 报文且其支持 挑战/请求的话,那么其应该显示此文字信息给用户,并提示用户进行响应。然后客户端会会重传其 Access-Request ,不过会使用一个新的 请求ID,同时 User-Password 属性会被响应所替换(加密的),也要包含在 Access-Challenge 中返回的 State 属性(在一个请求中,只有0 或 1 个此属性的实例存在)。Radius 可对此新的 Access-Request 报文进行响应:Access-Accept, Access-Reject, Access-Challenge等。

如果如果的条件都达成,为此用户的所有配置信息列表会放到一个 Access-Accept 响应中。这只怕配置包含了 服务的类型(SLIP, PPP, Login User)和所有期望的服务必要的信息。对于 SLIP 和 PPP,这可能会包含 IP 地址,子网掩码,MTU,期望的压缩方式,期望的包过滤标识等。对于角色模式的用户,这可能会包含期望的协议和域名。

挑战/响应

挑战/响应 认证中,用户会收到一个不可预测的数字,请求用户进行加密后返回结果。已授权的用户会有一些特殊的设备进行此项工作(如智能卡,或软件),能计算出正确的响应。未授权的用户,则会很困难。

Access-Challenge 包典型的会包含一个 Reply-Message 信息,其中是会显示给用户的内容。

用户的响应最终由客户端传以第二个 Access-Request 传输给RADIUS。如果通过,那么就会返回 Access-Accept

例如:

NAS 发送一个 Access-Request 包给 RADIUS 服务器,其内包含 NAS-Identifier, NAS-Port, User-Name, User-password(有可能只是固定的字符串或没有)。RADIUS 返回一个 Access-Challenge ,其内包含 State 与 Reply-Message(Challenge 12345679)。 NAS 提醒用户进行响应,然后发送一个 新的 Access-Request 到服务器(有一个新的 ID,NAS-Identifier, NAS-Port, User-Name, User-Password(用户输入的响应,加密)),以及一些 State 属性(由 Access-Challenge返回)。然后 RADIUS 进行认证后就会有结果了。

PAP 与 CHAP

对于 PAP,客户端会将 PAP ID 与密码包含在 Access-Requect 包中作为User-Name 和 User-Password 属性。NAS 可能会包含 Service-Type =Framed-User 和 Framed-Protocol = PPP 属性来提示 RADIUS 其期望的是 PPP 服务。

对于 CHAP,NAS 会产生一个随机的挑战(最好是16字节)然后发送给用户,用户会返回一个 CHAP 响应其中包含 CHAP ID 和 CHAP username。NAS 会将 CHAP username 作为 User-Name 属性,将 CHAP ID 和 CHAP 响应作为 CHAP-Password 属性放在 Access-Request 报文内传输给 RADIUS。这个随机挑战可以包含在 CHAP-Challenge 属性(当其是16 字节长时),也可以被放在 Request Authenticator 字段内。NAS 可能会包含 Service-Type =Framed-User 和 Framed-Protocol = PPP 属性来提示 RADIUS 其期望的是 PPP 服务。

RADIUS 基于 User-Name 来查找密码,然后将 User-Name,找到的密码,CHAP Challenge 用 CHAP ID以 MD5 进行加密,最后后 CHAP-Password 进行比较,看是否匹配。

为什么使用 UDP

RADIUS 有几个特点:

  1. 如果到主 RADIUS 的请求失败了,那么就必须查询第二个 RADIUS。为了达到这个要求,那么请求的副本必须在传输层进行保持以进行可能的重传。这就意味着,重传计时其是必须的。
  2. 这个协议的时间要求和TCP非常的不同。一个极端情况,RADIUS 不需要一个灵敏的对丢失数据的检测机制。用户愿意为认证的完成等待几秒。而 TCP的重传(基于平均往返时间)是不需要的,TCP 确认的开销也不会存在。另外一个极端的情况是,用户不愿意等待很久。因此,TCP 的 大概 2分钟可靠传输也是不实用的。更快的使用一个备用的服务器允许用户在放弃等待前就能认证完毕。
  3. 这个协议是无状态的,此简化了UDP的使用。客户端和服务器来回交互。系统的重启是独立的。这不会造成很大的超时,也不用检测 TCP 连接的丢失,代码可以写来处理异常的事件。UDP 完全避免了这些特殊的处理。每个客户端和服务器都可以打开他们的 UDP 传输一次,然后让其一直打开,处理所有网络上的失败事件。
  4. UDP 简化了服务器的实现。在早期的 RADIUS 实现中,服务器是单线程的。这就是说,单个请求收到后进行处理,然后返回。这在后端安全机制需要时时的环境下被发现是无法管理的。服务器的请求队列被充满,在每分钟有很多用户进行认证的时候,这个往返时间将会超过用户的预期的等待。最明显的解决办法是让服务器成为多线程的。这个目标通过 UDP 很容易达成。独立的进程被派生出来为每个请求服务,然后直接传输到客户端的NAS。

使用 UDP 有一个要求:我们必须手动的管理到同个服务器的重传计时器。

报文格式

 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Code | Identifier | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Authenticator |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Attributes ...
+-+-+-+-+-+-+-+-+-+-+-+-+-

前的20字节意义是固定的。Authenticator 占 16 字节。

例子

NAS:192.168.1.16

User-Name:nemo

Port:3

Passowrd:arctangent

Request Authenticator 是一个16字节的 NAS 产生的随机数。

User-Password 是一个 16 字节的密码,以 null 填充,用 MD5(预共享密钥|Request Authenticator) 进行XOR 异或。

01 00 00 38 0f 40 3f 94 73 97 80 57 bd 83 d5 cb
98 f4 22 7a 01 06 6e 65 6d 6f 02 12 0d be 70 8d
93 d4 13 ce 31 96 e4 3f 78 2a 0a ee 04 06 c0 a8
01 10 05 06 00 00 00 03

1 Code = Access-Request (1)
1 ID = 0
2 Length = 56
16 Request Authenticator

Attributes:
6 User-Name = "nemo"
18 User-Password
6 NAS-IP-Address = 192.168.1.16
6 NAS-Port = 3
02 00 00 26 86 fe 22 0e 76 24 ba 2a 10 05 f6 bf
9b 55 e0 b2 06 06 00 00 00 01 0f 06 00 00 00 00
0e 06 c0 a8 01 03

1 Code = Access-Accept (2)
1 ID = 0 (same as in Access-Request)
2 Length = 38
16 Response Authenticator

Attributes:
6 Service-Type (6) = Login (1)
6 Login-Service (15) = Telnet (0)
6 Login-IP-Host (14) = 192.168.1.3

CHAP

01 01 00 47 2a ee 86 f0 8d 0d 55 96 9c a5 97 8e
0d 33 67 a2 01 08 66 6c 6f 70 73 79 03 13 16 e9
75 57 c3 16 18 58 95 f2 93 ff 63 44 07 72 75 04
06 c0 a8 01 10 05 06 00 00 00 14 06 06 00 00 00
02 07 06 00 00 00 01

1 Code = 1 (Access-Request)
1 ID = 1
2 Length = 71
16 Request Authenticator

Attributes:
8 User-Name (1) = "flopsy"
19 CHAP-Password (3)
6 NAS-IP-Address (4) = 192.168.1.16
6 NAS-Port (5) = 20
6 Service-Type (6) = Framed (2)
6 Framed-Protocol (7) = PPP (1)
02 01 00 38 15 ef bc 7d ab 26 cf a3 dc 34 d9 c0
3c 86 01 a4 06 06 00 00 00 02 07 06 00 00 00 01
08 06 ff ff ff fe 0a 06 00 00 00 02 0d 06 00 00
00 01 0c 06 00 00 05 dc

1 Code = Access-Accept (2)
1 ID = 1 (same as in Access-Request)
2 Length = 56
16 Response Authenticator

Attributes:
6 Service-Type (6) = Framed (2)
6 Framed-Protocol (7) = PPP (1)
6 Framed-IP-Address (8) = 255.255.255.254
6 Framed-Routing (10) = None (0)
6 Framed-Compression (13) = VJ TCP/IP Header Compression (1)
6 Framed-MTU (12) = 1500