FreeRadius EAP-TLS 配置

来自 Alpine Linux

简介

相比使用预共享密钥 (WPA2),更安全的方式是使用 EAP-TLS 并为每个设备使用单独的证书。在之前的教程 在 Raspberry Pi 上使用 VPN 的 Linux 路由器 中,我提到过我会用 (Ubiquiti UniFi AP) 来做这件事。我已经用两部运行 CyanogenMod 11 (Android 4.4.4) 的手机测试过了。

安装

安装 FreeRadius

apk add freeradius freeradius-eap

证书

你将需要创建你的证书。最简单的方法是使用 FreeRadius 提供的脚本。这些脚本允许你轻松创建 CA(证书颁发机构)、服务器证书和客户端证书。记住要增加过期时间,如果默认的 60 天不适合你,并在 .cnf 文件中填写其他信息,就像 README 文件中说的那样。

该脚本的 readme 文件在 /etc/raddb/certs/README 中,或者可以在 这里 找到。

证书吊销列表

CRL 不是由脚本创建的,你必须手动创建。

我创建了一个名为 crl.cnf 的文件

[ ca ]
default_ca		= CA_default

[ CA_default ]
dir			= ./
certs			= $dir
crl_dir			= $dir/crl
database		= $dir/index.txt
new_certs_dir		= $dir
certificate		= $dir/ca.pem
serial			= $dir/serial
crl			= $dir/crl.pem
private_key		= $dir/ca.key
RANDFILE		= $dir/.rand
name_opt		= ca_default
cert_opt		= ca_default
default_days		= 730
default_crl_days	= 730
default_md		= sha256
preserve		= no
policy			= policy_match
crlDistributionPoints	= URI:http://www.example.com/example_ca.crl

[ policy_match ]
countryName		= match
stateOrProvinceName	= match
organizationName	= match
organizationalUnitName	= optional
commonName		= supplied
emailAddress		= optional

[ policy_anything ]
countryName		= optional
stateOrProvinceName	= optional
localityName		= optional
organizationName	= optional
organizationalUnitName	= optional
commonName		= supplied
emailAddress		= optional

[ req ]
prompt			= no
distinguished_name	= cacrl
default_bits		= 2048
input_password		= <password1>
output_password		= <password2>
x509_extensions		= v3_ca

[certificate_authority]
countryName		= <COUNTRY_CODE>
stateOrProvinceName	= Radius
localityName		= <REGION>
organizationName	= FreeRadius
emailAddress		= freeradius@localhost 
commonName		= "FreeRadius Certificate Authority"

[v3_ca]
subjectKeyIdentifier	= hash
authorityKeyIdentifier	= keyid:always,issuer:always
basicConstraints	= CA:true
crlDistributionPoints	= URI:http://www.example.com/example_ca.crl

创建吊销列表

openssl ca -gencrl -keyfile ca.key -cert ca.pem -out crl.pem -config crl.cnf

最后,创建一个新文件,它将同时保存 CA 和吊销的证书

cat ca.pem crl.pem > cacrl.pem

创建 Diffie-Hellman nonce 文件

openssl dhparam -check -text -5 -out /etc/raddb/certs/dh 1024

或者你可以使用更大的,例如(如果你不走运,这可能需要一段时间!)。

openssl dhparam -check -text -5 -out /etc/raddb/certs/dh 4096

服务器配置

WPA3 规范 (p12) 对 EAP 做了一些更改。即使你没有使用 WPA3,它仍然会影响你的 EAP RADIUS 认证,特别是对于 Android 11+ 等客户端。更多讨论在 这里

WPA 3.1 第 12 页

5.1.2 STA 配置了 EAP 凭据,该凭据明确指定了与接收到的服务器证书消息中的根证书匹配的 CA 根证书,并且如果 EAP 凭据还包含域名(FQDN 或仅后缀),则它与接收到的服务器证书消息中的证书 [2] 的域名(如果存在 SubjectAltName dNSName,否则为 SubjectName CN)匹配。

5.1.3 STA 配置了 EAP 凭据,该凭据包含与接收到的服务器证书消息中的证书 [2] 的域名(如果存在 SubjectAltName dNSName,否则为 SubjectName CN)匹配的域名(FQDN 或仅后缀),并且该证书的根证书存在于 STA 的信任根存储中。

如果没有这些更改,你会在 logcat 中看到类似以下的错误

EAP: Status notification: remote certificate verification (param=self signed certificate in certificate chain)
SSL: SSL3 alert: write (local SSL3 detected an error):fatal:unknown CA
EAP: Status notification: local TLS alert (param=unknown CA)

/etc/raddb/server.cnf

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

#  This should be a host name of the RADIUS server.
#  Note that the host name is exchanged in EAP *before*
#  the user machine has network access.  So the host name
#  here doesn't really have to match anything in DNS.
+ [alt_names]
+ DNS.1 = radius.example.com
+
+ # NAIRealm from RFC 7585
+ otherName.0 = 1.3.6.1.5.5.7.8.8;FORMAT:UTF8,UTF8:*.example.com

然后,当您添加 WiFi 网络时,您需要在“域”框中输入 “radius.example.com”。它在 wpa_supplicant.conf 或 NetworkManager 配置文件中也称为 “domain_suffix_match”。

/etc/raddb/certs/xpextensions

然后,您需要在进行配置之前更新 xpextensions。

+ [ xpserver_ext]
+ extendedKeyUsage = 1.3.6.1.5.5.7.3.1
+ crlDistributionPoints = URI:http://www.example.com/example_ca.crl

+ subjectAltName = @alt_names

and then at the bottom:

+ [alt_names]
+ DNS.1 = radius.example.com

+ # NAIRealm from RFC 7585
+ otherName.0 = 1.3.6.1.5.5.7.8.8;FORMAT:UTF8,UTF8:*.example.com

配置

/etc/raddb/clients.conf

首先,我们要添加一个客户端,这是你的 WiFi AP

client home {
    ipaddr = 192.168.1.10
    proto = *
    secret = <PASSWORD USED BY YOUR AP TO AUTHENTICATE WITH THIS RADIUS SERVER>
    shortname = <YOUR_SSID>
    require_message_authenticator = no
    nas_type = other

    limit {
        max_connections = 16
        lifetime = 0
        idle_timeout = 30
    }
}

/etc/raddb/mods-enabled/eap

接下来我们配置 eap。请注意 + 和 - 代表删除和添加的行,不要将它们包含在你的配置中!

你将要进行这些更改

- default_eap_type = md5
+ default_eap_type = tls
-   private_key_password = whatever
+   private_key_password = <Password you set output_password in server.cnf>
    private_key_file = ${certdir}/server.pem
-   ca_file = ${cadir}/ca.pem
+   ca_file = ${cadir}/cacrl.pem
-   random_file = /dev/urandom
+   random_file = /dev/random
- # check_crl = yes                 
+   check_crl = yes


将密码列表从 DEFAULT 减少到 HIGH,甚至是一个特定的列表

-   cipher_list = "DEFAULT"
+   cipher_list = "HIGH"

或者更短的列表,如果你决定的话(可能会导致一些设备兼容性问题)

+   cipher_list = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-RSA-CAMELLIA128-SHA"

将 ecdh 曲线更改为更强的曲线

-   ecdh_curve = "prime256v1"
+   ecdh_curve = "secp384r1"

你也可以将曲线增加到更高的位数 (521),但这可能会导致兼容性问题。

+   ecdh_curve = "secp521r1"

这些都适用于 Android 4.4.4,但是如果你有更旧的设备,你可能需要将列表设置为 HIGH 或 DEFAULT。

还有一些其他需要更改的地方

-     #name = "EAP module"
+     name = "EAP-TLS"
-     #persist_dir = "${logdir}/tlscache"
+     persist_dir = "${logdir}/tlscache"

/etc/raddb/sites-enabled/default

将监听端口更改为适合你的端口

- ipaddr = *
+ ipv4addr = 192.168.1.1

禁用 chap

#  The chap module will set 'Auth-Type := CHAP' if we are
#  handling a CHAP request and Auth-Type has not already been set
- chap
+ # chap

禁用 mschap

#  the MS-CHAP-Challenge attribute, and add 'Auth-Type := MS-CHAP'
#  to the request, which will cause the server to then use
#  the mschap module for authentication.
- mschap
+ # mschap

禁用 pap

#  This module should be listed last, so that the other modules
#  get a chance to set Auth-Type for themselves.

- pap
+ #pap

禁用我们不使用的认证类型

- Auth-Type PAP {
-   pap
- }
+ #Auth-Type PAP {
+ # pap
+ #}

- Auth-Type CHAP {
-   chap
- }
+ #Auth-Type CHAP {
+ # chap
+ #}

- Auth-Type MS-CHAP {
-   mschap
- }
+ #Auth-Type MS-CHAP {
+ # mschap
+ #}

启用 eap

-#  eap
+ eap

/etc/raddb/sites-available/tls

tls {
-   private_key_password = whatever
+   private_key_password = <Password you set input_password in server.cnf>
    private_key_file = ${certdir}/server.pem

IPtables 规则

接下来,你将需要一些 iptables 规则。

#Accept incoming connections from client FreeRadius
iptables -A IN_ETH0 -p tcp -s 192.168.1.10/24 --dport 1812 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A IN_ETH0 -p udp -s 192.168.1.10/24 --dport 1812 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

我还注意到,对于 Ubiquiti 设备,你需要允许这个才能使 AP 采纳工作

#Ubiquiti UAP Device Discovery Broadcast
iptables -A IN_ETH0 -p udp -s 192.168.1.10/24 --dport 10001 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

请注意,这些规则取决于最初在此处创建的链 在 Raspberry Pi 上使用 VPN 的 Linux 路由器#基本 IPtables 防火墙和路由

配置 AP

你将需要配置你的接入点以与你的新 Radius 服务器通信。

使用 clients.conf 中的 secret 和 shortname 将它们输入到你的接入点管理面板中。

启动 Radius

service radiusd start

添加到默认运行级别。

rc-update add radiusd default

你可以从控制台使用 radiusd -X 调试它,或者检查 /var/log/radius/radius.log,如果这不起作用。

配置设备

在 Android 上,我进入 “设置 > 安全 > 从存储设备安装” 并选择 ca.pem

然后我进行 “设置 > 安全 > 从存储设备安装” 并选择 client.p12”

输入正确的密码后,它应该可以工作。在 Android 上,你可能会看到一个警告,例如 “网络可能受到未知第三方的监控”。你可以通过将 CA 从 /data/misc/keychain/cacerts-added 移动到 /system/etc/security/cacerts 来修复此问题,确保用户和组是 root,并且权限设置为 644,即每个人都可读,只有 root 具有写入文件的权限。将其保存在 /sdcard/ 中,以便在您使用较新的 ROM 重新刷机时可以将其移回。

吊销证书

如果将来你想吊销特定用户的证书,你可以这样做

openssl ca -revoke user@example.com.pem -keyfile ca.key -cert ca.pem -config ca.cnf

<输入来自 ca.cnf 的 output_password>

现在,花点时间打开 index.txt,你应该看到证书索引号旁边有 “R”。如果你需要再次使此证书有效,你将编辑带有 “R” 的行以匹配其他证书的格式。

现在你需要再次创建 crl 列表,就像教程开始时所做的那样

openssl ca -gencrl -keyfile ca.key -cert ca.pem -out crl.pem -config crl.cnf

<输入来自 ca.cnf 的 output_password>

cat ca.pem crl.pem > cacrl.pem

吊销证书后,你需要重启 FreeRadius。

service radiusd restart

你可以使用以下命令验证证书是否被吊销

openssl crl -in /etc/raddb/certs/cacrl.pem -text

如果没有证书被吊销,你会看到

No Revoked Certificates.

如果一个或多个证书被吊销,你会看到

Revoked Certificates:
    Serial Number: <number of your cert>

参考