Linux 在指定端口上对每个 IP 进行限速
本文记录使用 iptables 和 tc 对本机指定端口进行限速。可以限制每个 IP 的速率。
IP限速
#!/bin/bash
INTERFACE="eth0" # 替换为你的实际网卡名称
TOTAL_BANDWIDTH="6400KBps" # 总带宽参数 (单位 KB/s)
RATE="256KBps" # 每个IP的限速 (单位 KB/s)
CEIL="384KBps" # 允许的最大速率 (单位 KB/s) 可以理解为 RATE + BURST
# BURST="256Kbit" # 允许的突发速率 (单位 Kbps)
# 清除规则
sudo tc qdisc del dev $INTERFACE root 2>/dev/null
# 添加根队列规则
sudo tc qdisc add dev $INTERFACE root handle 1: htb default 30
# 创建主类,限制总带宽
sudo tc class add dev $INTERFACE parent 1: classid 1:1 htb rate $TOTAL_BANDWIDTH
# 创建子类,限制每个IP的带宽
sudo tc class add dev $INTERFACE parent 1:1 classid 1:10 htb rate $RATE ceil $CEIL # burst $BURST
# 对所有 IP 应用规则
sudo tc filter add dev $INTERFACE protocol ip parent 1:0 prio 1 u32 match ip dst 0.0.0.0/0 flowid 1:10
端口限制
#!/bin/bash
INTERFACE="eth0" # 替换为你的实际网卡名称
PORT="443" # 替换为你的实际端口
MARK="10" # 替换为你的实际标记
INTERFACE="eth0" # 替换为你的实际网卡名称
TOTAL_BANDWIDTH="6400KBps" # 总带宽参数 (单位 KB/s)
RATE="256KBps" # 每个IP的限速 (单位 KB/s)
CEIL="384KBps" # 允许的最大速率 (单位 KB/s) 可以理解为 RATE + BURST
# BURST="256Kbit" # 允许的突发速率 (单位 Kbps)
# 检查并安装必要的软件包
if ! command -v tc &> /dev/null; then
echo "tc 命令未找到,请安装 iproute2 包。"
exit 1
fi
if ! command -v iptables &> /dev/null; then
echo "iptables 命令未找到,请安装 iptables 包。"
exit 1
fi
# 清除已有的队列规则
sudo tc qdisc del dev $INTERFACE root 2>/dev/null
# 添加根队列规则
sudo tc qdisc add dev $INTERFACE root handle 1: htb default 30
if [ $? -ne 0 ]; then
echo "添加根队列规则失败"
exit 1
fi
# 创建主类,限制总带宽
sudo tc class add dev $INTERFACE parent 1: classid 1:1 htb rate $TOTAL_BANDWIDTH
if [ $? -ne 0 ]; then
echo "创建主类失败"
exit 1
fi
# 创建子类,限制每个IP的带宽
sudo tc class add dev $INTERFACE parent 1:1 classid 1:10 htb rate $RATE ceil $CEIL # burst $BURST
if [ $? -ne 0 ]; then
echo "创建子类失败"
exit 1
fi
# 使用 iptables 将入方向流量标记为特定标记值($MARK)
sudo iptables -t mangle -A PREROUTING -i $INTERFACE -p tcp --dport $PORT -j MARK --set-mark $MARK
sudo iptables -t mangle -A PREROUTING -i $INTERFACE -p udp --dport $PORT -j MARK --set-mark $MARK
if [ $? -ne 0 ]; then
echo "添加入方向 iptables 规则失败"
exit 1
fi
# 使用 iptables 将出方向流量标记为特定标记值($MARK)
sudo iptables -t mangle -A OUTPUT -o $INTERFACE -p tcp --sport $PORT -j MARK --set-mark $MARK
sudo iptables -t mangle -A OUTPUT -o $INTERFACE -p udp --sport $PORT -j MARK --set-mark $MARK
if [ $? -ne 0 ]; then
echo "添加出方向 iptables 规则失败"
exit 1
fi
# 将带有特定标记值的流量应用到子类规则
sudo tc filter add dev $INTERFACE protocol ip parent 1:0 prio 1 handle $MARK fw flowid 1:10
if [ $? -ne 0 ]; then
echo "添加 tc 过滤器失败"
exit 1
fi
echo "端口 $PORT 上的流量已限速为 $RATE,最高速率为 $CEIL,总带宽为 $TOTAL_BANDWIDTH"
后续如果要添加端口限制为同样的速率,只需要 iptables 标记为相同的数值即可。
清除限制
#!/bin/bash
INTERFACE="eth0" # 替换为你的实际网卡名称
# 检查并安装必要的软件包
if ! command -v tc &> /dev/null; then
echo "tc 命令未找到,请安装 iproute2 包。"
exit 1
fi
# 清除已有的队列规则
sudo tc qdisc del dev $INTERFACE root 2>/dev/null
if [ $? -eq 0 ]; then
echo "已清除之前的所有带宽限制"
else
echo "无需清除,未发现之前的带宽限制"
fi
# 清除 iptables 规则
sudo iptables -t mangle -F
echo "已清除之前的所有 iptables 规则"
多端口限制
GPT3.5 写的,没有测试,自行判断是否使用。
#!/bin/bash
INTERFACE="eth0" # 替换为你的实际网卡名称
TOTAL_BANDWIDTH="6400KBps" # 总带宽参数 (单位 KB/s)
# 定义端口和相应的限速参数
declare -A PORT_LIMITS
PORT_LIMITS=(
[443]="256KBps:384KBps:128KBps:256KBps" # 入方向速率:入方向最大速率:出方向速率:出方向最大速率
[80]="128KBps:256KBps:64KBps:128KBps" # 以此类推
)
# 检查并安装必要的软件包
if ! command -v tc &> /dev/null; then
echo "tc 命令未找到,请安装 iproute2 包。"
exit 1
fi
if ! command -v iptables &> /dev/null; then
echo "iptables 命令未找到,请安装 iptables 包。"
exit 1
fi
# 清除已有的队列规则
sudo tc qdisc del dev $INTERFACE root 2>/dev/null
# 添加入方向根队列规则
sudo tc qdisc add dev $INTERFACE root handle 1: htb default 30
if [ $? -ne 0 ]; then
echo "添加入方向根队列规则失败"
exit 1
fi
# 添加出方向根队列规则
sudo tc qdisc add dev $INTERFACE handle ffff: ingress
if [ $? -ne 0 ]; then
echo "添加出方向根队列规则失败"
exit 1
fi
# 添加端口规则
for PORT in "${!PORT_LIMITS[@]}"
do
LIMITS=(${PORT_LIMITS[$PORT]})
IN_RATE=${LIMITS[0]}
IN_CEIL=${LIMITS[1]}
OUT_RATE=${LIMITS[2]}
OUT_CEIL=${LIMITS[3]}
MARK=$(($PORT + 10000)) # 使用不同的标记值区分不同端口的流量
# 添加入方向主类,限制总带宽
sudo tc class add dev $INTERFACE parent 1: classid 1:$PORT htb rate $TOTAL_BANDWIDTH
if [ $? -ne 0 ]; then
echo "创建入方向主类失败"
exit 1
fi
# 添加入方向子类,限制每个IP的入方向带宽
sudo tc class add dev $INTERFACE parent 1:$PORT classid 1:$((PORT * 10)) htb rate $IN_RATE ceil $IN_CEIL
if [ $? -ne 0 ]; then
echo "创建入方向子类失败"
exit 1
fi
# 添加出方向主类,限制总带宽
sudo tc class add dev $INTERFACE parent ffff: classid ffff:$PORT htb rate $TOTAL_BANDWIDTH
if [ $? -ne 0 ]; then
echo "创建出方向主类失败"
exit 1
fi
# 添加出方向子类,限制每个IP的出方向带宽
sudo tc class add dev $INTERFACE parent ffff:$PORT classid ffff:$((PORT * 10)) htb rate $OUT_RATE ceil $OUT_CEIL
if [ $? -ne 0 ]; then
echo "创建出方向子类失败"
exit 1
fi
# 使用 iptables 将入方向流量标记为特定标记值
sudo iptables -t mangle -A PREROUTING -i $INTERFACE -p tcp --dport $PORT -j MARK --set-mark $MARK
sudo iptables -t mangle -A PREROUTING -i $INTERFACE -p udp --dport $PORT -j MARK --set-mark $MARK
if [ $? -ne 0 ]; then
echo "添加入方向 iptables 规则失败"
exit 1
fi
# 使用 iptables 将出方向流量标记为特定标记值
sudo iptables -t mangle -A OUTPUT -o $INTERFACE -p tcp --sport $PORT -j MARK --set-mark $MARK
sudo iptables -t mangle -A OUTPUT -o $INTERFACE -p udp --sport $PORT -j MARK --set-mark $MARK
if [ $? -ne 0 ]; then
echo "添加出方向 iptables 规则失败"
exit 1
fi
# 将带有特定标记值的入方向流量应用到入方向子类规则
sudo tc filter add dev $INTERFACE protocol ip parent 1:0 prio 1 handle $MARK fw flowid 1:$((PORT * 10))
if [ $? -ne 0 ]; then
echo "添加入方向 tc 过滤器失败"
exit 1
fi
# 将带有特定标记值的出方向流量应用到出方向子类规则
sudo tc filter add dev $INTERFACE protocol ip parent ffff: prio 1 handle $MARK fw flowid ffff:$((PORT * 10))
if [ $? -ne 0 ]; then
echo "添加出方向 tc 过滤器失败"
exit 1
fi
echo "端口 $PORT 上的入方向流量已限速为 $IN_RATE,最高速率为 $IN_CEIL;出方向流量已限速为 $OUT_RATE,最高速率为 $OUT_CEIL;总带宽为 $TOTAL_BANDWIDTH"
done
出入方向合并版本
#!/bin/bash
INTERFACE="eth0" # 替换为你的实际网卡名称
TOTAL_BANDWIDTH="6400KBps" # 总带宽参数 (单位 KB/s)
# 定义端口和相应的限速参数
declare -A PORT_LIMITS
PORT_LIMITS=(
[443]="256KBps:384KBps" # 入方向速率:入方向最大速率
[80]="128KBps:256KBps" # 以此类推
)
# 检查并安装必要的软件包
if ! command -v tc &> /dev/null; then
echo "tc 命令未找到,请安装 iproute2 包。"
exit 1
fi
if ! command -v iptables &> /dev/null; then
echo "iptables 命令未找到,请安装 iptables 包。"
exit 1
fi
# 清除已有的队列规则
sudo tc qdisc del dev $INTERFACE root 2>/dev/null
# 添加根队列规则
sudo tc qdisc add dev $INTERFACE root handle 1: htb default 30
if [ $? -ne 0 ]; then
echo "添加根队列规则失败"
exit 1
fi
# 添加端口规则
for PORT in "${!PORT_LIMITS[@]}"
do
LIMITS=(${PORT_LIMITS[$PORT]})
RATE=${LIMITS[0]}
CEIL=${LIMITS[1]}
MARK=$(($PORT + 10000)) # 使用不同的标记值区分不同端口的流量
# 添加主类,限制总带宽
sudo tc class add dev $INTERFACE parent 1: classid 1:$PORT htb rate $TOTAL_BANDWIDTH
if [ $? -ne 0 ]; then
echo "创建主类失败"
exit 1
fi
# 添加子类,限制每个IP的带宽
sudo tc class add dev $INTERFACE parent 1:$PORT classid 1:$((PORT * 10)) htb rate $RATE ceil $CEIL
if [ $? -ne 0 ]; then
echo "创建子类失败"
exit 1
fi
# 使用 iptables 将流量标记为特定标记值
sudo iptables -t mangle -A PREROUTING -i $INTERFACE -p tcp --dport $PORT -j MARK --set-mark $MARK
sudo iptables -t mangle -A PREROUTING -i $INTERFACE -p udp --dport $PORT -j MARK --set-mark $MARK
sudo iptables -t mangle -A OUTPUT -o $INTERFACE -p tcp --sport $PORT -j MARK --set-mark $MARK
sudo iptables -t mangle -A OUTPUT -o $INTERFACE -p udp --sport $PORT -j MARK --set-mark $MARK
if [ $? -ne 0 ]; then
echo "添加 iptables 规则失败"
exit 1
fi
# 将带有特定标记值的流量应用到子类规则
sudo tc filter add dev $INTERFACE protocol ip parent 1:0 prio 1 handle $MARK fw flowid 1:$((PORT * 10))
if [ $? -ne 0 ]; then
echo "添加 tc 过滤器失败"
exit 1
fi
echo "端口 $PORT 上的流量已限速为 $RATE,最高速率为 $CEIL,总带宽为 $TOTAL_BANDWIDTH"
done
ubunt16 的版本,对于单个端口,比如 9000 端口限制后,其上传下载速度没有作用,也没有报错,这个是什么原因
@zhong 这个方法限制出方向速度应该是没问题的,如果要限制入方向速度要配合ifb使用