マルチポートモジュールは、iptables
複数の個別ルールに比べてパフォーマンス上の利点を提供しますか?つまり、これは次のようになります。
iptables -A INPUT -p tcp -m multiport --sports 1,2,3,4,5,6,7,8,9,10,11,12,13,14,80 -j ACCEPT
..これよりも効率的です。
iptables -A INPUT -p tcp --sport 1 -j ACCEPT
iptables -A INPUT -p tcp --sport 2 -j ACCEPT
iptables -A INPUT -p tcp --sport 3 -j ACCEPT
iptables -A INPUT -p tcp --sport 4 -j ACCEPT
iptables -A INPUT -p tcp --sport 5 -j ACCEPT
iptables -A INPUT -p tcp --sport 6 -j ACCEPT
iptables -A INPUT -p tcp --sport 7 -j ACCEPT
iptables -A INPUT -p tcp --sport 8 -j ACCEPT
iptables -A INPUT -p tcp --sport 9 -j ACCEPT
iptables -A INPUT -p tcp --sport 10 -j ACCEPT
iptables -A INPUT -p tcp --sport 11 -j ACCEPT
iptables -A INPUT -p tcp --sport 12 -j ACCEPT
iptables -A INPUT -p tcp --sport 13 -j ACCEPT
iptables -A INPUT -p tcp --sport 14 -j ACCEPT
iptables -A INPUT -p tcp --sport 80 -j ACCEPT
最初のケースでは、各パッケージをチェックし、tcp
モジュールmultiport
もチェックしますが、ルールは1つだけです。 2番目のケースでは、パッケージごとに15のルールを調べますが、各ルールごとにtcp
モジュールのみを処理します。
次のように単純なネットワークトポロジを作成しました。
server1[eth2] <--> [enp0s31f6]server2
eth2
入出力はすべて1GigEネットワークアダプタserver1
で、5m Cat5eケーブルで接続されています。ファイアウォールルールなしで10000MiBファイルをダウンロードした場合、スループットは942Mbpsでした。次に、次の4369のルールを作成しました。enp0s31f6
server2
server1
server2
for i in {1..65535}; do if ((i%15 == 0)); then iptables -A INPUT -p tcp -m multiport --sports $p$i -j ACCEPT; p=; else p=$p$i,; fi; done
multiport
これは、それぞれ15のポートを持つ4,369のルールがあることを意味します。たとえば、
# iptables -L INPUT 1 -v -n --line-numbers
1 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
# iptables -L INPUT 4369 -v -n --line-numbers
4369 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport sports 65521,65522,65523,65524,65525,65526,65527,65528,65529,65530,65531,65532,65533,65534,65535
#
wget --report-speed=bits -4 -O /dev/null 10.10.10.1:65535
今で実行すると、server2
驚くべきことに、スループットはまだ942Mbpsです。次に、INPUT
チェーンを更新し、次のように65535のルールを作成しました。
for i in {1..65535}; do iptables -A INPUT -p tcp --sport $i -j ACCEPT; done
wget --report-speed=bits -4 -O /dev/null 10.10.10.1:65535
再実行したところ、server2
スループットが580Mbpsに低下しました。では、極端なケースでは、このmultiport
方法がより効果的でしょうか?しかし、何万ものルールや数十Gbpsのトラフィックがない一般的な状況では、実質的な違いはありませんか?
答え1
iptables は、終了ターゲットに一致するエントリが見つかるまでテーブル内の各ルールを繰り返すため、ルールが少ないほど CPU 使用率が低くなります。一部のルールは他のルールよりも高速に実行されます。マルチポート15ポートルールは、同等のポートルールよりも速くすることができます。置くルール(例:Hauke Laging回答)。したがって、ルールの数だけでなく、ルールの種類も重要です。
ソースコードはTCP/UDP、マルチポートそして置くマッチング拡張はいくつかの経験則を提供しますが、進行速度がどこまで遅くなるかを予測するのは難しい。、可能なiptablesルールセットをベンチマークして、どちらが速いかを確認することをお勧めします。たとえば、私はiperf33つのポートのみを含むリスト伝送制御プロトコルモジュール比マルチポートそして置く同様のスループットを提供するモジュールです。
それでもマイクロベンチマークに興味がある場合は、このプログラムを実行するのに必要なCPUサイクルを計算してみました。ipt_do_table
非常に基本的なカーネル関数を使うシステムクリックスクリプト:
global call_cycles = 0
probe kernel.function("ipt_do_table@net/ipv4/netfilter/ip_tables.c").call {
call_cycles = get_cycles()
}
probe kernel.function("ipt_do_table@net/ipv4/netfilter/ip_tables.c").return {
delta = get_cycles() - call_cycles
printf(" <- delta = %d\n", delta)
}
Linux 4.15を実行している仮想マシンですべてのルールのパケットを繰り返す結果は次のとおりです。
基準寸法 | ポート | ルール | 1 実行 | ラン2 | 実行3 | 実行4 | 実行5 |
---|---|---|---|---|---|---|---|
伝送制御プロトコル | 4500 | 4500 | 973148 | 1032564 | 856528 | 410894 | 854708 |
マルチポート | 4500 | 300 | 89370 | 259250 | 99752 | 225275 | 182256 |
置く | 4500 | 1 | 28463 | 43494 | 28315 | 33589 | 40988 |
答え2
LinuxがopcodeレベルでNetfilterルールをどのように処理するのかわかりません。ただし、マルチポートアプローチでは、1回の操作で複数のチェックを実行できます。
1Gb/sはCPUにあまり多くないので(遅いCPUでも)極端な場合が必要なのは驚くべきことではありません。ただし、どちらの方法でも、同じスループットでも全く異なる負荷を生成できます。これはカーネルなので、おそらく機能しません/proc/loadavg
。したがって、同じシステムでCPU集約型アプリケーションを実行し、パフォーマンスを測定して実際の違いを確認する必要があります。
-p tcp
しかし、マルチポートは一度チェックしますが、マルチルールは同じチェックを65536回実行するため、比較が少し不公平だと思います。だからあなたはこれを行います:
iptables -N tcp_ports
iptables -A INPUT -p tcp -j tcp_ports
for ((i=1;i<65536;i++)); do iptables -A tcp_ports --sport $i ...
私はTCPチェックをそのまま無視できないことに気づきました--dport
。しかし、これがマルチルールアプローチが遅い理由の1つです。
あなたと同じ状況でマルチポーティングが機能しているかどうかはわかりません。ipset
巨大な比較リストが作成されました。だからこれはあなたが本当に欲しいものかもしれません。
ipset create foo bitmap:port range tcp:10000-19999
ipset add foo tcp:10000-19999
iptables -A INPUT -p tcp -m set --match-set foo dst