FreeRADIUS 3.2.10 配置参数详解

FreeRADIUS 3.2.10 配置体系详解:radiusd.conf 主框架(log/security 与 Blast-RADIUS 防护)、clients.conf NAS 定义、users 平面授权、sites-enabled/default 流水线实测逐行轨迹、eap/sql/ldap 模块参数与 MySQL 后端连库实测、生产配置模板。

FreeRADIUS身份认证网络LDAP2026/10/27

FreeRADIUS 3.2.10 配置参数详解

目标:吃透 FreeRADIUS 3.2.10 的配置体系——radiusd.conf 主框架、clients.conf 客户端定义、users 平面文件授权、sites-enabled/default 请求处理流水线,以及 eap/sql/ldap 三类核心模块的参数结构。全部配置片段取自 Ubuntu 22.04 上 apt 安装的 3.2.10 实机(/etc/freeradius/),关键行为(配置校验、MySQL 后端写入、EAP-MD5 交互)均在实机验证通过。

一、环境信息

  • 操作系统:Ubuntu 22.04 LTS(jammy),x86_64
  • FreeRADIUS 版本:3.2.10-1(官方 InkBridge deb 仓库安装,freeradius、freeradius-utils、freeradius-mysql、freeradius-ldap 全套)
  • 配置根目录:/etc/freeradius/(deb 版;源码编译版为 /usr/local/etc/raddb/)
  • 主配置:/etc/freeradius/radiusd.conf;NAS 客户端:clients.conf;用户文件:users
  • 虚拟服务器:sites-enabled/default(认证/计费)、sites-enabled/inner-tunnel(EAP 内层)
  • 模块目录:mods-available/(可用)与 mods-enabled/(已启用,软链)
  • 实测后端:本机 MySQL 8.0(radius 库,sql 模块真实连库并写入 radpostauth)
  • 服务管理:freeradius.service(systemd),运行身份 freerad:freerad
  • 字典目录:/usr/share/freeradius/(含 dictionary 主文件与 dictionary.dhcp 等)

二、前置条件

本文是配置详解篇,默认你已有一台装好 FreeRADIUS 3.2.10 的服务器。若尚未安装,按 《Ubuntu 22.04 安装 FreeRADIUS 3.2.10 指南》完成安装后再回来;组件定位与选型背景见 《FreeRADIUS 3.2.10 介绍与选型指南》。

验证配置环境就绪:

freeradius -v | head -1
ls /etc/freeradius/

实测回显:

radiusd: FreeRADIUS Version 3.2.10 (git #9071ea041), for host x86_64-pc-linux-gnu
certs  clients.conf  dictionary  hints  huntgroups  mods-available  mods-config
mods-enabled  policy.d  proxy.conf  radiusd.conf  sites-available  sites-enabled  users

/etc/freeradius/ 下的三层结构是理解全部配置的地图:

层文件/目录职责
主框架radiusd.conf日志、安全、线程、模块搜索路径等全局参数
客户端clients.conf哪些 NAS 设备允许发请求、用什么共享密钥
用户users平面文件用户与授权属性(默认认证后端之一)
站点sites-enabled/default、inner-tunnel请求进入后的处理流水线(authorize/authenticate/...)
模块mods-enabled/*.conf各认证/存储后端的实例化参数
代理proxy.conf转发到上游 RADIUS 服务器的拓扑定义
字典dictionary + /usr/share/freeradius/属性名 ↔ 编号映射(协议词表)

💡 技术拓展:FreeRADIUS 的「用户数据存哪里」有多种后端可选,配置入口与适用场景对比——

后端模块配置文件适用场景
平面文件filesusers实验环境、少量账号、最快上手
SQL 数据库sqlmods-enabled/sql用户量大、需 Web 管理界面(配合 daloRADIUS 等)
LDAP 目录ldapmods-enabled/ldap企业已有 AD/OpenLDAP 统一账号体系
Unix 系统用户unixmods-enabled/unix复用 /etc/passwd,安全收敛期少用
PAMpammods-enabled/pam对接系统级认证栈(如 OTP)

本文对 files(默认启用、实测闭环)、sql(实测连 MySQL)、ldap(参数结构详解)三类逐一展开;3.2.10 的默认流水线同时挂了 files 与 sql,谁先匹配谁生效。

三、参数查看与修改方式

改任何参数前先掌握三件事:参数在哪个文件、当前值是多少、改完如何验证。

3.1 查看生效配置

FreeRADIUS 没有独立的 show config 命令,两种官方口径的查看方式:

# 方式一:直接读配置文件(模块用 mods-enabled 下的软链文件)
grep -n "max_attributes\|reject_delay\|status_server" /etc/freeradius/radiusd.conf

实测回显:

466:max_attributes = 200
472:reject_delay = 1
474:status_server = yes
# 方式二:调试模式启动,配置解析全过程逐行打印(含每个模块加载与参数展开)
freeradius -X 2>&1 | head -25

实测回显(-X 启动头部节选,配置加载清单一目了然):

FreeRADIUS Version 3.2.10
Copyright (C) 1999-2026 The FreeRADIUS server project and contributors
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE
You may redistribute copies of FreeRADIUS under the terms of the
GNU General Public License
For more information about these matters, see the file named COPYRIGHT

FreeRADIUS is developed, maintained, and supported by InkBridge Networks.
For commercial support, please email sales@inkbridgenetworks.com
https://inkbridgenetworks.com/
Starting - reading configuration files ...
including dictionary file /usr/share/freeradius/dictionary
including dictionary file /usr/share/freeradius/dictionary.dhcp
including dictionary file /usr/share/freeradius/dictionary.vqp
including dictionary file /etc/freeradius/dictionary
including configuration file /etc/freeradius/radiusd.conf
including configuration file /etc/freeradius/proxy.conf
including configuration file /etc/freeradius/clients.conf
including files in directory /etc/freeradius/mods-enabled/

-X 是排查「配置到底生效没」的最权威手段:所有 if 分支展开、模块实例化顺序、变量替换结果都会逐行打印。

3.2 修改与校验的标准动作

# 修改后先做配置校验(不监听端口,纯解析)
freeradius -C
echo $?

实测回显(配置合法时):

0

freeradius -C 校验通过时无任何输出、退出码 0。语法错误时退出码为 1,但在 deb 默认配置(日志走文件)下控制台不打印错误详情,此时用 -X 看真实报错:

# 实测:向 radiusd.conf 追加一个多余的 '}' 后
freeradius -X 2>&1 | tail -1

实测回显:

Errors reading or parsing /etc/freeradius/radiusd.conf

校验通过后重启服务生效:

systemctl restart freeradius
systemctl is-active freeradius

实测回显:

active

⚠️ 注意:3.2.10 的配置解析器对「类型不匹配」「重复键」是宽容的(实测把 max_attributes 改成带引号的字符串、以及追加重复的 max_attributes 行,-C 均返回 0);真正会挂的是结构性错误(括号不配对、引用不存在的变量)。所以「-C 通过」只代表能解析,业务语义仍需靠 radtest 回归验证。

四、参数总览

文件关键参数段一句话职责
radiusd.conflog、security、max_request_time、max_servers全局运行框架
clients.confclient <name> { ipaddr/secret/... }NAS 准入与共享密钥
users<用户名> Cleartext-Password := ...平面文件认证与授权属性
sites-enabled/defaultauthorize/authenticate/accounting/post-auth请求处理流水线
sites-enabled/inner-tunnelEAP 内层虚拟服务器隧道内二次认证
mods-enabled/eapdefault_eap_type、tls-configEAP 类型与 TLS 证书
mods-enabled/sqldialect、driver、server、radius_dbSQL 后端连接与查询模板
mods-enabled/ldapserver、base_dn、user.filterLDAP 后端连接与查找
proxy.confhome_server、home_server_pool、realm上游转发拓扑

下面按这个顺序逐段展开。

五、核心参数分类详解

5.1 radiusd.conf:全局运行框架

radiusd.conf 是唯一定义「服务怎么跑」的文件。核心段落如下(实测节选自 3.2.10 默认文件)。

日志段 log(逐项含义见注释):

log {
	destination = files          # 日志去向:files/syslog/stdout/null
	colourise = yes              # 终端着色(仅 destination=stdout 时有意义)
	file = ${logdir}/radius.log  # 主日志文件,${logdir} 引用上文变量 /var/log/freeradius
	syslog_facility = daemon     # destination=syslog 时的 facility
	stripped_names = no          # 日志中是否隐藏用户名
	auth = no                    # 是否记录每个认证请求的摘要(排障时改 yes)
	auth_badpass = no            # 失败认证是否记录密码(安全敏感,保持 no)
	auth_goodpass = no           # 成功认证是否记录密码(同上,严禁生产开启)
	msg_denied = "You are already logged in - access denied"
}

关键取舍:auth = no 时 radius.log 只记服务生命周期与错误,不含每次认证——这就是「认证成功了但日志里找不到记录」的原因;排障期临时把 auth 改 yes,事后必须改回。

安全段 security(3.2.10 实测值):

security {
	user = freerad            # 启动后降权到的运行用户
	group = freerad           # 运行组(读取 /etc/freeradius 需要 freerad 属组)
	allow_core_dumps = no     # 崩溃转储开关
	max_attributes = 200      # 单个请求允许的最大属性数(防御畸形包)
	reject_delay = 1          # Access-Reject 延迟秒数(抗爆破,0 会放大字典攻击面)
	status_server = yes       # 响应 Status-Server 心跳包(radclient status 用)
	require_message_authenticator = yes   # Blast-RADIUS 防护:强制校验 Message-Authenticator
	limit_proxy_state = auto  # Blast-RADIUS 防护:对非代理请求强制 Proxy-State 校验
}

require_message_authenticator 与 limit_proxy_state 是 3.2 系列针对 Blast-RADIUS(CVE-2024-3596)的默认强化——3.0 系列默认值更宽松,升级迁移时这两项行为差异需要留意。

性能框架参数(同文件其他位置):

参数默认值说明
max_request_time30单请求最长处理秒数,超时丢弃
cleanup_delay5请求上下文保留秒数(重传去重窗口)
max_requests16384同时在处理的请求上限
max_servers=max_requests工作线程数上限
hostname_lookupsno反解客户端 IP(开了拖慢认证)
logdir/radacctdir/var/log/freeradius(/radacct)日志与计费明细目录

5.2 clients.conf:NAS 客户端定义

RADIUS 是「服务器信任 NAS」的模型:不在 clients.conf 里的来源 IP 一律不理睬。实测文件内容(默认两条 + 本文实验新增一条):

client localhost {
	ipaddr = 127.0.0.1        # 匹配的客户端来源 IP(单 IP 用 ipaddr,网段用 ipaddr = a.b.c.d/24)
	proto = *                 # 同时接受 udp 与 tcp
	secret = testing123       # 共享密钥,NAS 侧必须与此完全一致
	nas_type	 = other      # NAS 厂商类型(cisco/mikrotik/other),影响部分属性语义
	limit {
		max_connections = 16  # 该 client 的最大并发连接
		lifetime = 0          # 连接最长寿命(0 不限)
		idle_timeout = 900    # 空闲超时秒数
	}
}
client localhost_ipv6 {
	ipv6addr	= ::1
	secret		= testing123
}
client office-nas {
	ipaddr		= 10.89.56.0/24   # 按网段授权一整组接入设备
	secret		= nasSecret2026
	shortname	= office-switch   # 日志与计费明细里显示的短名
	nastype		= other
}

逐项说明:

  • ipaddr 与 ipv6addr 二选一;可写单 IP 或 CIDR 网段,服务器按最长匹配选 client。实测把 office-nas 定义为 10.89.56.0/24 后,从该网段内地址发起的请求(NAS-IP-Address=10.89.56.2)按这条 client 处理。
  • secret:RADIUS 安全的根基。实测用错误密钥发请求,客户端侧表现为 No reply from server(重试 3 次),而服务端日志给出明确原因——这是「密钥不一致」与「网络不通」的关键区分点:
Dropping packet without response because of error: Received packet from 10.89.56.2
with invalid Message-Authenticator!  (Shared secret is incorrect.) (from client office-switch)
  • 密钥强度:默认 testing123 只有 10 字符,服务端启动时会给警告 Shared secret for client localhost is short, and likely can be broken by an attacker.;生产密钥建议 22 字符以上,可用工具链里的 radsecret 生成(实测输出形如 qh/HOmmIpvcsGPay)。

5.3 users:平面文件用户与授权

users 文件是 files 模块的数据源,语法为「每行一个用户 + 缩进的回复属性」。本文实测账号(文件末尾新增):

admin	Cleartext-Password := "q1w2e3r4"
	Reply-Message = "Welcome, admin"
  • 第一列是用户名,Cleartext-Password := "..." 是检查项(:= 表示赋值覆盖);后面缩进行是命中后附加的回复属性(Reply-Message 会随 Access-Accept 原样返回给 NAS)。
  • 实测闭环:radtest admin q1w2e3r4 127.0.0.1 0 testing123 返回 Access-Accept 且带 Reply-Message = "Welcome, admin";密码错误时返回 Access-Reject——注意 Reject 里也带了 Reply-Message,说明 users 命中后回复属性在拒绝分支同样下发,敏感场景不要在 users 里放暴露信息的回复属性。
  • 文件自带的结尾注释点明语义:On no match, the user is denied access——files 未匹配且其他后端也没命中时默认拒绝。
  • 生产口径:users 适合实验与兜底账号;正式用户放 SQL/LDAP(见 5.6/5.7),users 只留管理员与应急账号。

5.4 sites-enabled/default:请求处理流水线

虚拟服务器把模块编排成流水线,是 FreeRADIUS 灵活性的核心。default 站点的段落骨架(实测行号):

段落行号职责
server default47虚拟服务器开始
listen(1812 认证)59监听地址与端口
listen(1813 计费)223计费通道
listen(18120)264EAP 内层测试端口(仅 127.0.0.1)
authorize303认证前置:找用户、定 Auth-Type
authenticate584按 Auth-Type 真正比对凭据
accounting722计费请求处理
session800会话检查(Simultaneous-Use)
post-auth812认证后加工与审计
pre-proxy/post-proxy1137/1192转发前后的属性加工

authorize 段的实测执行顺序(用 freeradius -X + 一次真实 radtest 抓取,节选):

(0)   authorize {
(0)     policy filter_username { ... }        # 用户名合法性过滤(空格/双@/连续点)
(0)     [preprocess] = ok                     # 剥 hints、规范化属性
(0)     [chap] = noop                         # 探测 CHAP 密码属性
(0)     [mschap] = noop
(0)     [digest] = noop
(0) suffix: No '@' in User-Name = "admin", looking up realm NULL
(0)     [suffix] = noop                       # Realm 域分离
(0) eap: No EAP-Message, not doing EAP
(0)     [eap] = noop                          # EAP 探测(PAP 请求无 EAP 属性则跳过)
(0) files: users: Matched entry admin at line 209
(0)     [files] = ok                          # 平面文件命中
(0) sql: Executing select query: SELECT id, username, attribute, value, op FROM radcheck WHERE username = 'admin' ORDER BY id
(0) sql: WARNING: User not found in radcheck table.
(0)     [sql] = notfound                      # SQL 未命中继续走下一模块
(0)     [expiration] = noop
(0)     [logintime] = noop
(0)     [pap] = updated                       # 依据已有密码属性确定 Auth-Type = PAP
(0)   } # authorize = updated

两个关键机制:

  • 短路语义:模块返回值决定流水线走向,reject 直接拒绝、accept 直接接受、ok/notfound/noop 继续向下。files 命中后 sql 仍会执行(返回 notfound 继续走),而任何模块返回 reject 则立即终止。
  • Auth-Type 协商:authorize 阶段不比对密码,只决定「用哪种方式比对」;[pap] = updated 后进入 authenticate 段的 Auth-Type PAP { pap } 分支,实测日志:
(0)   Auth-Type PAP {
(0) pap: Login attempt with password
(0) pap: Comparing with "known good" Cleartext-Password
(0) pap: User authenticated successfully
(0)     [pap] = ok
(0)   } # Auth-Type PAP = ok

post-auth 段的实测行为:3.2.10 默认启用了 sql 的 post-auth 记账(写 radpostauth 表),实测展开的 INSERT:

(0) sql: EXPAND INSERT INTO radpostauth (username, pass, reply, authdate ) VALUES ( '%{SQL-User-Name}', '%{%{User-Password}:-%{Chap-Password}}', '%{reply:Packet-Type}', '%S.%M' )
(0) sql:    --> INSERT INTO radpostauth (username, pass, reply, authdate ) VALUES ( 'admin', 'q1w2e3r4', 'Access-Accept', '2026-10-27 06:27:54.014642' )
(0) sql: SQL query returned: success

⚠️ 注意:radpostauth 表明文记录密码(上例中 q1w2e3r4 直接可见)。这是默认模板的行为,生产上若开 post-auth 审计,务必改 mods-config/sql/main/mysql/queries.conf 中的 postauth_query,剔除 %{%{User-Password}:-%{Chap-Password}}。

5.5 mods-enabled/eap:EAP 认证体系

EAP 模块管理可扩展认证(802.1X 无线/有线接入的核心)。实测默认配置头部:

eap {
	default_eap_type = md5      # 默认 EAP 方法(实验用 md5,生产 Wi-Fi 用 peap/tls)
	timer_expire = 60           # EAP 会话状态保留秒数
	ignore_unknown_eap_types = no
	cisco_accounting_username_bug = no
	max_sessions = ${max_requests}
	md5 {                       # EAP-MD5 子段( challenge-response 校验)
	}
	gtc {                       # EAP-GTC(明文口令质询,常配 PAP 语义)
		auth_type = PAP
	}
	tls-config tls-common {     # 所有 TLS 系方法共用的证书配置
		private_key_password = whatever
		private_key_file = ${certdir}/server.pem
		...
	}
}

💡 技术拓展:default_eap_type 不止 md5 一种,主流 EAP 方法对比——

方法隧道凭据保护适用场景
EAP-MD5无仅挑战应答,可离线字典攻击实验验证、有线 802.1X 兜底
EAP-TLS双向 TLS证书双向认证,最安全有 PKI 体系的企业 Wi-Fi
PEAP-MSCHAPv2TLS 隧道隧道内 MSCHAPv2AD 域环境最常见
EAP-TTLS/PAPTLS 隧道隧道内明文(受 TLS 保护)后端只支持 PAP/LDAP 时

本文实测用默认 md5(服务端开箱即用、radtest 原生支持);生产无线认证主流是 PEAP-MSCHAPv2 或 EAP-TLS,二者依赖 tls-config tls-common 的证书链,证书用 /etc/freeradius/certs/bootstrap 生成实验自签证书。

EAP 认证的请求会进入 sites-enabled/inner-tunnel 做内层认证——这是 default 之外第二个虚拟服务器的存在意义。

5.6 mods-enabled/sql:SQL 后端(实测 MySQL)

sql 模块把用户/组/计费数据放进关系库。实测配置(/etc/freeradius/mods-enabled/sql,MySQL 后端):

sql {
	dialect = "mysql"           # 方言:mysql/postgresql/sqlite/mssql 等
	driver = "rlm_sql_mysql"    # 驱动(包 freeradius-mysql 提供)
	server = "localhost"        # 数据库地址
	port = 3306
	login = "radius"            # 连接账号
	password = q1w2e3r4         # 连接密码(生产用强密钥并收紧权限)
	radius_db = "radius"        # 库名,radcheck/radreply/radusergroup/radacct 所在库
	...
}

逐项说明与实测行为:

  • dialect 决定读哪套查询模板:mods-config/sql/main/${dialect}/queries.conf(认证查 radcheck/radusergroup,计费写 radacct,审计写 radpostauth)。改 SQL 语句应改 queries.conf 而不是模块文件。
  • 实测认证时对 MySQL 的真实查询序列(-X 抓取):
(0) sql: EXPAND SELECT id, username, attribute, value, op FROM radcheck WHERE username = '%{SQL-User-Name}' ORDER BY id
(0) sql: Executing select query: SELECT id, username, attribute, value, op FROM radcheck WHERE username = 'admin' ORDER BY id
(0) sql: WARNING: User not found in radcheck table.
(0) sql: EXPAND SELECT groupname FROM radusergroup WHERE username = '%{SQL-User-Name}' ORDER BY priority
(0) sql: User not found in any groups
  • 实测计费闭环:radclient 发 Accounting-Request(Start/Stop)后服务端写 radacct 明细,-X 下可见对应 INSERT;post-auth 写 radpostauth(见 5.4)。
  • ⚠️ 迁移高频坑(实测确认):3.2 的 mods-available/sql 中 mysql 段展开了一个 tls {} 块(实测位于第 154 行,含 ca_file/certificate_file/private_key_file)。从 3.0 迁移直接拷旧配置或启用该段而证书文件不存在时,模块实例化失败、服务启动报错。不需要 MySQL TLS 就注释整段,或把路径填成真实证书。
  • 启用方式:ln -s /etc/freeradius/mods-available/sql /etc/freeradius/mods-enabled/sql,再 systemctl restart freeradius。

5.7 mods-enabled/ldap:LDAP 后端(文档口径)

ldap 模块对接 AD/OpenLDAP。默认配置骨架(实测节选,本文未连真实目录服务,以下为参数口径说明):

ldap {
	server = 'localhost'        # 目录服务器,可空格分隔多个
	base_dn = 'dc=example,dc=org'
	sasl {                      # SASL 绑定(GSSAPI/Kerberos 场景)
	}
	update {
		control:Password-With-Header	+= 'userPassword'   # 把 userPassword 带入服务端比对
		control:			+= 'radiusControlAttribute'
		request:			+= 'radiusRequestAttribute'
		reply:				+= 'radiusReplyAttribute'
	}
	user_dn = "LDAP-UserDn"
	user {
		base_dn = "${..base_dn}"
		filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"   # 用户查找过滤器
		...
	}
}

口径要点:

  • 认证流程:authorize 阶段按 user.filter 查 DN → 绑定验证密码(或取回 Password-With-Header 交给 pap 模块比对)→ 命中后把 LDAP 属性映射为 RADIUS 回复属性。
  • 启用需安装 freeradius-ldap 包并建软链;默认 server = 'localhost' 指向本机目录服务。
  • ⚠️ 实测启动日志警告(OpenLDAP 2.5.20 环境):libldap is using GnuTLS, while FreeRADIUS is using OpenSSL ... There may be random issues with TLS connections due to this conflict.——Ubuntu 仓库的 libldap 链接 GnuTLS,与 FreeRADIUS 的 OpenSSL 并存时 ldaps/TLS 连接可能出现随机失败,生产上建议用链接 OpenSSL 的 libldap 构建(官方 wiki 的 Rlm_ldap 页面有说明),纯明文 ldap:// 连接不受影响。

5.8 proxy.conf:上游转发拓扑

FreeRADIUS 同时是成熟的 RADIUS 代理。proxy.conf 定义「转发到谁」(实测默认文件骨架):

proxy server {
	default_fallback = no       # realm 无匹配时是否回落默认转发
}
home_server localhost {         # 上游服务器定义
	type = auth                 # auth/acct/auth+acct
	ipaddr = 127.0.0.1
	port = 1812
	secret = testing123         # 与上游的共享密钥
	response_window = 20        # 等响应窗口秒数
	zombie_period = 40          # 判定上游僵尸的观察期
	...
}

home_server_pool 把多个 home_server 编成池(fail-over/负载均衡),realm 段按用户名 @ 后缀决定是否转发。单机部署不改此文件即可;default_fallback = no 保证未定义 realm 的请求就地处理而不是误转发。

六、生产配置模板

以下模板面向「1000 用户规模、无线 802.1X + 记账入库」的典型企业场景(4GB 内存、普通 SSD 完全够用;FreeRADIUS 本身极轻量,单机处理每秒数百次认证无压力)。逐段给出最小改动集:

# /etc/freeradius/radiusd.conf —— 仅列需要改动的键
security {
	require_message_authenticator = yes   # 保持 3.2 默认,Blast-RADIUS 防护
	reject_delay = 1                      # 保持默认,抗在线爆破
}
log {
	auth = yes                            # 排障期开启;稳定后改回 no
	auth_badpass = yes                    # 记录失败尝试(不含密码),便于告警联动
}
# /etc/freeradius/clients.conf —— 每类接入设备一段,密钥 22 字符以上
client wifi-controllers {
	ipaddr    = 10.20.0.0/22
	secret    = <22+位强密钥,用 radsecret 生成>
	shortname = wlc-hq
	nastype   = other
}
# mods-enabled/sql —— 用户入库,files 只留应急账号
sql {
	dialect = "mysql"
	server = "10.20.1.50"
	login = "radius"
	password = <数据库强口令>
	radius_db = "radius"
	# mysql 段的 tls{} 块:不用数据库 TLS 就整段注释,避免实例化失败
}
# mods-enabled/eap —— 生产 Wi-Fi 用 PEAP
eap {
	default_eap_type = peap
	peap {
		default_eap_type = mschapv2
	}
	tls-config tls-common {
		private_key_file = /etc/freeradius/certs/server.pem   # 换成正式证书
		certificate_file = /etc/freeradius/certs/server.pem
		ca_file = /etc/freeradius/certs/ca.pem
	}
}

配置清单之外的两条纪律:① 每次改动先 freeradius -C 再 systemctl restart freeradius,异常时用 freeradius -X 看解析报错;② 上线前用 radtest(PAP/EAP-MD5)与真实 NAS 各回归一轮,命令见 《FreeRADIUS 3.2.10 常用 CLI 命令与工具详解》。

七、常见问题

Q1:改了配置重启后没生效? 先确认改的是 mods-enabled/ 下的软链目标还是 mods-available/ 里的源文件——只有 mods-enabled 里被链接(或显式 $INCLUDE)的文件才参与运行。用 freeradius -X 启动头部的 including configuration file ... 清单核对文件是否真的被加载。

Q2:freeradius -C 报错但看不到错误内容? deb 默认 log { destination = files },-C 的解析错误不落控制台。两种办法:临时 freeradius -X 启动(实测会打印 Errors reading or parsing /etc/freeradius/radiusd.conf 指明文件);或临时把 destination 改成 stdout。退出码本身就可靠:0 合法、1 有错。

Q3:radtest 提示 No reply,但网络明明通? 密钥不一致。服务端默认静默丢弃(客户端无响应),但 radius.log 会记录 Dropping packet without response because of error: ... invalid Message-Authenticator! (Shared secret is incorrect.)(实测原文)。核对 clients.conf 的 secret 与 NAS 侧配置,注意行尾空格与转义。

Q4:sql 模块起来后认证全走不了? 按三步定位:① freeradius -X 看模块实例化是否报错(典型:mysql 段 tls{} 引用的证书文件不存在);② -X 下发一次 radtest,看 sql: 行的真实查询与返回(User not found in radcheck table 说明库通但没数据);③ 核对 radcheck 表数据格式:username 与请求的 User-Name 一致、attribute = Cleartext-Password、op = :=。

Q5:EAP-MD5 测试时 radtest 报 "EAP packet is too short"? 实测现象:3.2.10 的 radtest 对 EAP-MD5 的最后一跳(EAP Success 封在 Access-Accept 里)解码报 failed decoding EAP: EAP packet is too short,随后打印 EAP transaction finished, but reply does not contain EAP-Code = Success 并以非零码退出——但服务端确实发出了 Access-Accept(报文里 EAP-Message=0x03b10004 即 Success),认证本身是成功的。这是 radtest 客户端侧解码的表现问题,判定结果以服务端 -X 日志为准。

Q6:升级 3.0 → 3.2 后有哪些默认值差异会咬人? 安全段 require_message_authenticator/limit_proxy_state 的默认收紧(旧 NAS 若不发 Message-Authenticator 会被丢包,需升级 NAS 固件或显式评估);mods-available/sql 的 mysql 段新增默认展开的 tls{} 块;部分模块(如 eap)默认段结构有调整。迁移后全量跑一遍 -C + radtest 回归。

八、参考链接