iptablesとnftablesで25万ルール詰め込む場合の話
Posted on 2018/07/10(Tue) 23:45 in technical
さまり
iptablesはAPIが古い設計なので、フィルタルールの追加時には全データをユーザランドにコピーして、再ストアする動きをする。
そのため、ルール数が多くなるとフィルタルールの追加に時間がかかるようになる。
対して、Linuxの次期標準ファイアウォールアプリケーションとして開発されているnftablesはその点が解消されており、フィルタルールの追加が高速に行われるようになっている。
今日は25万個のルールを詰め込んでみて、その差を体感してみようと思う。
環境
環境には、仮想マシンに入れたUbuntu 18.04を準備した。おおよそ以下の通り。
# cat /etc/os-release NAME="Ubuntu" VERSION="18.04 LTS (Bionic Beaver)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 18.04 LTS" VERSION_ID="18.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=bionic UBUNTU_CODENAME=bionic # uname -a Linux kanade 4.15.0-23-generic #25-Ubuntu SMP Wed May 23 18:02:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux # iptables -V iptables v1.6.1
また、nftablesを実行する環境は、上記から以下の変更を加えたものになる。
# apt update # apt install -y nftables iptables-nftables-compat # apt purge -y iptables # nft -v nftables v0.8.2 (Joe Btfsplk)
測定方法
適当なコマンドをペタペタ貼り付けたファイルを用意して、これを実行した。
基本的にはiptablesとnftablesでほぼ互換の設定をしているはず。
要点は、以下の通り。
- 全部で25万個のルールがINPUTチェインに追加される
- サンプル点は50回に1回の5000点
iptables
#!/bin/bash
RUN_LOG="iptables_rule250k.log"
APPEND_LOG="iptables_rule250k_append.log"
INSERT_LOG="iptables_rule250k_insert.log"
echo "#user,system,elapsed" > ${APPEND_LOG}
echo "#user,system,elapsed" > ${INSERT_LOG}
iptables -F INPUT
iptables -L INPUT > ${RUN_LOG}
for dport in $(seq 60001 65000)
do
for sport in $(seq 50001 50049)
do
iptables -A INPUT -p tcp --sport ${sport} --dport ${dport} -j DROP
done
/usr/bin/time -f "%U,%S,%E" iptables -A INPUT -p tcp --sport 50050 --dport ${dport} -j DROP &>> ${APPEND_LOG}
done
iptables -L INPUT | wc -l >> ${RUN_LOG}
iptables -F INPUT
iptables -L INPUT >> ${RUN_LOG}
for dport in $(seq 60001 65000)
do
for sport in $(seq 50001 50049)
do
iptables -I INPUT 1 -p tcp --sport ${sport} --dport ${dport} -j DROP
done
/usr/bin/time -f "%U,%S,%E" iptables -I INPUT 1 -p tcp --sport 50050 --dport ${dport} -j DROP &>> ${INSERT_LOG}
done
iptables -L INPUT | wc -l >> ${RUN_LOG}
iptables -F INPUT
iptables -L INPUT >> ${RUN_LOG}
nftables
#!/bin/bash
RUN_LOG="nftables_rule250k.log"
APPEND_LOG="nftables_rule250k_append.log"
INSERT_LOG="nftables_rule250k_insert.log"
echo "#user,system,elapsed" > ${APPEND_LOG}
echo "#user,system,elapsed" > ${INSERT_LOG}
nft flush chain inet filter input
nft list ruleset > ${RUN_LOG}
for dport in $(seq 60001 65000)
do
for sport in $(seq 50001 50049)
do
nft add rule inet filter input tcp sport ${sport} tcp dport ${dport} counter drop
done
/usr/bin/time -f "%U,%S,%E" nft add rule inet filter input tcp sport 50050 tcp dport ${dport} counter drop &>> ${APPEND_LOG}
done
nft list ruleset | wc -l >> ${RUN_LOG}
nft flush chain inet filter input
nft list ruleset >> ${RUN_LOG}
for dport in $(seq 60001 65000)
do
for sport in $(seq 50001 50049)
do
nft insert rule inet filter input tcp sport ${sport} tcp dport ${dport} counter drop
done
/usr/bin/time -f "%U,%S,%E" nft add rule inet filter input tcp sport 50050 tcp dport ${dport} counter drop &>> ${INSERT_LOG}
done
nft list ruleset | wc -l >> ${RUN_LOG}
nft flush chain inet filter input
nft list ruleset >> ${RUN_LOG}
結果
結果のグラフは以下のようになった。(点線はExcelによる近似曲線)
とりあえずiptablesは設計通りの単調増加。nftablesはその点が解消されて常に一定で設定速度も十分高速。
終わり
iptablesがルール数の増大によって設定時間が増加するということを知っていないと、 iptablesでは大量のフィルタルールを設定するケースで、想定していない設定エラーなどに遭遇するかもしれない。
nftablesに切り替えればいいというのは事実かもしれないけど、既にiptablesが前提になっているOpenStackとかDockerなんかもいたりするので、上手に付き合っていけるように特性を踏まえておくと良いと思います。