校园网络毕业设计实战:从零构建高可用校园网认证与流量管理系统
一、为什么“画拓扑”救不了毕设
每年 3 月,学院机房的毕设展板都会准时出现一批“校园网规划”海报:三层交换机画得像披萨,防火墙图标比键盘还大,配文“采用最新安全技术”。问一句“802.1X 的 EAP 类型选什么”,多半会卡壳。
真实校园网最在意的三件事,恰好是毕设最容易翻车的三点:
- 安全性:纯门户认证(Web Portal)+ 静态口令,抓个包就能重放,后台还没审计日志。
- 可扩展性:把用户表硬编码在 MySQL 单表,并发上千时 SELECT 锁等待直接拖死。
- 协议合规:交换机已经支持 802.1X,可毕设却用私有 Socket 模拟,验收时现场换品牌就全崩。
想拿优秀,就得把“能跑”升级成“能扛”。下面记录我如何用 6 周时间,把一套可上生产的“认证 + 流量可视化”系统搬进毕业设计。
二、认证协议选型:RADIUS vs OAuth2.0
| 维度 | RADIUS | OAuth2.0 | |---|---|---|---| | 传输层 | UDP/1812,轻量 | TCP/443,握手重 | | 标准 802.1X 支持 | 原生 | 无,需额外 Portal | | 会话状态 | 无,靠 NAS 维护 | 有,access_token | | 防重放 | 内置 Request Authenticator | 需二次加密 | | 代码量 | 直接调库 | 自写 Challenge |
结论:交换机已经走 802.1X,RADIUS 是事实标准;OAuth2.0 更适合 Web SSO。
最终方案:
- 认证引擎:FreeRADIUS 3.2(EAP-TLS/PEAP 全支持)
- 业务逻辑:Python Flask 微服务,通过 rlm_python 插件把授权信息抛给后台
- 用户门户:仍保留 OAuth2.0 做自服务改密,与 RADIUS 账号系统单向同步
三、核心模块拆解
1. EAP-TLS 认证流程(证书双向校验)
- 客户端发送 EAPoL-Start
- 交换机返回 Identity Request
- 客户端回 Identity,携带匿名用户名
@campus.local - FreeRADIUS 返回 EAP-TLS/Start,附带服务器证书
- 客户端校验服务器证书 → 发送客户端证书 + 私钥签名
- FreeRADIUS 调用
rlm_python把 CN(学号)抛给 Flask - Flask 查询 Redis 白名单 → 返回 Accept
- 交换机收到 RADIUS Accept,VLAN 下发完成
关键代码(Flask 端授权钩子):
# authorize.py : 被 rlm_python 回调 import redis, os, json r = redis.Redis(host='127.0.0.1', port=6379, decode_responses=True) def authorize(args): """ args 格式:{'User-Name': '20211234', 'TLS-Client-Cert-CN': '20211234', ...} """ cn = args.get('TLS-Client-Cert-CN') if not cn: return (None, False) # 拒绝 # 白名单 + 账号状态 if r.exists(f"user:{cn}") and r.hget(f"user:{cn}", "status") == "active": return ({'Tunnel-Private-Group-Id': r.hget(f"user:{cn}", "vlan"), 'Session-Timeout': 86400}, True) return (None, False)Clean Code 要点:
- 函数纯逻辑,不直接操作 DB
- 返回元组,方便 FreeRADIUS 侧解包
- 所有魔法字串提到模块常量,方便单元测试 mock
2. Redis 在线用户状态管理
RADIUS 本身无会话,需要自建“在线表”。
设计:
- Key:
online:{NAS-IP}:{Acct-Session-Id} - TTL: 与 Acct-Interim-Interval 对齐(默认 300 s)
- 字段:
username,vlan,ingress,egress,ip,calling-station-id
Flask 暴露/api/online给前端实时查询,O(1) 复杂度。
下线感知:
- 正常:Accounting-Stop 到来即删 Key
- 异常:TTL 过期 + 交换机端口 Down 事件双重确认,避免“幽灵会话”
3. sFlow 探针数据采集
校园网出口交换机已支持 sFlow,采样比 1:2048。
采集端用sflowtool+Python asyncio改写,直接解析 JSON。
关键字段:
srcIP,dstIP,srcPort,dstPort,proto,inBytes,outBytes
逻辑:
- 收到 sFlow 包 → 按五元组聚合 1 min 窗口
- 写 InfluxDB 2.x,measurement=flow,tag=srcIP
- Grafana 模板变量联动:点击在线用户 → 自动填充 IP → 展示实时速率
四、压测与数据
工具:radperf+tcpreplay重放 802.1X 握手
硬件:i5-8400 / 8 G / Intel I350-T4
结果:
- 并发认证:3200 次/秒,CPU 65 %
- 平均延迟:18 ms(含 TLS 双向校验)
- 失败率:0.04 %(主要由客户端证书链不完整导致)
瓶颈:
- 单核 OpenSSL 验签 → 开
openssl speed ecdsa确认 P-256 可跑 9 k ops/s,足够 - UDP 丢包:Linux 默认
net.core.rmem_default小,调大到 8 M 后消失
五、安全加固清单
- 防重放:FreeRADIUS 3.x 自带
replay-window,同时启用require-message-authenticator - 证书吊销:CRL 周期 1 h,另加 OCSP Stapling,防止学生丢私钥
- 日志脱敏:
- 把
Calling-Station-Id(MAC)后 24 bit 掩 0 - 用户名写入前哈希,保留学号前缀以供排障
- 把
- Redis 公网隔离:绑定 unix socket,关闭
bind 0.0.0.0 - Flask 仅监听 127.0.0.1,外部通过 Nginx + Client Cert 反向代理
六、生产环境避坑指南
- 证书管理陷阱
- 不要把 CA 私钥放 GitLab!用 cfssl 多级证书,Root 离线存 U 盘
- 交换机只认 DER,而 Windows 客户端要 P12,脚本化一键
openssl pkcs12 -export
- 交换机镜像端口误区
- 采样口=镜像口?错!sFlow 由 ASIC 复制,不占镜像资源;若误把镜像目的口当上行,会直接环路
- 冷启动会话恢复
- 交换机重启后端口默认授权 VLAN 1,需把
aaa authorization network default group radius写进startup-config - Redis 数据易失,Flask 启动时主动发
CoA-Request查询交换机当前会话,重建在线表
- 交换机重启后端口默认授权 VLAN 1,需把
七、留给下一届的思考:无厂商 QoS,如何限速?
目前系统只采集,不控制。要在不绑定华为/华三 CLI 的前提下做带宽 QoS,可考虑:
- 用Linux TC+OpenFlow把用户 VLAN 引流到中央软路由,Flask 根据套餐动态
tc class change - 或让交换机支持OpenFlow 1.3+,控制器下推 Flow-Mod,匹配
srcIP+input port后 set-queue
两条路都要求“可编程”硬件,预算有限时,先用 TC 在 Linux 网关侧限速,毕业答辩足够炫。
写完这篇,我的体会是:毕设不是写 PPT,而是把“能跑起来的脚本”熬成“敢让老师拔掉电源再重启”的系统。当你真把 3000 个账号、3 台交换机、1 条 10 G 出口塞进 8 G 内存的小主机,还能在 Grafana 上看到自己的实时流量,那种成就感比任何“优秀”印章都香。祝你也能把实验室的灯熬成校园网的光。