资讯动态

CentOS下FreeRADIUS+daloradius+OpenPortal认证计费与限速实战

发布时间:2026/10/13 23:26:41 来源:尧图企业网站定制
1. 为什么这套组合方案至今仍有人在用先把场景说清楚。你手上有一台 CentOS 服务器需要给一批用户提供统一的网络接入认证同时还要对每个用户的带宽做限制——不是简单的限速而是按用户、按组、按时间段灵活控制。这种需求在园区网、酒店、小型运营商、实验室环境里非常常见。FreeRADIUS 负责认证、授权、计费这三件事daloradius 是架在它上面的 Web 管理界面OpenPortal 则负责把认证页面和用户交互这一层补齐。三者拼在一起就是一套完整的认证管理门户方案。这套组合不是最新的技术栈但它的稳定性经过了大量实际环境的验证配置逻辑清晰出了问题也容易定位。我之所以还愿意花时间整理这套流程是因为网上能找到的资料要么太老、要么缺关键步骤、要么在流量控制这块一笔带过。实际配下来你会发现真正卡人的不是 FreeRADIUS 本身而是 daloradius 和数据库的对接细节以及限速策略到底该挂在哪一层。这篇文章会把整个链路拆开讲包括每一步为什么这么做、参数怎么算、哪里容易翻车。适合读这篇的人有 Linux 基础、需要搭建一套可控的认证计费系统、并且对流量控制有实际要求的人。纯小白建议先把 CentOS 的基本操作和 MySQL 的增删改查过一遍再来看。2. 环境准备与组件职责的重新梳理2.1 三个组件到底谁管什么很多人配这套东西的时候容易混乱是因为没搞清楚三个组件的边界。我用一句话概括FreeRADIUS 是干活的daloradius 是管账的OpenPortal 是迎客的。FreeRADIUS 是核心守护进程监听认证请求查数据库验证身份返回授权属性同时记录计费信息。它不关心界面好不好看只关心规则对不对。daloradius 是一套 PHP 写的 Web 应用它直接读写 FreeRADIUS 用的那套数据库表。你在界面上添加用户、设置组、查看在线记录本质上都是在操作 MySQL 里的表。它不参与认证过程只是把数据库操作可视化了。OpenPortal 负责的是用户接入时的门户页面——用户连上网络后被重定向到一个登录页输入账号密码提交给 RADIUS 认证。它解决的是用户怎么把凭据交上来这个问题。理解了这个分工后面配置的时候你就知道每一步该去哪个组件的配置文件里找。2.2 CentOS 基础环境的关键选择系统版本上CentOS 7 和 CentOS 8 的包管理差异比较大。CentOS 7 用 yumCentOS 8 转向了 dnf而且默认的软件源里 FreeRADIUS 版本也不同。我建议用 CentOS 7 的较新小版本原因是 daloradius 对 PHP 版本有要求CentOS 7 默认的 PHP 5.4 太老需要额外装 remi 源升级到 PHP 7.x这个组合验证得最充分。关闭 SELinux 这件事我要单独说。很多人上来就setenforce 0但重启后又回来了。正确做法是改配置文件sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config setenforce 0为什么必须关因为 FreeRADIUS 要写日志到非标准目录、daloradius 要读写数据库套接字、OpenPortal 要监听特定端口SELinux 的默认策略会把这些全挡掉。你也可以花时间写自定义策略但在搭建阶段关掉它能让排查问题的复杂度降低一个数量级。防火墙方面需要放行的端口包括RADIUS 认证端口 1812/udp、计费端口 1813/udp、Web 管理界面的 80/tcp、数据库的 3306/tcp如果数据库不在本机。用 firewalld 的话firewall-cmd --permanent --add-port1812/udp firewall-cmd --permanent --add-port1813/udp firewall-cmd --permanent --add-servicehttp firewall-cmd --reload注意1812 和 1813 是 UDP 端口不是 TCP。我见过有人只开了 TCP然后死活认证不通查了半天才发现协议搞错了。2.3 数据库选型与初始化MySQL 还是 MariaDB在 CentOS 7 上默认源里的 MariaDB 5.5 就够用daloradius 的建表语句对这两个都兼容。我倾向于用 MariaDB因为它在 CentOS 上的包依赖更干净。安装完成后要做几件事设置 root 密码、删除匿名用户、禁止 root 远程登录。这些是基本安全操作不展开。重点是要创建一个专用的数据库用户给 daloradius 和 FreeRADIUS 用不要直接用 root。CREATE DATABASE radius; GRANT ALL ON radius.* TO radiuslocalhost IDENTIFIED BY 你的强密码; FLUSH PRIVILEGES;这里有个细节FreeRADIUS 连接数据库的方式有两种一种是通过rlm_sql模块直接用 MySQL 客户端库另一种是通过 Unix socket。用 localhost 走 socket 性能更好但要注意 MySQL 的 socket 路径要和 FreeRADIUS 配置里写的一致。CentOS 上通常是/var/lib/mysql/mysql.sock。3. FreeRADIUS 的安装与核心配置拆解3.1 安装与目录结构认知yum install -y freeradius freeradius-mysql freeradius-utils装完之后先别急着改配置花两分钟把目录结构看清楚。/etc/raddb/是配置根目录里面几个关键文件radiusd.conf是主配置clients.conf定义哪些客户端可以来认证users是本地用户文件sites-available/default是虚拟主机配置mods-available/sql是数据库模块配置。/var/log/radius/是日志目录radius.log记录启动和认证信息radacct/下面按日期存放计费明细。调试的时候这两个地方是主要的信息来源。3.2 让 FreeRADIUS 认识数据库默认安装的 FreeRADIUS 用的是文件认证我们要把它切到数据库认证。第一步是启用 sql 模块ln -s /etc/raddb/mods-available/sql /etc/raddb/mods-enabled/sql然后编辑/etc/raddb/mods-available/sql找到sql {这一段修改以下关键项driver rlm_sql_mysql dialect mysql server localhost port 3306 login radius password 你的强密码 radius_db radius再往下找到read_clients yes这一行把注释去掉。这个选项让 FreeRADIUS 从数据库的nas表读取客户端定义而不是从clients.conf读。用 daloradius 管理的时候这个必须开否则你在界面上添加的 NAS 设备不生效。还有一个容易漏的地方acct_table1、acct_table2、postauth_table这些表名要和 daloradius 建的表名一致。daloradius 默认建的表就是radacct、radpostauth这些所以一般不用改但如果你手动改过表名这里必须同步。3.3 虚拟主机配置里必须改的三处编辑/etc/raddb/sites-available/default这个文件决定了认证请求怎么处理。找到authorize {段确保里面有sql这一行而且它在files之前。顺序很重要先查数据库数据库里没有再去查本地文件。找到accounting {段同样确保sql在里面。计费数据要写进数据库这一行不能少。找到session {段把sql加进去。这个段负责同时在线数控制如果你要做一个账号只能同时在线一台设备就靠这里。改完之后建立软链接到 sites-enabledln -s /etc/raddb/sites-available/default /etc/raddb/sites-enabled/default3.4 用 radtest 验证认证链路在动 daloradius 之前先用命令行工具确认 FreeRADIUS 本身是通的。启动服务systemctl start radiusd systemctl enable radiusd然后用 radtest 测试。但前提是数据库里得有个测试用户。手动插一条INSERT INTO radcheck (username, attribute, op, value) VALUES (testuser, Cleartext-Password, :, testpass);然后radtest testuser testpass localhost 0 testing123testing123是clients.conf里 localhost 客户端的默认密钥。如果返回Access-Accept说明认证链路通了。如果返回Access-Reject去看/var/log/radius/radius.log里面会写清楚是数据库连不上还是密码不匹配。这一步非常关键。我见过太多人跳过这步直接配 daloradius结果界面能登录、能加用户但认证就是不通最后排查发现是 FreeRADIUS 根本没连上数据库。先把底层打通上层的问题才好定位。4. daloradius 部署中的版本陷阱与数据库对接4.1 版本选择与 PHP 环境daloradius 的版本更新不算频繁但不同版本对 PHP 的要求差异很大。较新的版本需要 PHP 7.0 以上而 CentOS 7 默认是 PHP 5.4。你需要先装 remi 源yum install -y epel-release yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm yum install -y yum-utils yum-config-manager --enable remi-php74 yum install -y php php-mysql php-gd php-common php-mbstring php-cli装完之后php -v确认版本。这里有个坑如果你之前装过 PHP 5.4 的相关包升级后 Apache 可能还在加载旧的模块。最稳妥的做法是重启 httpd 服务并且检查/etc/httpd/conf.d/php.conf是否指向了新的模块路径。4.2 导入数据库结构的正确姿势daloradius 的安装包里有个contrib/db/mysql-daloradius.sql文件这是建表语句。但直接导入经常会报错原因是字符集问题。先确认数据库的默认字符集SHOW VARIABLES LIKE character_set_database;如果是latin1导入中文用户信息会乱码。建议在创建数据库时就指定CREATE DATABASE radius CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;然后导入mysql -u radius -p radius mysql-daloradius.sql导入完成后用SHOW TABLES;确认表都建好了。应该能看到radacct、radcheck、radgroupcheck、radusergroup、nas、operators等表。其中operators表存的是 daloradius 的管理员账号默认会有一条 admin 记录密码是加密的首次登录后要改掉。4.3 Web 界面配置文件的几个关键项把 daloradius 的代码放到 Web 目录下比如/var/www/html/daloradius。然后编辑library/daloradius.conf.php这是核心配置文件。需要改的项$configValues[CONFIG_DB_HOST] localhost; $configValues[CONFIG_DB_PORT] 3306; $configValues[CONFIG_DB_USER] radius; $configValues[CONFIG_DB_PASS] 你的强密码; $configValues[CONFIG_DB_NAME] radius;还有一个容易被忽略的项CONFIG_MAINTENANCE_LOAD。这个如果设成 1界面会进入维护模式什么都点不了。确保它是 0。另外daloradius 需要写日志到某个目录默认是/var/log/daloradius/。这个目录要手动创建并给 Apache 用户写权限mkdir -p /var/log/daloradius chown apache:apache /var/log/daloradius4.4 登录后第一件该做的事用默认管理员登录后不要急着加用户。先去Configuration菜单里检查几个设置RADIUS Settings里的RADIUS Server地址要填 FreeRADIUS 所在机器的 IPRADIUS Secret要和clients.conf里对应客户端的密钥一致。这个密钥是 daloradius 在界面上执行某些操作比如断开用户连接时用的填错了那些功能会静默失败。然后去Management里添加一个 NAS。NAS 就是网络接入设备可以是交换机、无线控制器、或者任何支持 RADIUS 的设备。添加时填 IP 地址和共享密钥这个密钥要和设备上配置的一致。添加完 NAS 之后FreeRADIUS 才能接受来自这个设备的认证请求。5. OpenPortal 的角色与认证页面集成5.1 OpenPortal 解决的是什么问题FreeRADIUS 和 daloradius 配好之后认证是能用了但用户怎么触发认证如果是 802.1X 环境客户端会自动弹出认证框。但如果是 Web 认证环境——比如酒店、商场、园区的访客网络——用户连上 WiFi 后需要打开一个网页输入账号密码这个网页就是 OpenPortal 提供的。OpenPortal 本质上是一个轻量级的 Web 服务它监听特定端口接收来自网络设备的重定向请求展示登录页面然后把用户提交的凭据转发给 RADIUS 做认证。认证通过后它通知网络设备放行该用户的流量。5.2 部署与对接要点OpenPortal 的部署方式取决于你拿到的版本。如果是源码包解压后放到 Web 目录配置数据库连接指向同一个 radius 库。它需要读取radcheck表来验证用户也需要写radacct表来记录会话。关键配置项通常在一个config.php或类似文件里需要设置RADIUS 服务器地址、共享密钥、数据库连接信息、以及监听端口。监听端口默认可能是 8080 之类的要确保防火墙放行。对接的时候有一个细节OpenPortal 提交认证请求的方式。有的版本是直接调用radtest命令有的是通过 PHP 的 RADIUS 扩展。如果是前者要确保 Web 用户有执行radtest的权限如果是后者要装php-radius扩展。这个扩展在 remi 源里有装完之后要重启 httpd。5.3 认证流程的完整链路用户连上网络设备把 HTTP 请求重定向到 OpenPortal 的登录页。用户输入账号密码OpenPortal 把凭据发给 FreeRADIUS。FreeRADIUS 查数据库验证通过后返回Access-Accept同时带上授权属性——这些属性里就包含了限速策略。OpenPortal 收到成功响应后通知网络设备放行用户开始上网。计费方面网络设备会在会话开始时发Accounting-Start结束时发Accounting-Stop中间定期发Interim-Update。FreeRADIUS 把这些都写进radacct表daloradius 从表里读出来展示在线用户和流量统计。6. 流量控制的三种实现路径与参数计算6.1 限速到底该在哪一层做这是整套方案里最核心也最容易搞混的部分。流量控制可以在三个层面实现RADIUS 属性下发、网络设备本地策略、以及服务器端限速。三者的适用场景完全不同。RADIUS 属性下发是最灵活的方式。你在数据库里给用户或用户组设置特定的属性FreeRADIUS 在认证响应里把这些属性发给网络设备设备根据属性值来限速。这种方式的好处是集中管理改数据库就生效不用登录每台设备。缺点是依赖设备支持相应的属性。网络设备本地策略是在交换机或控制器上直接配限速规则RADIUS 只负责认证。这种方式简单直接但用户多了之后管理成本高。服务器端限速是在 FreeRADIUS 所在的服务器上用 tc 或 iptables 做限速。这种方式适合服务器本身就是网关的场景但如果只是做认证服务器流量不经过它就限不了。绝大多数场景下你应该用第一种——RADIUS 属性下发。6.2 标准属性与厂商私有属性限速用的 RADIUS 属性分两类。标准属性是 RFC 定义的所有厂商都认但功能有限。最常用的是Filter-Id它是一个字符串具体含义由设备解释。有的设备把它当作限速策略的名称有的当作 ACL 名称。厂商私有属性功能更强但只在该厂商的设备上生效。比如某些厂商用WISPr-Bandwidth-Max-Down和WISPr-Bandwidth-Max-Up来分别控制上下行带宽单位是 bits per second。这两个属性在无线认证场景里用得很多。配置的时候在 daloradius 的radgroupreply表里给用户组添加属性。比如给普通用户组设置下行 2Mbps、上行 512KbpsINSERT INTO radgroupreply (groupname, attribute, op, value) VALUES (normal, WISPr-Bandwidth-Max-Down, :, 2097152); INSERT INTO radgroupreply (groupname, attribute, op, value) VALUES (normal, WISPr-Bandwidth-Max-Up, :, 524288);注意单位是 bps不是 Bps。2Mbps 是 2097152 bps不是 2097152 字节。这个换算错误我见过不止一次配完之后用户说网速不对一查发现单位搞错了。6.3 按用户、按组、按时段的差异化限速daloradius 支持用户组的概念。你可以建多个组每个组设不同的限速属性然后把用户分配到组里。用户会继承组的属性同时也可以有自己独有的属性。当用户属性和组属性冲突时用户属性优先。按时段限速稍微复杂一些。FreeRADIUS 本身不直接支持基于时间的属性下发但可以通过radcheck表里的Expiration属性来控制账号有效期或者用Login-Time属性来控制允许登录的时间段。如果要实现白天限速 1M、晚上限速 5M这种动态策略需要写自定义的 unlang 策略或者用外部脚本。一个可行的做法是在sites-available/default的post-auth段里加一段逻辑根据当前时间修改返回的属性。这需要一定的 unlang 编写能力但灵活性很高。6.4 限速不生效的排查思路配了限速但没效果按这个顺序查第一确认属性真的下发了。在 FreeRADIUS 调试模式下radiusd -X看认证响应的Reply-Message或属性列表确认限速属性在里面。第二确认设备认这个属性。不同厂商对属性的支持差异很大。查设备的文档看它支持哪些限速属性。如果不支持 WISPr 属性试试Filter-Id或者厂商自己的属性。第三确认属性值的单位。前面说了bps 和 Bps 差 8 倍。还有的设备用 kbps 而不是 bps值要相应调整。第四确认设备上的限速功能是开启的。有的设备默认不启用 RADIUS 下发的限速策略需要在全局配置里打开一个开关。7. 计费数据与在线用户监控的落地细节7.1 radacct 表的结构与关键字段radacct表是计费数据的核心。每次会话开始FreeRADIUS 插入一条记录acctstarttime记录开始时间acctstoptime为空表示会话进行中。会话结束时更新acctstoptime和acctsessiontime。中间的Interim-Update会更新acctinputoctets和acctoutputoctets这两个字段就是上下行流量字节数。acctsessionid是会话的唯一标识nasipaddress是设备 IPusername是用户名。这几个字段是查询在线用户和统计流量的关键。7.2 在线用户列表为什么有时不准daloradius 的在线用户页面读的是radacct表里acctstoptime IS NULL的记录。但实际环境中经常出现用户已经下线了但记录还在的情况。原因是设备没有发送Accounting-Stop包——可能是设备重启了、网络断了、或者配置有问题。解决办法有两个。一是在 FreeRADIUS 里配置interim_update的超时清理超过一定时间没有收到更新就把会话标记为结束。二是在 daloradius 里手动清理或者写个定时脚本定期清理超时的会话记录。UPDATE radacct SET acctstoptime NOW(), acctterminatecause Stale-Session WHERE acctstoptime IS NULL AND acctupdatetime DATE_SUB(NOW(), INTERVAL 1 HOUR);这个脚本可以放到 crontab 里每小时跑一次。7.3 流量统计的精度问题acctinputoctets和acctoutputoctets的精度取决于设备发送Interim-Update的频率。如果设备每 5 分钟发一次那流量统计的精度就是 5 分钟。如果设备只在会话结束时发一次那会话进行中就看不到流量。在设备上把interim-update的间隔设短一些比如 60 秒能提高精度但会增加数据库写入压力。这个需要根据用户规模和服务器性能来权衡。几百个用户的话60 秒间隔完全没问题上万用户的话要考虑分表或者用时序数据库。8. 几个真实踩过的坑与排查链路8.1 认证成功但用户上不了网这个问题的排查链路是这样的先看 FreeRADIUS 日志确认返回的是Access-Accept。如果是说明认证没问题问题在授权或设备侧。然后看返回的属性里有没有设备需要的授权属性。有的设备要求必须返回Tunnel-Type、Tunnel-Medium-Type、Tunnel-Private-Group-Id这一组属性才会放行缺一个都不行。再检查 NAS 的共享密钥。密钥不匹配的话设备会丢弃 RADIUS 响应表现就是认证超时。在 FreeRADIUS 日志里能看到Received packet from x.x.x.x with invalid signature这样的提示。最后检查设备的 ACL 或策略配置。RADIUS 只负责告诉设备这个用户通过了具体放行哪些流量、走哪个 VLAN还是设备自己决定的。8.2 daloradius 界面报数据库连接错误先确认daloradius.conf.php里的数据库信息对不对。然后确认 MySQL 用户有没有从 localhost 连接的权限。有时候用户建了但只给了%的权限localhost 反而连不上。还有一个隐蔽的问题PHP 的 MySQL 扩展。CentOS 7 上默认可能是mysqlnd但 daloradius 的某些版本用的是旧的mysql_connect函数这个函数在 PHP 7 里已经被移除了。如果报Call to undefined function mysql_connect()说明你用的 daloradius 版本太老需要升级到用mysqli或PDO的版本。8.3 计费数据重复写入有时候会发现同一个会话在radacct表里有两条记录。原因是设备发送了重复的Accounting-Start或者 FreeRADIUS 的acct_unique模块没启用。acct_unique模块会根据会话 ID、用户、NAS 等信息生成一个唯一键防止重复插入。在sites-available/default的preacct段里确保acct_unique被调用。8.4 限速属性下发但设备不执行前面提过先确认设备支持该属性。如果设备支持但就是不执行检查属性值的格式。有的设备要求Filter-Id的值必须是设备上已存在的策略名称不能随便填。这种情况下你需要在设备上先建好策略然后在 RADIUS 里下发策略名称。还有一个可能设备上的 RADIUS 授权功能没开。有的设备默认只做认证不做授权需要在配置里显式开启。9. 性能调优与日常维护的几点经验FreeRADIUS 的性能瓶颈通常在数据库查询上。如果用户量大可以开启rlm_sql的缓存功能把常用的查询结果缓存起来。在sql模块配置里找到query_timeout和read_groups这些选项根据实际情况调整。数据库方面radacct表会越来越大需要定期归档。可以按月分表或者把历史数据导出后删除。daloradius 本身没有自动归档功能需要自己写脚本。日志方面FreeRADIUS 的调试日志在radiusd -X模式下会输出到终端正常运行时写到/var/log/radius/radius.log。日志级别可以在radiusd.conf里调整生产环境建议用auth级别不要用debug否则日志量会非常大。备份方面最重要的是数据库。radius库里的radcheck、radgroupreply、nas、operators这几张表存的是配置数据丢了要重新配。radacct表存的是计费数据丢了影响对账。建议每天定时mysqldump保留最近 30 天。我在实际维护中发现这套系统最怕的不是配置复杂而是配完之后没人管。用户加了不删、组策略改了不测试、数据库满了不清理这些问题积累起来比初始配置的难度大得多。建议至少每个月检查一次在线用户列表和数据库大小每季度做一次全量备份恢复演练。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑