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

本文链接:

https://blog.nkxingxh.top/archives/431/
1 + 8 =
快来做第一个评论的人吧~