Freeradius:请求没有用户密码属性的休息模块

Mar*_*ruz 2 freeradius

我正在尝试使用休息后端进行身份验证来设置半径服务器。我以以下项目为例:https : //github.com/fgsants/REST-API-FreeRADIUS

一切都已经设置好了,如果我使用以下命令来模拟在 radius 上的登录,一切都可以正常工作:

radtest bar passwd 127.0.0.1 10 testing123

其余后端接收/user/:username/mac?action=authorize然后/user/:username/mac?action=authenticate&password=passwd.

当我将 AP 配置为使用此半径服务器时,请求似乎与预期不同并且身份验证失败。这是尝试通过 AP 登录时半径服务器的输出:

(0) Received Access-Request Id 105 from 172.21.0.1:46358 to 172.21.0.3:1812 length 126
(0)   User-Name = "bar"
(0)   NAS-IP-Address = 192.168.0.21
(0)   NAS-Identifier = "RalinkAP1"
(0)   NAS-Port = 0
(0)   Called-Station-Id = "1A-0D-2C-1B-49-11"
(0)   Calling-Station-Id = "D4-9A-20-70-F4-0E"
(0)   Framed-MTU = 1400
(0)   NAS-Port-Type = Wireless-802.11
(0)   EAP-Message = 0x0201000801626172
(0)   Message-Authenticator = 0xbffda6639904c9026259be2a45b378c4
(0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default
(0)   authorize {
rlm_rest (rest): Reserved connection (0)
(0) rest: Expanding URI components
(0) rest: EXPAND http://rest:3000
(0) rest:    --> http://rest:3000
(0) rest: EXPAND /user/%{User-Name}/mac?action=authorize
(0) rest:    --> /user/bar/mac?action=authorize
(0) rest: Sending HTTP GET to "http://rest:3000/user/bar/mac?action=authorize"
(0) rest: Processing response header
(0) rest:   Status : 204 (No Content)
rlm_rest (rest): Released connection (0)
Need 5 more connections to reach 10 spares
rlm_rest (rest): Opening additional connection (5), 1 of 27 pending slots used
rlm_rest (rest): Connecting to "http://rest:3000"
(0)     [rest] = ok
(0)     if (ok) {
(0)     if (ok)  -> TRUE
(0)     if (ok)  {
(0)       update control {
(0)         Auth-Type := rest
(0)       } # update control = noop
(0)     } # if (ok)  = noop
(0)   } # authorize = ok
(0) Found Auth-Type = rest
(0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default
(0)   Auth-Type rest {
(0) rest: ERROR: You set 'Auth-Type = REST' for a request that does not contain a User-Password attribute!
(0)     [rest] = invalid
(0)   } # Auth-Type rest = invalid
(0) Failed to authenticate the user
(0) Using Post-Auth-Type Reject
(0) Post-Auth-Type sub-section not found.  Ignoring.
(0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default
(0) Delaying response for 1.000000 seconds
Waking up in 0.2 seconds.
Waking up in 0.7 seconds.
(0) (0) Discarding duplicate request from client ipv4 port 46358 - ID: 105 due to delayed response
(0) Sending delayed response
(0) Sent Access-Reject Id 105 from 172.21.0.3:1812 to 172.21.0.1:46358 length 20
Waking up in 3.9 seconds.
(0) Cleaning up request packet ID 105 with timestamp +15
Ready to process requests

Run Code Online (Sandbox Code Playgroud)

半径服务器似乎没有从 AP 接收密码:

(0)   User-Name = "bar"
(0)   NAS-IP-Address = 192.168.0.21
(0)   NAS-Identifier = "RalinkAP1"
(0)   NAS-Port = 0
(0)   Called-Station-Id = "1A-0D-2C-1B-49-11"
(0)   Calling-Station-Id = "D4-9A-20-70-F4-0E"
(0)   Framed-MTU = 1400
(0)   NAS-Port-Type = Wireless-802.11
(0)   EAP-Message = 0x0201000801626172
(0)   Message-Authenticator = 0xbffda6639904c9026259be2a45b378c4
Run Code Online (Sandbox Code Playgroud)

所以后来授权失败:

(0) rest: ERROR: You set 'Auth-Type = REST' for a request that does not contain a User-Password attribute!
Run Code Online (Sandbox Code Playgroud)

这是我的配置文件:

server default {

listen {
    type = auth
    ipaddr = *
    port = 0
    limit {
          max_connections = 16
          lifetime = 0
          idle_timeout = 30
    }
}

listen {
    ipaddr = *
    port = 0
    type = acct
    limit {
    }
}

authorize {
    rest
        if (ok) {
            update control {
                Auth-Type := rest
            }
        }
}

authenticate {
    Auth-Type rest {
        rest {
            updated = 1
        }
        if (updated) {
            ok
        }
    }
}

preacct {
    preprocess
    acct_unique
    suffix
}

accounting {
    detail
    rest
}

post-auth {
    update {
        &reply: += &session-state:
    }
}
}

Run Code Online (Sandbox Code Playgroud)

缺少了什么?需要做什么才能从接入点接收密码?

谢谢

Arr*_*ell 5

模块方法和认证方法

FreeRADIUS 模块有多种“方法”,每种方法处理处理 RADIUS 数据包的不同方面。

当模块在授权部分中列出时,将调用“授权”方法。authorize 方法用于收集附加信息以授权用户。

'authenticate' 方法在一个模块被列在身份验证部分时被调用,并且授权部分中的一个模块通过设置指定这个特定模块用于对用户进行身份验证control:Auth-Type = <module>

通常有两种方法可以验证用户:

  1. 将他们的凭据提交给外部身份验证服务器(在本例中通过调用rest.authenticate)。
  2. 从外部服务器检索他们“已知正确”密码的副本,并将其与用户提交的内容进行比较(在本例中通过调用rest.authorize)。

您需要决定要使用这些方法中的哪一种。

如果是方法 1,则用户需要将其密码以明文形式发送,以便将其提交给身份验证服务器。

如果是方法 2,那么您需要从另一台服务器以明文形式检索用户密码的副本。

这两种方法各有优缺点,您选择哪种方法会影响您可以使用的 EAP(可扩展身份验证协议)方法。

无线认证

协议分层

在您的示例中,您使用的是 WPA/2-Enterprise,在这种情况下,在 AP 和无线客户端之间运行的身份验证框架将为 802.1X。

使用 802.1X,AP 和无线客户端通过称为 EAPOL(EAP Over Lan)的协议交换身份验证数据包。802.1X 和 EAPOL 允许无线客户端在交换加密密钥(WPA 四次握手)之前以及无线客户端可以交换正常(非 EAPOL)数据包之前向身份验证服务器(通常是 RADIUS 服务器)提交凭据与 AP(如 DHCP 数据包)。

对于无线身份验证,EAPOL 和 RADIUS 主要用作 EAP 及其在身份验证尝试期间携带用户凭据的 EAP 的传输。

EAP 和 FreeRADIUS

当接入点在 RADIUS 数据包中转发 EAP 数据时,它会将 EAP 数据包拆分为 253 字节的块,并将这些块封装在 EAP 消息属性中。

当 FreeRADIUS 执行身份验证服务器的角色时,它需要重新组装那些 253 字节的块并运行它与无线客户端协商的任何 EAP 方法的状态机。

为了简化处理 EAP 身份验证的编写配置,FreeRADIUS 使用两个虚拟服务器。“外部”服务器处理身份验证尝试的 RADIUS 部分,“内部”服务器处理身份验证尝试的 EAP 部分。

除非您正在实施复杂的策略,否则外部服务器需要调用的唯一模块是“eap”。

在您的配置中,从授权和验证部分中删除所有内容,只留下 eap 模块:

authorize {
    eap
}

authenticate {
   eap
}
Run Code Online (Sandbox Code Playgroud)

当在授权部分调用 eap 模块时,eap 模块检查请求中是否存在一个或多个 EAP-Message 属性,并且设置为control:Auth-Type = EAP,因此在身份验证部分调用的模块也是 eap。

当在身份验证部分调用 eap 模块时,eap 模块将所有 EAP 消息属性连接回单个数据包,并运行 EAP 状态机,根据需要调用 EAP 子模块以运行不同的 EAP 方法。

哪个 EAP 方法首先运行由default_eap_typein决定raddb/mods-available/eap

如果您使用方法 1(用户提交明文凭据),则需要使用 EAP 方法(如 EAP-TTLS),它将明文凭据包装在 TLS 包装器中(以保护它们免遭窃取)。

设置default_eap_type = ttls是否要使用方法 1。

如果您使用方法 2(外部服务器提供纯文本凭据),您可以使用更广泛的 EAP 方法。PEAP(受保护的 EAP)是消费设备(电话、笔记本电脑、VoIP 电话等)中实施最广泛的 EAP 方法。与 TTLS 一样,PEAP 使用 TLS 包装器来保护凭证交换,但不是以明文形式发送用户密码,而是使用 MSCHAPv2 进行凭证交换,这意味着凭证永远不会以明文形式通过网络发送。

事实上,MSCHAPv2 仅提供对 TTLS 的有限额外保护,因为 MSCHAPv2 被认为已损坏,但如果您有运行 <= Windows 7 的旧客户端,您可能需要使用 PEAP,因为 EAP-TTLS 支持仅在 Windows 8 中添加。

设置default_eap_type = peap是否要使用方法 2。

内部虚拟服务器

用于基于 TLS 的 EAP 方法(如 TTLS 和 PEAP)的 FreeRADIUS 子模块通过单独的“内部”虚拟服务器运行合成请求(内部生成)。

此请求的目的是表示 TLS 包装器的解密和解码内容,并使其他模块(例如 rest、ldap、pap 等)以它们可以解释的标准形式使用该内容。

有一个示例内部虚拟服务器包含在名为sites-available/inner-tunnel. 此虚拟服务器在默认 EAP 模块中配置为默认服务器,您应该修改此服务器以设置验证用户凭据的方式。

方法一

EAP-TTLS 实际上可以运行许多不同的内部认证方法,甚至是 EAP 的另一层。这是因为 EAP-TTLS 允许在其 TLS 包装器内发送 RADIUS 属性空间中的多个属性。

然而,一般来说,大多数请求者会默认运行 PAP 作为内部身份验证方法,因此当您看到发送到内部虚拟服务器的合成请求时,它可能只包含User-NameUser-Password属性。

删除 的授权和验证部分中的所有现有文本sites-available/inner-tunnel

要么将原始示例中的文本复制到授权和身份验证部分,要么...我不确定您是否需要两次调用 REST 模块(老实说,自从我使用 v3 以来已经很长时间了),您可能想要尝试:

authorize {
   if (&User-Password) {
      update control {
          Auth-Type = rest
      }
   }
}

authenticate {
   rest {
      update = 1
   }
   if (update) {
      ok
   }
}
Run Code Online (Sandbox Code Playgroud)

方法二

对于 PEAP,TLS 包装器内容代表另一个“内部”EAP 对话。为了处理这个对话,我们需要首先检索用户的密码,然后调用inner-eap 模块。

注意:inner-eap 是 EAP 模块的另一个实例,但只启用了适合在另一个 EAP 对话中使用的 EAP 方法。inner-eap 应该在 中可用mods-available/eap_inner,您可能需要将此文件从mods-availablemods-enabled.

删除 的授权和验证部分中的所有现有文本sites-available/inner-tunnel

在授权部分列出了rest模块,然后是inner-eap模块:

authorize {
    rest
    inner-eap
}
Run Code Online (Sandbox Code Playgroud)

当您的 API 端点收到请求时,您需要返回一个control:Cleartext-Password属性以及用户的明文密码。

在 authentication 部分中只列出了内 eap 模块:

authenticate {
    inner-eap
}
Run Code Online (Sandbox Code Playgroud)