简介:围绕Ubuntu与Freeradius搭建802.1X EAP-TLS双向认证测试环境的实操文档,面向具备Linux基础、需要验证无线接入认证与证书链路的网络学习者及运维人员。压缩包仅含1个docx文件,约472KB,结构紧凑,便于按章节对照实验环境逐步操作。正文从Freeradius与openssl安装讲起,依次说明users文件、client.conf客户端参数、CA根证书与服务器/客户端证书生成、eap模块的私钥与证书路径配置,以及路由器RADIUS地址、共享密钥和WPA认证方式的对接设置。测试部分给出client.p12证书导入终端、选择EAP-TLS身份并连接热点的验证流程,同时整理了端口占用、证书读取权限等常见报错的排查思路。文档将环境准备、证书生成、服务配置与终端测试串成完整链路,可作为实验记录和排错清单使用。已有2926人学习,适合希望从零跑通双向认证流程、积累无线安全实验经验的读者参考。
1. EAP-TLS 双向认证测试环境:为什么值得自己搭一套
手上有一台设备要接 802.1X 无线网络,对方开口就要 EAP-TLS 双向证书认证——这种时候最省事的做法,是在本地用 Ubuntu 加 freeradius,搭一套能反复重启、能随时看日志、能随便换证书的测试环境,而不是在现网 AP 上猜。这套环境解决的就是「证书对不对、握手卡在哪一步、终端为什么报证书无效」这三个问题:freeradius 在前台 debug 模式下会把每一轮 EAP-Message 的收发都打印出来,相当于给认证过程开了个黑匣子。适合三类人:做无线准入和终端入网的工程师、需要验证自签证书链能不能被设备接受的固件开发者、以及要复现 802.1X 故障但不想动生产网络的人。整套东西不依赖任何商业组件,一台虚拟机就能跑。
2. 装包与认路:freeradius 3.0 装完先搞清目录分工
2.1 apt 安装与版本确认
Ubuntu 的 apt 源里就有 freeradius,装之前先把系统包索引刷一遍,避免装到半旧版本后发现和文档对不上。整套操作建议全程用 root,因为证书目录、私钥文件的所有者都是 freerad 用户,普通用户改完还得反复 sudo,反而容易漏掉 chown。
sudo su # 后续操作都在 root 下,省掉每条命令前的 sudo apt update # 刷新包索引,否则可能装到旧补丁版 apt-get install -y freeradius openssl # -y 免交互;openssl 用于证书生成与后续排查 freeradius -v # 打印版本,确认落在 3.0.x-y只是免掉确认,真正要留意的是版本号:3.0 系列和更早的 2.x 在配置路径上是两套东西,2.x 在/etc/freeradius/,3.0 在/etc/freeradius/3.0/,配置文件里的模块名也改过。装完先跑一次freeradius -v,把版本记下来,后面所有路径都以这个为准。
apt 安装完成后,服务默认会被 systemd 直接拉起来并占用 1812 端口。这一点很关键——后面用freeradius -X前台调试时如果直接报端口占用,多半就是它在后台跑着。
systemctl status freeradius # 看是不是 active (running) systemctl stop freeradius # 调试期间先停掉,避免抢 1812/1813 systemctl disable freeradius # 测试机可以顺手关掉开机自启
注意:调试阶段建议一直保持服务停止、只用freeradius -X前台跑,这样日志实时输出到终端,Ctrl+C 就能重启,比反复systemctl restart再看 journal 快得多。
2.2 目录分工与软链接机制
进到/etc/freeradius/3.0/之后别急着改文件,先把几个目录的职责分清楚,不然后面改了半天发现改的是mods-available里的模板、真正加载的是mods-enabled里的软链接。
| 路径 | 作用 | 是否常改 |
|---|---|---|
radiusd.conf | 主配置,定义$certdir、$cadir等变量和模块加载顺序 | 少改 |
clients.conf | 定义 NAS/AP 客户端段,决定谁能来问认证 | 必改 |
users | 本地账号表,明文密码、测试身份写这里 | 必改 |
mods-available/ | 所有模块的模板文件,改了不一定生效 | 看情况 |
mods-enabled/ | 指向 available 的软链接,真正被加载的模块 | 改这个 |
certs/ | 证书目录,含 Makefile 和生成产物 | 必用 |
sites-enabled/default | 虚拟服务器,决定请求走哪些模块 | 少改 |
cd /etc/freeradius/3.0 ls -l mods-enabled/eap # 确认 eap 是软链接,指向 ../mods-available/eap readlink -f mods-enabled/eap # 打印真实路径,改之前心里有数readlink -f这一步是我习惯性的动作:看到软链接指向哪,就知道 vim 打开的到底是哪个实体文件。曾经有一次在mods-enabled下直接rm了软链接再用 vim 新建,结果新文件权限和所有者都不对,freeradius 启动时读不到,报了个很含糊的模块加载失败。血泪经验是:软链接只做指向,内容永远改实体文件。
2.3 网络模式:桥接、静态 IP 与 1812/1813
虚拟机装 Ubuntu 的话,网络连接方式一定改成桥接模式。NAT 模式下虚拟机的 IP 是宿主机内部地址,AP 从无线侧回来的 RADIUS 响应包根本路由不进来,表现就是终端一直停在「正在认证」,而服务器侧一条日志都没有——这种「两边都觉得自己没问题」的现场最耗时间。
桥接之后给虚拟机配一个和 AP 同网段的静态地址,不要用 DHCP,否则重启后 IP 变了,clients.conf里的ipaddr又得跟着改。
ip -4 addr show # 确认拿到的地址和 AP 在同一网段 ss -lunp | grep -E '1812|1813' # 看 UDP 1812/1813 有没有被占用 ufw status # 如果开了防火墙,放行 RADIUS 端口 ufw allow 1812/udp ufw allow 1813/udp1812 是认证端口,1813 是计费端口。EAP-TLS 只跑认证的话 1813 用不上,但很多 AP 会同时发计费包,一并放行省得后面排查时多一个变量。ss -lunp比netstat快,-u只看 UDP,-p带进程名,端口被谁占了一眼就能看出来。
规划上给个参考:AP 管理地址 192.168.1.1,RADIUS 服务器 192.168.1.10,测试终端随便挂。这套地址后面会出现在clients.conf和 AP 的管理页面里,两处必须对得上。
3. 证书链自制:certs/Makefile 一跑,四个文件各管什么
3.1 EAP-TLS 为什么必须双向
EAP-TLS 和 PEAP、TTLS 最大的区别在于:它在 TLS 隧道建立之前就把证书摆上台面了。终端先验证服务器证书是不是自己信任的 CA 签的,服务器再验证终端递上来的客户端证书,两边都过了才继续往下走密钥协商。中间没有任何「先建隧道再验身份」的缓冲,所以任何一侧证书配错,握手直接断在最开始,日志里只会留下一句很笼统的 TLS 失败。
这也解释了为什么测试环境必须自成一套 CA:你不可能拿生产 CA 的私钥来签测试证书,而终端设备通常只信任内置根证书列表,自签 CA 装进去之后才能形成完整链路。整个过程里,CA 私钥只在签证书时用一次,签完就可以放在服务器上不动。
3.2 make 之前先改 Makefile 里的 CN 和有效期
certs/目录下有一个现成的 Makefile,一条make就能把整条链生成出来。但直接跑之前,先看看里面几个关键变量,尤其是 CN(Common Name)和证书有效期——默认值往往不适合真实设备。
cd /etc/freeradius/3.0/certs grep -nE 'CN|DAYS|PASSWORD|OPENSSL' Makefile | head -30这条命令只列关键行,不把整个 Makefile 打出来。要看的是三类东西:SERVER_CN之类的字段决定服务器证书的主体名,DAYS决定有效期,PASSWORD决定私钥和 p12 的导出密码。默认有效期通常很短,测试周期长的话会被证书过期坑一次,建议改成 365 天以上;CN 最好改成 AP 或服务器实际使用的标识,有些终端会拿它和配置里的域名比对。
cp Makefile Makefile.bak # 改之前先备份,这是后悔药 vim Makefile # 按上面 grep 出来的行号定位,改 CN 和 DAYS make # 开始生成,DH 参数那一步会卡几分钟make跑到生成 DH 参数时会长时间没有输出,这不是卡死。2048 位 DH 参数是逐个素数试出来的,慢是正常的,耐心等,别 Ctrl+C,中断后dh文件是半截的,后面握手会失败但报错很难懂。
3.3 四个产物逐一解读
生成完成后目录里会多出一堆文件,真正要关心的就四个加一个 DH:
| 文件 | 内容 | 密码 | 给谁用 |
|---|---|---|---|
ca.pem | 自签发根证书 | 无 | 服务器和终端都要装 |
server.pem | 服务器证书 | 无 | freeradius 用 |
server.key | 服务器私钥 | whatever(默认) | freeradius 用,不可外传 |
client.p12 | PKCS#12 打包的客户端证书+私钥 | whatever(默认) | 导入测试终端 |
dh | Diffie-Hellman 参数 | 无 | freeradius 用 |
ca.pem是信任锚,终端侧只要装了它,就等于承认「这个 CA 签发的服务器证书我都认」。client.p12是唯一需要离开服务器的文件,里面同时装了客户端证书和私钥,所以它必须带密码——这个密码在导入终端时会提示输入,忘了就得重新生成。
除了client.p12,Makefile 通常还会生成client.pem和client.key两个分离文件,用eapol_test做命令行验证时直接引用这两个更方便,不用先解包 p12。
3.4 权限收紧与 client.p12 的导出
生成出来的私钥文件默认权限往往偏宽,freeradius 启动时会检查,权限不对直接拒绝加载。正确的做法不是无脑 777,而是把所有者交给 freerad,再把其他用户的写权限去掉。
cd /etc/freeradius/3.0/certs chown freerad:freerad ca.pem dh server.key server.pem chmod 640 ca.pem dh server.key server.pem # 所有者读写,同组只读 chmod o-w ca.pem dh server.key server.pem # 兜底:确保其他人无写权限 ls -l ca.pem dh server.key server.pem # 确认结果把私钥设成 777 是很多教程里的顺手写法,能让服务起来,但等于把服务器私钥对系统上任何用户开放,测试机无所谓,一旦这套配置被照搬到别的地方就是隐患。640加chown freerad才是既能让服务读到、又不至于裸奔的写法。
导出到终端有两条路:一是scp拉到本地再传到手机或设备,二是直接 U 盘拷。不管哪种,client.p12落地后第一件事是确认文件大小不为 0,曾经有过scp中断留下空文件的翻车现场,导入时报「证书格式错误」,查了半天才发现是传输问题。
4. 三个配置文件串起来:users、clients.conf、eap
4.1 users:账号密码的正确写法
users文件是 freeradius 的本地账号表,格式是「身份名 + 属性 + 值」,字段之间用制表符或空格分隔。EAP-TLS 理论上只看证书不看密码,但身份名(Identity)必须能在某个地方对上,测试阶段最省事的做法就是在users里留一条明文记录,方便先用radtest确认服务本身是通的。
cd /etc/freeradius/3.0 cp users users.bak # 改配置文件前先备份,习惯动作 vim users在文件末尾加一行:
Testing Cleartext-Password := "password"几个细节值得说清楚。身份名Testing要和终端连接时填的 Identity 完全一致,大小写敏感;Cleartext-Password是 3.0 推荐的写法,会自动适配内部的密码比较逻辑,老的User-Password只在某些兼容场景下用;引号必须是半角双引号,从文档里复制过来的全角引号会让解析直接失败,而且报错信息不会告诉你是引号的问题,只会说「找不到匹配的用户」。这就是典型的玄学故障——配置看起来一模一样,就是不生效。
改完可以用radtest快速验一下服务链路:
radtest Testing password 127.0.0.1 0 testing123四个参数分别是身份、密码、服务器地址、NAS 端口号(0 表示本地)、共享密钥。返回Access-Accept说明 users 和 clients.conf 这两段是通的,此时还没碰 EAP,属于分层排查的第一步。
4.2 clients.conf:NAS 客户端段怎么写
clients.conf定义的是「谁有权来问认证」,也就是 AP 或路由器的身份。很多人第一次会去找一个叫client.conf的文件——原文里也是这么写的——实际文件名是复数形式的clients.conf,找不到文件的时候先ls | grep client确认一下,别急着新建。
cd /etc/freeradius/3.0 vim clients.conf在文件末尾追加一个客户端段:
client client1 { ipaddr = 192.168.1.1 secret = testing123 require_message_authenticator = no shortname = ap1 nas_type = other }| 参数 | 含义 | 怎么填 |
|---|---|---|
client1 | 段名,仅作标识 | 任意,能和别的段区分开即可 |
ipaddr | 允许发起请求的源地址 | 填 AP 的管理地址,不是终端地址 |
secret | 共享密钥,RADIUS 报文用它做完整性校验 | 和 AP 管理页面里填的必须逐字符一致 |
require_message_authenticator | 是否强制要求报文带 Message-Authenticator 属性 | 老设备填no,否则会被直接丢弃 |
shortname | 短名,日志里显示用 | 便于在日志里认出是哪个 AP |
nas_type | NAS 类型 | 不确定就填other |
ipaddr这里最容易填错:填成测试终端的地址,结果 AP 发来的包源地址对不上,服务端连日志都不打就把包扔了。判断方法很简单,看 AP 管理页面里配置的 RADIUS 服务器地址指向哪台机器,那台机器上的clients.conf里就要有 AP 自己的地址。
require_message_authenticator = no是为了兼容老设备。新版 freeradius 默认要求这个属性,而不少早期 AP 在发 Access-Request 时并不带,表现就是「配置全对但认证永远失败」,日志里连一条 Access-Request 都看不到。
4.3 eap 模块:default_eap_type=tls 与 tls-config 参数
EAP 模块决定用哪种 EAP 方法,以及 TLS 层用哪套证书。改的是mods-enabled/eap,如果它是软链接,vim 会顺着链接改到实体文件,这正是我们要的。
cd /etc/freeradius/3.0 vim mods-enabled/eap定位到eap {段,改成:
eap { default_eap_type = tls tls-config tls-common { private_key_password = whatever private_key_file = ${certdir}/server.key certificate_file = ${certdir}/server.pem ca_file = ${cadir}/ca.pem dh_file = ${certdir}/dh random_file = /dev/urandom ca_path = ${cadir} cipher_list = "DEFAULT" tls_min_version = "1.2" tls_max_version = "1.2" cache_enable = no } }| 参数 | 作用 | 填错的表现 |
|---|---|---|
default_eap_type | 默认 EAP 方法 | 不改成tls会走 PEAP,终端选 EAP-TLS 直接失败 |
private_key_password | server.key 的保护密码 | 和生成时不一致,启动即报解密失败 |
private_key_file | 服务器私钥路径 | 路径写错会在启动阶段报文件不存在 |
certificate_file | 服务器证书路径 | 和私钥不匹配会导致握手时签名校验失败 |
ca_file | 用于验证客户端证书的根证书 | 指错就等于不信任终端证书,握手在最后一步断 |
dh_file | DH 参数文件 | 文件缺失或半截会导致密钥交换阶段失败 |
tls_min/max_version | 允许的 TLS 版本区间 | 老设备只支持 1.0/1.1 时需要放宽,否则连不上 |
${certdir}和${cadir}是主配置里定义的变量,一般指向certs目录,用变量而不是硬编码路径,后面换目录时不用逐处改。cache_enable = no在测试环境里建议关掉,避免改了证书之后还命中旧缓存,出现「明明换了证书行为却没变」的诡异现象。
tls_max_version这一行很多人不写,默认会协商到 1.3。如果被测设备是几年前的老固件,很可能只支持到 1.2,现象是终端侧报「无法建立安全连接」而服务端日志只有一行 TLS 错误。测试环境里把上下限都压到 1.2,等确认链路通了再逐步放开,是更稳的排查顺序。
4.4 前台 debug 启动与日志读数
配置改完,用-X前台启动,把所有日志打到终端:
freeradius -X启动过程会打印一串模块加载信息,最后一行出现Ready to process requests才算真正就绪。中途任何模块加载失败都会以红色错误行显示,最常见的是证书文件读取失败和端口占用。
终端发起连接后,日志会按顺序出现几段关键内容:先是Received Access-Request,带User-Name和NAS-IP-Address;然后是 EAP 状态机的EAP-Start到EAP-Response/Identity;接着进入 TLS 握手,会打印TLS_Accept或TLS_Certificate相关行;最后以Access-Accept或Access-Reject收尾。定位问题时从后往前看:先看结论是 Accept 还是 Reject,再往上看是哪一步开始不对。
提示:-X模式下日志量大,建议开一个script -f radius.log之类的录制,或者把终端滚屏缓冲区调大,否则关键的那几行很容易被后续输出顶掉。
5. 避坑与排查:五个把认证卡死的现场
5.1 启动期:证书权限与端口占用
现象:freeradius -X刚跑几行就退出,报读取server.key失败,或者提示 1812 端口已被占用。
原因:前者是私钥文件所有者或权限不对,freeradius 以 freerad 用户身份运行,读不到 root 独占的文件;后者是 apt 装完自动启动的服务还在后台跑。
解决:权限按第 3.4 节处理,chown freerad:freerad加chmod 640;端口冲突先ss -lunp | grep 1812确认占用进程,再systemctl stop freeradius停掉后台实例。不需要重启整台机器,停服务就够。
5.2 配置期:全角引号与文件名笔误
现象:users里明明写了账号,radtest却返回Access-Reject,日志里说找不到用户;或者按文档去找client.conf发现文件不存在。
原因:从网页或文档复制配置时带进了全角引号、全角空格,解析器不认;配置文件名实际是clients.conf,少个 s 就找不到。
解决:用cat -A users | tail -5看行尾,全角字符会显示成异常的字节序列;实在不确定就手敲一遍那一行。文件名用ls /etc/freeradius/3.0/ | grep -i client确认。
5.3 连接期:终端侧证书选择与身份不匹配
现象:终端显示「正在认证」转圈十几秒后失败,服务端日志里能看到 Access-Request,但 TLS 握手没走完。
原因:终端连接配置里 CA 证书那一栏空着或选错,客户端证书没选对,或者 Identity 填的和users里的不一致。
解决:先把client.p12连同ca.pem一起导入终端,连接时 CA 证书选ca.pem(部分设备可以不选,但选了更利于排查),客户端证书选导入的那张,Identity 严格填Testing。日志里能看到终端上报的 Identity,和users对不上会直接体现出来。
5.4 兼容期:Message-Authenticator 与 TLS 版本
现象:AP 那边配置全对,服务端日志里连一条 Access-Request 都没有;或者有请求但立刻被丢弃,没有任何 EAP 交互。
原因:新版 freeradius 默认要求报文带 Message-Authenticator,老 AP 不发这个属性,包在进入处理流程前就被扔掉。另一种是 TLS 版本协商不上,服务端只开 1.2 而设备要 1.0。
解决:clients.conf里对应客户端段加require_message_authenticator = no;TLS 版本在tls-config里把tls_min_version下调。改完必须 Ctrl+C 重启-X,配置不是热加载的。
5.5 复现期:改了配置却像没生效
现象:证书重新生成了,eap文件也改了,重启后行为还是老样子。
原因:证书缓存没关,或者改的是mods-available/eap而不是mods-enabled/eap,后者才是被加载的。
解决:tls-config里设cache_enable = no;用readlink -f mods-enabled/eap确认实体路径,改完diff一下两个文件确认改动落在正确的那份上。
6. 从「能连上」到「可复现」:用 eapol_test 把认证跑成一条命令
手动拿手机连一次热点,一次两次还行,改十遍配置就要疯。更稳的做法是把 EAP-TLS 认证做成命令行可重复执行的动作,eapol_test就是干这个的——它是 wpa_supplicant 自带的测试客户端,能完整跑一遍 EAP 状态机,把结果以退出码返回。
装包和准备配置:
apt-get install -y wpasupplicant mkdir -p /root/eaptest && cd /root/eaptest新建tls-test.conf:
network={ key_mgmt=WPA-EAP eap=TLS identity="Testing" ca_cert="/etc/freeradius/3.0/certs/ca.pem" client_cert="/etc/freeradius/3.0/certs/client.pem" private_key="/etc/freeradius/3.0/certs/client.key" private_key_password="whatever" }这里用的是分离的client.pem和client.key,比 p12 少一步解包。identity必须和users里那行一致,private_key_password是生成时设的密码。
跑起来:
eapol_test -c tls-test.conf -s testing123 -a 127.0.0.1 -p 1812-c指定配置,-s是共享密钥(对应clients.conf里的 secret),-a和-p是服务器地址和端口。成功时会打印SUCCESS,失败时打印具体的 TLS 告警,退出码非 0。
这套东西的价值在于三点。一是回归快:改完eap或重新生成证书,一条命令就知道有没有把功能改坏,不用每次都去操作物理终端。二是日志对得上:eapol_test这边打印的每一步 TLS 交互,和服务端-X的输出能逐行对应,卡在哪一步非常明确。三是可进 CI:把这条命令包进脚本,make生成证书、重启 freeradius、跑eapol_test、断言退出码,整套环境就能在任意一台干净机器上重建。
一个实际经验:先用radtest验证 users 和 clients 两段配置,再用eapol_test验证 TLS 和证书链,最后才上真实设备验证 AP 透传和无线侧行为。这三层分开之后,任何一个失败都能立刻缩小到某一段配置,不会再出现「全挂了不知道从哪查」的局面。从那以后我每次改 freeradius 配置,都强制走一遍「radtest → eapol_test → 真机」这个顺序,中间任何一步不过就不往下走。希望帮到你。
本文还有配套的精品资源,点击获取