web-dev-qa-db-ja.com

Linux:tcとiptablesを組み合わせて特定のポートレートを制限すると、期待どおりに機能しません

スクリプトブローは、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
1
tianchaijz

私は以下のリンクをリストすることによってこの質問に答えようとします:

トラフィックシェーピングには、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
2
tianchaijz

jinzhengが言ったことは正しいです、あなたは入口のトラフィックを形作ることができません。しかし、あなたはキャプテンジャックスパロウのようにそれをすることができます...事実を変えてください。

「redirect-gateway」を使用してホストとvpsの間にopenvpn接続を作成し、すべてのトラフィックがvpsを通過するようにします。次のようになります:ホームネットワーク/ PC->インターネット-> vps->インターネット

ホームネットワークのINGRESSはvpsのEGRESSであり、vpsの発信インターフェイスを形成します。

いくつかのヒント:ホームネットワーク/ IPを指定することを忘れないでください。そうしないと、vpsアップロードレートが無効になります。 vpsは、ホームネットワークよりも優れた帯域幅を備えている必要があります。帯域幅を測定してください。ドイツでは、hetzner.deから7€vpsを取得できます。かなり信頼性があります。

1
Julius Junghans

それを行う必要はありません。カーネルとiptablesにパッチを適用するだけで、着信トラフィックを形成できます。+ LXCを使用している場合は、KVMだけでパッチを適用する必要もありません。

0
martyns