Thanks to visit codestin.com
Credit goes to github.com

Skip to content

alfiy/OpenVPNClient-TC-shell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenVPN Client Tc 限流脚本介绍

这个脚本是一个用于 OpenVPN 环境的 流量控制守护进程,旨在动态管理连接用户的网络带宽。它通过周期性解析状态日志来识别在线用户,并利用 Linux 的 Traffic Control (tc) 工具和 HTB 队列规则为每个客户端分配特定的限速策略。脚本支持通过配置文件定义 用户或角色的个性化上下行带宽,并结合 IFB 设备 实现对双向流量的精准拦截。为了确保系统的健壮性,它具备幂等性初始化 和状态自动恢复功能,能在服务重启后自动重建内存中的 IP 映射关系。通过这种全自动的监控与执行机制,管理员可以高效地实现虚拟私有网络内的 按需带宽分配。

限速原理:

上传限速:直接对 tun0 的出口流量(dst_ip 匹配客户端)设置 HTB 规则。 下载限速:通过 ifb0 虚拟网卡,把 tun0 的入口流量重定向到 ifb0 出口,再对 ifb0 的出口流量(src_ip 匹配客户端)设置 HTB 规则。 幂等性设计:所有 tc 规则的创建 / 删除都先检查是否存在,避免重复操作报错,保证脚本可重复启动。 动态性:每 3 秒检测一次客户端状态,自动为新客户端创建限速规则,为离线客户端清理规则,支持用户 / 角色级别的差异化带宽配置。

核心文件 / 配置

status.log:OpenVPN 状态日志,是客户端状态的数据源。 tc-users.conf:用户 / 角色的带宽配置(格式:用户名/角色名=上传带宽 下载带宽)。 tc-roles.map:用户 - 角色映射(格式:用户名=角色名)。 tun0/ifb0:核心网卡,分别用于上传 / 下载限速。

运行依赖

内核需加载 ifb 模块(modprobe ifb)。 系统需安装 iproute2(提供 tc/ip 命令)。 OpenVPN 需开启 status 日志(配置文件中加 status /var/log/openvpn/status.log)。

该脚本如何通过自动化手段动态管理 OpenVPN 客户端的网络带宽限制?

该脚本通过结合 Linux 的 流量控制工具 (Traffic Control, TC)、中继设备 (IFB) 以及对 OpenVPN 状态日志的实时监控,实现了对客户端带宽的动态自动化管理。其核心逻辑可以归纳为以下几个关键维度:

  1. 流量控制基础设施的初始化 在脚本启动时,init_tc 函数负责构建限速所需的网络环境: • 流量重定向: 由于 Linux TC 在处理输入(Ingress)流量时功能有限,脚本加载了 ifb 模块并创建 ifb0 设备。它将 VPN 设备 (tun0) 的所有入站流量重定向到 ifb0 的出站方向,从而实现对下载带宽的控制。 • 分级令牌桶 (HTB) 队列: 在 tun0 和 ifb0 上分别建立 HTB 队列规则 (qdisc)。这种分级结构允许脚本为每个客户端创建独立的子类(Class),并为其分配特定的带宽上限。
  2. 动态监测与身份识别 脚本通过一个无限循环(每 3 秒执行一次)来跟踪客户端的变化: • 状态解析: parse_clients 函数读取 OpenVPN 的 status.log 文件,通过解析“ROUTING TABLE”部分,提取当前在线客户端的 IP 地址和用户名。 • 配置检索: get_user_rate 函数会根据用户名动态查找限速策略。它首先检查用户特定的配置文件 (tc-users.conf),如果没有,则查找角色映射 (tc-roles.map);若均未找到,则应用默认的 2Mbit 带宽限制。
  3. 客户端生命周期的自动化管理 脚本通过维护内存中的映射表 (IP_CLASS_MAP),自动处理客户端的上线与下线: • 自动分配与限速 (Add Client): 当检测到新 IP 连接时,add_client 会从预设池(101-350)中分配一个唯一的 ClassID。随后,它执行 tc class add 创建带宽限额,并使用 tc filter add(基于 flower 过滤器和 IP 地址)将特定客户端的流量关联到该限额类上。 • 自动清理 (Del Client): 当某个客户端不再出现在 status.log 中时,脚本会调用 del_client 自动删除对应的 TC 过滤器和类别,并释放该 ClassID 供后续使用,确保系统资源不被浪费。
  4. 健壮性与状态恢复 为了确保自动化过程的可靠性,脚本具备以下特性: • 状态重建: 如果脚本重启,rebuild_state 函数会扫描内核中已存在的 TC 规则,并结合 status.log 重新构建内存中的 IP 与 ClassID 映射,避免与正在运行的连接冲突。 • 幂等性操作: 在执行创建操作前,脚本会通过 class_exists 和 filter_exists 检查规则是否已存在,防止重复添加导致的错误。 • 用户变更检测: 如果同一 IP 对应的用户名发生变化,脚本会先删除旧规则并按新用户的权限重新创建限速策略。

脚本采用了哪些关键机制来确保流量控制规则的初始化与状态恢复?

该脚本通过一套完整的初始化流程、内核状态扫描机制以及幂等性检查,确保了流量控制规则在启动和运行过程中的稳定性与一致性。以下是其采用的关键机制:

  1. 流量控制(TC)规则的标准化初始化 在 init_tc 函数中,脚本执行了一系列步骤来构建限速基础环境: • 依赖与设备检查: 脚本首先验证 tc、ip 和 modprobe 命令是否存在,并尝试加载 ifb 内核模块。 • 延迟等待机制: 考虑到 OpenVPN 启动时设备创建可能滞后,脚本会循环等待最多 30 秒,直到 tun0 设备在系统中出现。 • 强制清理残留: 为了确保环境干净,脚本会先删除 tun0 上的根队列和输入队列,并彻底删除并重建 ifb0 设备,以消除之前运行可能留下的失效规则。 • 分级架构建立: 在 tun0(控制上传)和 ifb0(控制下载)上分别建立 HTB(分级令牌桶) 根队列,并配置默认类和流量重定向过滤器。
  2. 深度内核状态恢复(Rebuild State) 为了在脚本重启后不干扰已有的连接并找回管理状态,rebuild_state 函数实现了以下功能: • 实时内核扫描: 脚本通过解析 tc filter show 命令的输出,从内核中反向提取已存在的过滤规则。 • 双向数据提取: 扫描 tun0 上的 dst_ip(目标 IP)和 ifb0 上的 src_ip(源 IP),并准确捕获它们对应的 flowid(即 ClassID)。 • 用户关系同步: 脚本会读取 OpenVPN 的 status.log 文件,将提取到的 IP 地址与当前的用户名进行关联,从而重新构建内存中的 IP_CLASS_MAP 映射表。 • 资源占用标记: 恢复过程中,已发现的 ClassID 会被标记在 CLASSID_USED 数组中,防止新连接分配到正在使用的 ClassID。
  3. 操作的幂等性与健壮性 脚本在执行增删操作时采用了“先检查、后操作”的策略,以确保系统的稳健: • 存在性校验: 通过 class_exists、filter_exists_dst 和 filter_exists_src 等辅助函数,在添加规则前先确认该规则是否已存在于内核中,避免重复创建导致报错。 • 错误重试逻辑: 在主循环启动时,如果 init_tc 初始化失败,脚本支持最多 5 次重试,每次间隔 5 秒,以应对临时的系统资源竞争或网络设备未就绪的情况。 • 静默处理: 在删除规则(del_client)时,脚本会忽略不存在的项,确保在客户端频繁上下线或系统抖动时不会触发不必要的错误日志。

如何为特定用户在配置文件中设置自定义带宽限额?

根据脚本的设计逻辑,您可以通过编辑两个主要的配置文件来为特定用户设置自定义带宽限额。该脚本支持直接针对用户名设置以及基于角色(Role)批量设置两种方式。 具体操作方法如下:

  1. 配置文件路径与格式 脚本在初始化部分定义了相关的配置文件路径: • 用户限速配置: /etc/openvpn/tc-users.conf • 用户角色映射: /etc/openvpn/tc-roles.map
  2. 方法一:直接为特定用户设置 您可以直接在 /etc/openvpn/tc-users.conf 文件中按照 用户名=上传带宽 下载带宽 的格式进行定义。 • 操作步骤: 打开 /etc/openvpn/tc-users.conf,添加类似以下内容: • 脚本逻辑: get_user_rate 函数会优先检索该文件。如果匹配到当前登录的用户名,将直接提取对应的上传和下载速率。
  3. 方法二:通过角色(Role)进行关联设置 如果您有大量用户需要应用相同的限速策略,可以使用角色映射功能。这需要同时操作两个文件:
  4. 定义角色限速: 在 /etc/openvpn/tc-users.conf 中定义角色的带宽。
  5. 建立用户与角色的映射: 在 /etc/openvpn/tc-roles.map 中将用户名指向特定角色。 • 脚本逻辑: 如果在 tc-users.conf 中找不到直接对应的用户名,脚本会去 tc-roles.map 查找该用户所属的角色,再根据角色名回到 tc-users.conf 获取限速值。
  6. 默认限速说明 如果上述两个文件中都没有找到对应的配置,脚本将应用预设的默认限速: • 默认上传: 2Mbit • 默认下载: 2Mbit 注意事项 • 带宽单位: 设置时应使用 Linux TC 支持的单位,如 Mbit、Kbit、bps 等。 • 格式要求: 每一行必须严格遵循 key=value 的格式,中间不要有空格,因为脚本使用的是 cut -d= -f2 来解析数据。 • 生效时间: 脚本的主循环每 3 秒检查一次 status.log。对于新上线的用户,配置会立即生效;对于已在线的用户,若检测到用户名发生变更,脚本会自动重建其对应的流量控制类(Class)以应用新策略。

脚本中设置的 101 到 350 个 ClassID 限制了最大并发用户数吗?

是的,该脚本中设置的 101 到 350 个 ClassID 确实限制了脚本能够同时动态管理带宽的最大并发用户数。 具体分析如下:

  1. 并发用户数的计算 根据脚本中的基本配置,CLASSID_START 设置为 101,而 CLASSID_END 设置为 350。这意味着脚本预留了一个包含 250个 唯一标识符(ClassID)的资源池(350−101+1=250)。
  2. ClassID 与用户的对应关系 • 唯一性分配: 在 add_client 逻辑中,每当有一个新 IP 的客户端上线时,脚本都会调用 alloc_classid 函数从该池子中分配一个尚未被占用的 ClassID。 • 一对一绑定: 这个 ClassID 会被同时用于 tun0(上传)和 ifb0(下载)的流量控制类(Class),并与该用户的 IP 地址绑定。 • 内存记录: 分配成功的 ClassID 会被记录在 CLASSID_USED 数组和 IP_CLASS_MAP 映射表中。
  3. 达到上限后的表现 当池子中的 250 个 ID 全部被占用且没有用户下线释放 ID 时: • alloc_classid 函数在遍历完 101 到 350 的所有数值后,会因为找不到空闲 ID 而返回错误。 • 脚本会输出日志错误:“❌ classid 池已耗尽”。 • 对于超出第 250 名之后的并发用户,脚本将无法为其创建限速规则(放弃执行 add_client 逻辑),这些用户可能会不受限速控制或遵循系统的默认队列规则。
  4. 资源的回收与复用 该限制仅针对同时在线的用户数。当客户端下线时,脚本通过 del_client 过程调用 free_classid,将该 ID 从 CLASSID_USED 中移除,从而使其能够被后续上线的其他用户重新利用。 总结: 该脚本目前最大支持 250 个并发用户 的带宽管理。如果您的 OpenVPN 服务器需要支持更多同时在线的用户,需要手动修改脚本开头的 CLASSID_END 参数以扩大资源池。

创建systemd服务

将vpn-tc-daemon.service文件保存在/etc/systemd/system目录下,然后执行以下命令:

systemctl daemon-reload
systemctl enable vpn-tc-daemon.service
systemctl start vpn-tc-daemon.service

About

openvpn client 限速脚本开发

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages