该脚本尝试限制端口 2000 的传入速率,当使用 iptables 标记INPUT
数据包时不起作用,但OUTPUT
可以正常工作。
我使用nc -kl 2000
这台机器10.0.1.54
和iperf -c 10.0.1.54 -p 2000 -t 10
另一台机器来测试它。
为什么OUTPUT
有效 但 无效 呢INPUT
?
dev=enp3s0
ip_addr=10.0.1.54
ip_port=2000
rate_limit=20kbit
htb_class=10
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
if [ "$1" = "enable" ]; then
echo "enabling rate limits"
tc qdisc del dev $dev root > /dev/null 2>&1
tc qdisc add dev $dev root handle 1: htb
tc class add dev $dev parent 1: classid 1:$htb_class htb rate $rate_limit ceil $rate_limit
tc filter add dev $dev parent 1: prio 0 protocol ip handle $htb_class fw flowid 1:$htb_class
# marking the INPUT chain does dot work as expected
#iptables -t mangle -A INPUT -d $ip_addr -p tcp --dport $ip_port -j MARK --set-mark $htb_class
# marking the OUTPUT chain works fine
iptables -t mangle -A OUTPUT -s $ip_addr -p tcp --sport $ip_port -j MARK --set-mark $htb_class
elif [ "$1" = "disable" ]; then
echo "disabling rate limits"
tc qdisc del dev $dev root > /dev/null 2>&1
#iptables -t mangle -D INPUT -d $ip_addr -p tcp --dport $ip_port -j MARK --set-mark $htb_class
iptables -t mangle -D OUTPUT -s $ip_addr -p tcp --sport $ip_port -j MARK --set-mark $htb_class
elif [ "$1" = "show" ]; then
tc qdisc show dev $dev
tc class show dev $dev
tc filter show dev $dev
iptables -t mangle -vnL INPUT
iptables -t mangle -vnL OUTPUT
else
echo "invalid arg $1"
fi
答案1
我尝试通过列出以下链接来回答这个问题:
流量整形有两种模式:INGRESS 和 EGRESS。INGRESS 处理传入流量,EGRESS 处理传出流量。Linux 不支持对 INGRESS 进行整形/排队,只支持监管。因此存在 IFB,我们可以将其附加到 INGRESS 队列,同时我们可以将任何常规排队(如 FQ_CODEL)添加为 IFB 设备上的 EGRESS 队列。[http://wiki.gentoo.org/wiki/Traffic_shaping]
所以,我对这个问题的解决方案是:
#!/bin/bash
dev=enp3s0
ifb_dev=ifb0
ip_addr=10.0.1.54
ip_port=2000
rate_limit=20kbit
htb_class=10
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
modprobe ifb
ifconfig ifb0 up
if [ "$1" = "enable" ]; then
echo "enabling rate limits"
tc qdisc add dev $dev handle ffff: ingress
tc filter add dev $dev parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $ifb_dev
tc qdisc add dev $ifb_dev root handle 1: htb
tc class add dev $ifb_dev parent 1: classid 1:$htb_class htb rate $rate_limit ceil $rate_limit
tc filter add dev $ifb_dev parent 1: protocol ip prio 1000 u32 match ip dport 2001 0xffff flowid 1:$htb_class
elif [ "$1" = "disable" ]; then
echo "disabling rate limits"
tc qdisc del dev $dev root > /dev/null 2>&1
tc qdisc del dev $dev ingress > /dev/null 2>&1
tc qdisc del dev $ifb_dev root > /dev/null 2>&1
tc qdisc del dev $ifb_dev ingress > /dev/null 2>&1
elif [ "$1" = "show" ]; then
tc qdisc show dev $dev
tc class show dev $dev
tc filter show dev $dev
else
echo "invalid arg $1"
fi
答案2
金正说得对,你无法控制入口流量。但你可以像杰克船长那样......改变事实。
使用“重定向网关”在您的主机和 vps 之间创建一个 openvpn 连接,以便所有流量都通过 vps。因此它看起来像这样:您的家庭网络/电脑 -> 互联网 -> vps -> 互联网
对于您的家庭网络来说,INGRESS 是 VPS 的 EGRESS,然后在 VPS 上塑造传出接口。
一些提示:请记住指定您的家庭网络/ip,否则您将杀死 vps 上传速率。vps 必须具有比您的家庭网络更好的带宽,测量带宽。在德国,您只需从 hetzner.de 购买 7 欧元的 vps,它们非常可靠。
答案3
没必要这么做,很简单,你只需要修补内核和 iptables,然后你就可以调整传入流量了,+ 如果你使用 LXC,那么你甚至不需要修补任何东西,只需在 KVM 上