插件常问问题
1️⃣ 项目难点
流量线程 会根据 虚拟地址 高频查询客户端信息,但客户端断连时 pcc 会从 在线上下文 里移除。如果流量线程直接依赖 pccMap,就会面临 pcc 生命周期不稳定的问题。
所以我没有让 流量线程 直接访问 pcc,而是专门维护了一个 virtual_address_map,把流量线程需要的字段提前从 pcc 中抽出来,按 virtual_address -> Json 的形式保存。这样流量线程只读 轻量级映射,不依赖 pcc 本身,从而规避了断连场景下访问失效上下文的问题,同时也减少了重复组装 JSON 的开销。
2️⃣ 项目优化
请求链路优化
根据场景不同,将 证书校验、用户规则下载、连接状态上报 进行拆分:
证书校验: 走 **同步fast_fail**(服务器不可访问则立即返回),因为证书校验在主链路上,必须立即返回;用户访问规则下载: 走 **异步gRPC**,基于用户的 完成队列 (Completion Queue) 提前下载用户规则,同时避免阻塞OpenVPN主流程;连接状态上报: 走 **异步gRPC**,基于全局的 **完成队列 (Completion Queue)**,避免阻塞OpenVPN主流程;
规则下发和更新优化
- 访问控制不是每次 全量重建,而是按用户维度生成独立
nftables chain; - 通过
map把 虚拟地址 跳到 用户规则链; - 新增、删除、更新某个用户时只改这个用户对应的链,开销更小;
- 服务端规则变化时,也不是轮询,而是通过
gRPC双向流推送,插件收到后做增量更新;
稳定性和一致性优化
对不同 RPC 设置了不同的 超时 和 失败 策略
- 证书校验: 使用
fail-fast; - 状态上报: 使用
wait-for-ready; - 双向推送流: 使用
指数退避重连; - 定时全量状态同步: 每
3分钟把当前在线用户状态重新上报一次,避免长连接抖动或偶发失败后服务端状态漂移。
并发优化
项目里维护了 在线用户 和 虚拟地址 的映射,我把访问模式拆开了
- 流量线程查看用户信息 是 高频读:所以用了
shared_mutex; - 新增/删除用户 是 高频写:所以用了
unique_lock;
3️⃣ 做这些优化的出发点是什么?
OpenVPN插件在认证接入阶段不能被远程服务拖住;- 防火墙规则更新不能每次全量重建;
- 控制面消息不能只靠一次事件成功,必须考虑断连、丢消息和状态漂移;
4️⃣ 项目模块问题
1️⃣ 你项目里 PcapPlusPlus 干了什么
OpenVPN 插件里封装了一个 tcap 模块,在插件启动后根据 OpenVPN 提供的网卡名 dev 打开对应设备,注册抓包回调,实时捕获经过 VPN 网卡的流量。拿到原始包之后,我会用 PcapPlusPlus 做协议层解析,解析到网络层、传输层,配置允许的话还能继续到应用层,比如 DNS、HTTP、SSL。然后把解析出的字段连同节点信息、服务器信息、时间戳、VPN 用户信息一起组织成 JSON,最后发送到 Kafka,供后续审计和流量分析使用。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 GYu的妙妙屋!
