こんにちは、ぐっちゃんです。
RHEL7では firewalld の下で iptables が動作していましたが、RHEL8以降ではデフォルトで nftables へ変更になりました。しかし、書店やサーバ構築手順書を読んでも nftables について説明をしている記事や本が見当たらない…
そこで、今回は nftables の仕様とルールの見え方について調査してみました。
まとめ
- nftables は Firewalldのバックエンド(RHEL7以前は iptables)
- ゾーンに対して設定するルールでは、inet firewalldテーブル内のチェーンに記述される
- ダイレクトルールの設定は、ip filterテーブルに記述される
- 設定のないゾーンについては、nftablesのルールに出力されない。
nftables とは
nftables は Firewalldのバックエンド(Firewalldの下)で動いているものです。これは /etc/firewalld/firewalld.confに設定されています。
[root@localhost] # awk ‘!/^#|^$/’ /etc/firewalld/firewalld.conf
:
FirewallBackend=nftables ★
なお、FirewallBackendパラメータを iptables に変更してリロードすれば、従来通りの iptables でのパケット処理となります。
nftables のルールの見え方
デフォルトの nftables のルールを nft.org というファイルに書き出し、ルール追加する毎に diffコマンドで差分を確認します。
[root@localhost ~]# firewall-cmd –list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp0s3
sources:
services: cockpit dhcpv6-client ssh
ports:
:
[root@localhost ~]# nft list ruleset > nft.org
ポート開放(例:80番を開ける時)
[root@localhost ~]# firewall-cmd –add-port=80/tcp
[root@localhost ~]# nft list ruleset > nftaddport80
◆差分確認
[root@localhost ~]# diff nft.org nftaddport80
> tcp dport 80 ct state { new, untracked } accept
このルールの追加箇所は、inet firewalldテーブルの filter_IN_public_allowチェーンでした。なお、ポート追加でなく、サービス名(http)の追加でも同じ結果が得られます。
[root@localhost ~]# nft list ruleset |less
table inet firewalld {
:
chain filter_IN_public_allow {
tcp dport 22 ct state { new, untracked } accept
ip6 daddr fe80::/64 udp dport 546 ct state { new, untracked } accept
tcp dport 9090 ct state { new, untracked } accept
tcp dport 80 ct state { new, untracked } accept ★
}
direct rule 設定(例:25番を優先度0で開ける時)
[root@localhost ~]# firewall-cmd –direct –add-rule ipv4 filter INPUT 0 -p tcp –dport 25 -j ACCEPT
[root@localhost ~]# nft list ruleset > nftadddirect
◆差分確認
[root@localhost ~]# diff nft.org nftadddirect
> meta l4proto tcp tcp dport 25 counter packets 0 bytes 0 accept
ダイレクトルールに設定されたルールの場所を確認すると、ip filterテーブルに記述されます。inet firewalldテーブルに記述されないことから、ダイレクトルールはゾーンに対して設定しないことがわかります。
[root@localhost ~]# nft list ruleset |less
table ip filter {
chain FORWARD {
type filter hook forward priority filter; policy accept;
}
chain INPUT {
type filter hook input priority filter; policy accept;
meta l4proto tcp tcp dport 25 counter packets 0 bytes 0 accept ★
}
}
table inet firewalld {
:
独自ゾーン追加(例:testzoneを追加する)
[root@localhost ~]# firewall-cmd –permanent –new-zone=testzone
[root@localhost ~]# firewall-cmd –reload
[root@localhost ~]# nft list ruleset > nftaddnewzone
◆差分確認
[root@localhost ~]# diff nft.org nftaddnewzone
[root@localhost ~]# ★変化なし
ゾーンを追加しただけでは何も差分が得られません。思えば、internal や external 等他のゾーンもありませんね。インタフェースを割り当ててみると testzone に関するチェーンが作成されます。
◆インタフェース ens0s3 を testzone に割り当てて再度確認
[root@localhost ~]# firewall-cmd –permanent –zone=testzone –change-interface=ens0s3
[root@localhost ~]# firewall-cmd –reload
[root@localhost ~]# nft list ruleset > nfttestzone
[root@localhost ~]# diff nft.org nfttestzone
:
chain filter_IN_testzone {
jump filter_INPUT_POLICIES_pre
jump filter_IN_testzone_pre
jump filter_IN_testzone_log
jump filter_IN_testzone_deny
jump filter_IN_testzone_allow
:
}
:
rich rule によるログ出力(例:80番ポートに通信が来た際、”80test”と出力する)
[root@localhost ~]# firewall-cmd –add-rich-rule=’rule family=”ipv4″ port port=80 protocol=tcp log prefix=”80test” level=info’
[root@localhost ~]# nft list ruleset > nftlogrule
◆差分確認
[root@localhost ~]# diff nft.org nftlogrule
meta nfproto ipv4 tcp dport 80 ct state { new, untracked } log prefix “80test” level info
このルールの追加箇所を見てみると inet firewalld テーブルの filter_IN_public_log チェーンでした。ログ出力の設定は、ポートやサービスの許可と違い、自動的にチェーンに割り当てられるようです。
[root@localhost ~]# nft list ruleset
:
table inet firewalld {
:
chain filter_IN_public_log { ★
meta nfproto ipv4 tcp dport 80 ct state { new, untracked } log prefix “80test” level info
}
}
コメント