スクリプトブローは、iptablesを使用してINPUT
パケットをマークする場合、ポート2000の着信レートを制限しようとしますが、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
私は以下のリンクをリストすることによってこの質問に答えようとします:
トラフィックシェーピングには、INGRESSとEGRESSの2つのモードがあります。 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
jinzhengが言ったことは正しいです、あなたは入口のトラフィックを形作ることができません。しかし、あなたはキャプテンジャックスパロウのようにそれをすることができます...事実を変えてください。
「redirect-gateway」を使用してホストとvpsの間にopenvpn接続を作成し、すべてのトラフィックがvpsを通過するようにします。次のようになります:ホームネットワーク/ PC->インターネット-> vps->インターネット
ホームネットワークのINGRESSはvpsのEGRESSであり、vpsの発信インターフェイスを形成します。
いくつかのヒント:ホームネットワーク/ IPを指定することを忘れないでください。そうしないと、vpsアップロードレートが無効になります。 vpsは、ホームネットワークよりも優れた帯域幅を備えている必要があります。帯域幅を測定してください。ドイツでは、hetzner.deから7€vpsを取得できます。かなり信頼性があります。
それを行う必要はありません。カーネルとiptablesにパッチを適用するだけで、着信トラフィックを形成できます。+ LXCを使用している場合は、KVMだけでパッチを適用する必要もありません。