简介:这份文档面向需要在 Ubuntu 环境下搭建 802.1X 认证实验的网络运维与安全学习者,聚焦 Freeradius 与 EAP-TLS 双向认证的测试环境部署。内容围绕环境准备、Freeradius 安装、users 与 client.conf 配置、TLS 模块证书生成、eap 文件参数调整、路由器对接及客户端证书导入测试等环节展开,覆盖从服务端到终端的完整链路。资源包内仅含 1 个 docx 文件,约 472KB,以图文步骤形式记录配置命令与关键参数,便于对照操作。目前已有 2922 人学习,适合作为无线认证入门与实验排错的参考材料,帮助读者理解证书签发、共享密钥匹配及端口占用等常见问题的处理思路。
1. 为什么我宁愿在 Ubuntu 上从零搭一套 EAP-TLS 双向认证测试环境
很多做物联网、企业无线或 802.1X 接入的同行,第一次接触 EAP-TLS 时都会卡在同一个地方:证书链到底怎么签、服务端和客户端各自要装哪几个文件、FreeRADIUS 的配置改哪几行才生效。网上能搜到的教程要么只贴半截配置,要么默认你已经有一套现成的 PKI,照着敲完radtest能过,换成eapol_test就报 TLS alert,最后只能对着日志猜。我自己的血泪经验是:与其在别人的半成品环境里调玄学,不如在 Ubuntu 上用 FreeRADIUS 从零搭一套最小可复现的 EAP-TLS 双向认证测试环境,把证书、服务端、客户端、验证工具四件事一次跑通。这套环境适合三类人:要验证设备 802.1X 接入逻辑的嵌入式工程师、要给内部无线做认证联调的运维、以及需要离线复现认证失败场景的安全测试人员。它不依赖真实 AP,一台 Ubuntu 虚拟机加一个虚拟客户端就能把双向认证的握手过程完整走一遍。
2. 先把 EAP-TLS 双向认证的证书链讲透:谁签谁、谁验谁
2.1 双向认证到底“双向”在哪
EAP-TLS 和普通 HTTPS 最大的区别在于:HTTPS 通常只验服务端证书,客户端身份靠账号密码;而 EAP-TLS 要求服务端和客户端各自出示一张由可信 CA 签发的证书,双方互相验证对方证书链是否可信、是否在有效期内、用途字段是否匹配。服务端证书的 Extended Key Usage 要包含 serverAuth,客户端证书要包含 clientAuth,CA 证书则负责签发这两者。握手时服务端先发自己的证书链,客户端校验通过后再发自己的证书链,服务端校验通过,双方才进入 TLS 加密隧道,后续的认证信息都在隧道里传。理解这一点很关键:任何一端证书链不完整、EKU 不对、时间不对,握手都会在 TLS 阶段直接断掉,而不是等到 RADIUS 层才报错。
2.2 一套最小 PKI 需要哪几个文件
我一般会准备一个独立的 CA 目录,把根证书、服务端证书、客户端证书分开签,避免混用。最小集合如下表:
| 文件 | 作用 | 放在哪 |
|---|---|---|
| ca.crt | 根证书,双方都信任 | 服务端和客户端都要 |
| ca.key | 根私钥,只用于签发 | 只在 CA 机器上,签完可离线 |
| server.crt / server.key | 服务端证书和私钥 | FreeRADIUS 配置目录 |
| client.crt / client.key | 客户端证书和私钥 | 测试客户端目录 |
| dh | Diffie-Hellman 参数 | 服务端,用于前向保密 |
常见做法是用openssl手动签,而不是上完整的 PKI 套件,因为测试环境要的是可控和可复现。下面这段是我常用的签发脚本,注意-extensions部分决定了 EKU,写错就会在握手时报unsupported certificate purpose。
# 生成根 CA 私钥和自签根证书,有效期 3650 天 openssl genrsa -out ca.key 4096 openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \ -subj "/C=CN/O=TestLab/CN=Test Root CA" -out ca.crt # 生成服务端私钥和 CSR openssl genrsa -out server.key 2048 openssl req -new -key server.key -subj "/C=CN/O=TestLab/CN=radius.test.lab" -out server.csr # 用根 CA 签发服务端证书,EKU 必须是 serverAuth openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ -days 825 -sha256 -extfile <(printf "extendedKeyUsage=serverAuth") -out server.crt # 生成客户端私钥和 CSR openssl genrsa -out client.key 2048 openssl req -new -key client.key -subj "/C=CN/O=TestLab/CN=client01.test.lab" -out client.csr # 签发客户端证书,EKU 必须是 clientAuth openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ -days 825 -sha256 -extfile <(printf "extendedKeyUsage=clientAuth") -out client.crt # 生成 DH 参数,2048 位在测试环境足够,生成较慢可提前做 openssl dhparam -out dh 2048逻辑说明:根证书用-x509自签,服务端和客户端 CSR 都用同一把根私钥签,保证链能对上。-extfile里只写 EKU,是因为测试环境不需要 SAN,但如果你的客户端会校验 CN 或 SAN,就要补subjectAltName。-days 825是常见浏览器策略上限,测试环境可以更长,但别超过根证书有效期。DH 参数生成慢是正常的,可以提前跑,或者用openssl dhparam -dsaparam加速,但安全性略降。
2.3 证书用途字段写错会怎样
我踩过最典型的坑是:服务端证书忘了写serverAuth,客户端证书忘了写clientAuth,结果eapol_test直接报TLS alert handshake failure,FreeRADIUS 日志里只有一行eap_tls: SSL_read failed,看不出根因。后来用openssl x509 -in server.crt -text | grep -A1 "Extended Key Usage"才确认字段缺失。所以签完证书一定要验一遍:
# 检查服务端证书 EKU 是否包含 serverAuth openssl x509 -in server.crt -noout -text | grep -A1 "Extended Key Usage" # 检查客户端证书 EKU 是否包含 clientAuth openssl x509 -in client.crt -noout -text | grep -A1 "Extended Key Usage" # 验证证书链是否完整 openssl verify -CAfile ca.crt server.crt openssl verify -CAfile ca.crt client.crt如果openssl verify返回 OK,说明链没问题;如果返回unable to get local issuer certificate,通常是签发时没用同一把 CA,或者中间证书没带上。测试环境一般不用中间 CA,直接用根 CA 签最省事。
3. 在 Ubuntu 上装 FreeRADIUS 并跑通 EAP-TLS 的最小配置
3.1 安装与目录结构确认
Ubuntu 上装 FreeRADIUS 直接用 apt 即可,但要注意版本差异:20.04 默认是 3.0.x,22.04 也是 3.0.x,配置路径基本一致。安装后配置目录在/etc/freeradius/3.0/,证书默认放在/etc/freeradius/3.0/certs/。我一般会把上一步签好的文件复制进去,并改权限,否则 FreeRADIUS 以freerad用户运行时读不到私钥。
# 安装 FreeRADIUS 和 EAP 测试工具 sudo apt update sudo apt install -y freeradius freeradius-utils eapol-test # 备份默认配置,方便回滚 sudo cp -r /etc/freeradius/3.0 /etc/freeradius/3.0.bak # 复制证书到配置目录 sudo cp ca.crt server.crt server.key dh /etc/freeradius/3.0/certs/ sudo chown freerad:freerad /etc/freeradius/3.0/certs/server.key sudo chmod 640 /etc/freeradius/3.0/certs/server.key逻辑说明:freeradius-utils提供radtest,eapol-test提供eapol_test,后者才是真正走 EAP-TLS 握手的工具。权限不对时 FreeRADIUS 启动会报Failed to read private key,但日志可能只显示rlm_eap_tls: Failed initializing SSL context,容易误判成配置语法错。
3.2 改 eap 模块:指向证书和私钥
FreeRADIUS 的 EAP 配置在/etc/freeradius/3.0/mods-enabled/eap,核心是tls-config段。我一般只改这几行:
# 编辑 eap 模块配置 sudo nano /etc/freeradius/3.0/mods-enabled/eaptls-config tls-common { private_key_file = /etc/freeradius/3.0/certs/server.key certificate_file = /etc/freeradius/3.0/certs/server.crt ca_file = /etc/freeradius/3.0/certs/ca.crt dh_file = /etc/freeradius/3.0/certs/dh cipher_list = "DEFAULT" tls_min_version = "1.2" tls_max_version = "1.3" cache_enable = no verify_client = yes check_crl = no }参数说明:verify_client = yes是双向认证的关键,设为 no 就退化成单向认证,客户端证书不会被校验。tls_min_version建议至少 1.2,1.0/1.1 在很多新客户端上已被禁用。cache_enable在测试环境关掉,避免会话缓存干扰失败复现。check_crl测试环境没有 CRL,关掉即可。改完用sudo freeradius -XC做语法检查,返回Configuration appears to be OK再启动。
3.3 配置客户端来源和测试用户
FreeRADIUS 默认只允许 localhost 发认证请求,测试客户端如果不在本机,要在/etc/freeradius/3.0/clients.conf里加一段:
client test-client { ipaddr = 192.168.56.0/24 secret = testing123 require_message_authenticator = no }secret是 RADIUS 共享密钥,eapol_test里要填一样的值。require_message_authenticator在测试环境可以关,生产环境建议开。用户文件在/etc/freeradius/3.0/users,EAP-TLS 本身不依赖用户名密码,但 RADIUS 层需要一个身份标识,我一般加一行:
client01 Cleartext-Password := "whatever" Reply-Message := "EAP-TLS test user"这里的密码不会被真正校验,因为 EAP-TLS 走的是证书认证,但 FreeRADIUS 需要这个条目来匹配外层身份。启动服务:
sudo systemctl restart freeradius sudo systemctl status freeradius # 前台调试模式,能看到完整握手日志 sudo freeradius -X调试模式下如果看到Ready to process requests,说明服务端就绪。此时用radtest只能测 PAP,测不了 EAP-TLS,必须用eapol_test。
4. 用 eapol_test 跑通双向认证:命令、参数和日志怎么看
4.1 写一份最小 eapol_test 配置
eapol_test需要一个配置文件,指定网络、身份、证书路径和 RADIUS 服务端信息。我常用的最小配置如下:
network={ ssid="test-ssid" key_mgmt=WPA-EAP eap=TLS identity="client01" ca_cert="/etc/freeradius/3.0/certs/ca.crt" client_cert="/etc/freeradius/3.0/certs/client.crt" private_key="/etc/freeradius/3.0/certs/client.key" private_key_passwd="" }注意ca_cert必须指向根证书,client_cert和private_key是客户端自己的证书和私钥。identity要和users文件里的条目一致。如果私钥有密码,填private_key_passwd,测试环境一般不加密码,省去交互。
4.2 执行命令并解读关键日志
# -c 指定配置文件,-a 指定 RADIUS 服务端地址,-s 指定共享密钥 eapol_test -c eapol_test.conf -a 127.0.0.1 -s testing123 -p 1812成功时输出里会有SUCCESS,并且能看到EAP-TLS: TLS handshake completed。失败时重点看这几行:
SSL: Server certificate verification failed:客户端不信任服务端证书,检查ca_cert是否指向正确的根证书。TLS alert handshake failure:通常是 EKU 不对或证书链不完整,回到第 2 章检查。EAP: Failed to initialize EAP type TLS:客户端证书或私钥路径错,或者私钥权限不对。RADIUS: No response from server:服务端没起、端口不对、共享密钥不匹配。
我一般会同时开两个终端:一个跑sudo freeradius -X看服务端日志,一个跑eapol_test,这样握手每一步都能对上。服务端日志里eap_tls: TLS_accept: SSL_read之后如果出现eap_tls: Continuing EAP-TLS,说明证书交换正常;如果卡在SSL_read failed,基本就是证书问题。
4.3 验证双向认证是否真的生效
很多人以为eapol_test返回 SUCCESS 就是双向认证成功了,其实不一定。要确认服务端真的校验了客户端证书,可以做一个反向测试:把客户端证书换成一个由别的 CA 签发的证书,或者把客户端证书的 EKU 改成serverAuth,再跑一次。如果服务端仍然返回 SUCCESS,说明verify_client没生效,大概率是配置没加载或改错了文件。正确的表现是:客户端证书不可信时,服务端日志出现eap_tls: TLS Alert read:fatal:unknown CA或certificate verify failed,eapol_test返回 FAILURE。这个反向验证我每次搭环境都会做一遍,算是后悔药,能提前发现配置漏项。
5. 避坑与排查:EAP-TLS 测试环境最常见的 5 个翻车点
5.1 现象:eapol_test 报 unknown CA,但 ca.crt 明明是对的
原因:客户端配置里的ca_cert指向了服务端证书或中间证书,而不是根证书;或者服务端发送的证书链不完整,只发了 server.crt 没带 ca.crt。解决:确认ca_cert是根证书,服务端certificate_file如果只写 server.crt,FreeRADIUS 会自动拼接 ca.crt,但有些版本需要手动把 ca.crt 内容追加到 server.crt 后面。用openssl s_client -connect 127.0.0.1:1812 -cert client.crt -key client.key -CAfile ca.crt可以单独验证 TLS 层。
5.2 现象:服务端日志显示证书校验通过,但 RADIUS 返回 Access-Reject
原因:users文件里没有对应的identity条目,或者条目里的用户名和客户端identity大小写不一致。EAP-TLS 虽然靠证书认证,但 FreeRADIUS 仍会在授权阶段查用户。解决:在users文件里补上client01条目,或者把identity改成和现有条目一致。注意users文件对大小写敏感。
5.3 现象:FreeRADIUS 启动报错Failed to read private key
原因:server.key 权限不对,freerad用户读不到;或者私钥有密码但配置里没写private_key_password。解决:chown freerad:freerad server.key && chmod 640 server.key,如果有密码,在tls-config里加private_key_password = 你的密码。测试环境建议直接生成无密码私钥,省事。
5.4 现象:eapol_test 卡在EAP: Requesting identity不动
原因:客户端和服务端的 TLS 版本不匹配,比如服务端只开 1.3,客户端只支持 1.2;或者 cipher 套件不兼容。解决:在tls-config里把tls_min_version设为 1.2,tls_max_version设为 1.3,cipher_list用DEFAULT。如果还不行,用openssl ciphers -v 'DEFAULT'看双方支持的套件交集。
5.5 现象:换了一台客户端机器就连不上,报No response from server
原因:clients.conf里只允许了 localhost,新客户端 IP 不在允许范围;或者防火墙挡了 1812/1813 端口。解决:在clients.conf里加新客户端网段,sudo ufw allow 1812/udp。测试环境我一般直接sudo ufw disable,但生产环境千万别这么干。
6. 进阶技巧:用脚本批量验证证书链和握手成功率
搭好环境只是第一步,真正省时间的是把验证过程脚本化。我习惯写一个 bash 脚本,自动检查证书 EKU、有效期、链完整性,然后跑一轮eapol_test,把结果汇总成表格。这样每次改配置或换证书,跑一遍脚本就知道有没有回归。
#!/bin/bash # 批量验证 EAP-TLS 证书和握手 CA=/etc/freeradius/3.0/certs/ca.crt SERVER=/etc/freeradius/3.0/certs/server.crt CLIENT=/etc/freeradius/3.0/certs/client.crt echo "=== 证书链验证 ===" openssl verify -CAfile $CA $SERVER openssl verify -CAfile $CA $CLIENT echo "=== EKU 检查 ===" openssl x509 -in $SERVER -noout -text | grep -A1 "Extended Key Usage" openssl x509 -in $CLIENT -noout -text | grep -A1 "Extended Key Usage" echo "=== 有效期检查 ===" openssl x509 -in $SERVER -noout -dates openssl x509 -in $CLIENT -noout -dates echo "=== 握手测试 ===" eapol_test -c eapol_test.conf -a 127.0.0.1 -s testing123 -p 1812 | grep -E "SUCCESS|FAILURE|TLS"逻辑说明:openssl verify检查链,-text | grep检查 EKU,-dates检查有效期,最后跑eapol_test并只抓关键行。这个脚本可以放进 CI,每次改证书自动跑。参数上唯一要注意的是eapol_test的-a和-s要和clients.conf一致,否则会误报失败。
另一个进阶用法是模拟证书过期:用openssl x509 -req签发一张-days 0的证书,看服务端是否拒绝。正常表现是eapol_test报certificate has expired,服务端日志出现certificate verify failed。这个测试能验证check_crl和有效期校验是否真的生效。我自己的习惯是:每次搭完环境,先跑正向成功,再跑反向失败,两个都符合预期才算收工。这套流程帮我省了很多次“以为配好了其实没生效”的返工。希望帮到你。
本文还有配套的精品资源,点击获取