Atsushi2022の日記

データエンジニアリングに関連する記事を投稿してます

iptablesの後継 nftables

nftablesはパケットフィルタリングツールで、iptablesip6tablesなどの後継。

簡単なユースケースではfirewalldを使用するが、複雑なケースやネットワーク全体に対する設定はnftablesを使用する。今後はiptablesの代わりに、nftablesの試用が推奨される。

設定構造

nftablesの設定全体のことをルールセットと呼ぶ。ルールセットには、アドレスファミリごとに設定されるテーブルがある。テーブルにはチェーンがあり、そこにルールが含まれる。

  • ルールセット
    • テーブル A
      • チェーン i
        • ルール 1
        • ルール 2
      • チェーン ii
        • ルール 1
        • ルール 2
    • テーブル B
      • チェーン i
        • ルール 1
        • ルール 2

テーブルは、アドレスファミリ(=プロトコル)毎にを作成する。

アドレスファミリの種類

アドレスファミリには次のような種類がある。

nftablesはdnf install nftablesでインストールできる(もちろんyum install nftables`でもよい)

# dnf install nftables
# systemctl start nftables
# dnf list installed | grep nftables
nftables.x86_64                      1:1.0.4-11.el9              @anaconda
# rpm -qa | grep nftables
nftables-1.0.4-11.el9.x86_64

nftablesnftコマンドで設定できる。アドレスファミリが「ip」である テーブル「table01」を作成する場合は、次のようなコマンドになる。

# nft create table ip table01 # アドレスファミリが「ip」のテーブル「table01」を作成
# nft list ruleset
table ip table01 {
}

さらにチェーンを作成する。(詳細は後述)

# nft create chain ip table01 chain01 { type filter hook input priority 1 \; policy accept \; } # チェーンの作成。タイプ「filter」、フック「input」、プライオリティ「1」、ポリシー「drop」を指定
# nft list ruleset
table ip table01 {
        chain chain01 {
                type filter hook input priority filter + 1; policy drop;
        }
}

チェーン内にルールを追加する。(詳細は後述)

# nft add rule ip table01 chain01 ip saddr 59.138.xxx.xxx accept
# nft -a list ruleset
table ip table01 { # handle 1
        chain chain01 { # handle 1
                type filter hook input priority filter + 1; policy accept;
                ip saddr 59.138.xxx.xxx accept # handle 2
        }
}

削除は次のような感じ。{ flags dormant \; }で作成したテーブルを無効化することもできる

# nft delete rule ip table01 chain01 handle 2
# nft -a list ruleset
table ip table01 { # handle 1
        chain chain01 { # handle 1
                type filter hook input priority filter + 1; policy accept;
        }
}
#
# nft delete chain ip table01 chain01 # チェーンの削除
# nft list ruleset
table ip table01 {
}
# nft add table ip table01 { flags dormant \; } # テーブルの無効化
# nft list ruleset
table ip table01 {
        flags dormant
}
# nft delete table ip table01 # テーブル削除
# nft list ruleset
#

テーブル

テーブルを作成するにはnft create table [アドレスファミリ] [テーブル名]とする。

チェーン

次にチェーンを作成するには、nft create chain [アドレスファミリ] [テーブル名] [チェーン名] { type [タイプ] hook [フック] priority [プライオリティ] ; policy [ポリシー] ; }とする。

タイプ

以下の3種類が存在する。

  • filter
    • フィルタリングに使用
  • nat
    • NATの実行に使用
    • ip、ip6のみ使用可能
  • route
    • パケットのルーティングに使用
    • ip、ip6のみ使用可能

フック

以下の6種類が存在する

  • prerouting
    • パケット受信時、かつルーティング前に実行
    • ip、ip6、inet、bridgeに対応
  • input
    • ローカルホスト向けのパケット受信時
    • ip、ip6、inet、bridge、arpに対応
  • forward
    • 転送される際に実行
    • ip、ip6、inet、bridgeに対応
  • output
    • ローカルプロセスがパケット生成時に実行
    • ip、ip6、inet、bridge、arpに対応
  • postrouting
    • パケット送信時に実行
    • ip、ip6、inet、bridgeに対応
  • ingress
    • パケット受信時に実行
    • netdevに対応

プライオリティ

  • チェーン毎の優先順位(=同じフックが指定されたチェーンが複数存在する場合にどのチェーンから実行するか決める)
  • 値が小さい順にチェーンが実行される

ポリシー

  • チェーン内のルールに該当しなかった場合、パケットを許可(accept)するか、破棄(drop)するかを指定する
  • 省略された場合はacceptとみなされる

ルール

ルールの追加はnft insert ruleまたはnft add ruleで行う。insertだと指定したハンドル番号の前に、addだと指定したハンドル番号の後にルールを追加する。ハンドル番号を指定しないと、insertの場合先頭にルールが追加され、addの場合末尾にルールが追加される。

nft add rule ip table01 chain01 handle [ハンドル番号] [式] [処理]

チェーンに登録されているルールを順に実行していき、全ルールの評価が完了するか、パケットがdropされるなどして評価を継続しない場合、そのチェーンでの評価が完了し、次のチェーンの評価を行う。

以下の例だと2つのルールを追加し、送信元IP59.138.xxx.xxxからのパケットは許可して、それ以外はdropさせている。

# nft add rule ip table01 chain01 ip saddr 59.138.xxx.xxx accept
# nft add rule ip table01 chain01 drop
# nft -a list ruleset
table ip table01 { # handle 1
        chain chain01 { # handle 1
                type filter hook input priority filter + 1; policy accept;
                ip saddr 59.138.xxx.xxx accept # handle 2
                drop # handle 3
        }
}

以下の例だとハンドル番号3の前に、ルールがを追加している。

# nft insert rule ip table01 chain01 handle 3 ip saddr 59.139.xxx.xxx accept
# nft -a list ruleset
table ip table01 { # handle 1
        chain chain01 { # handle 1
                type filter hook input priority filter + 1; policy accept;
                ip saddr 59.138.xxx.xxx accept # handle 2
                ip saddr 59.139.xxx.xxx accept # handle 4
                drop # handle 3
        }
}

ルールの修正はreplace、削除はdeleteで行う。

代表的な処理は次のようなものがある。

  • accept
  • drop
  • reject
    • パケットをrejectし、rejectしたことを送信元に返送する。withキーワードを併用することで、返送する情報を指定できる
  • log
    • パケットの情報をログに記録する
  • snat, dnat

おそらく一番多い用途は送信元/先IPと送信先ポートの指定だと思う。

ip saddr 100.122.34.10 ip daddr 22.31.33.44 tcp dport 443 accept

上の例だと、送信元IPをip saddrで指定し、送信先ip daddr、接続先ポート番号をtcp dportで指定している。

よく使用しそうなキーワードは以下の通り。

  • IPアドレス指定
    • ip saddr [IPアドレス]ip daddr [IPアドレス]IPv6の場合はip6 saddr、ICMPの場合はicmp saddrといった感じ)
  • プロトコル指定
    • ip protocol [プロトコル指定]
  • ポート番号指定
    • tcp sport [ポート番号]tcp dport [ポート番号]UDPの場合は、udp sportといった感じ)

他にもコネクションの状態やバイト数、など様々なキーワードがあり、複雑なケースにも対応できる。

ルールセットの保存と削除

ルールセットはnft list rulesetで出力したテキストを読み込むことで復元できる。なので、nft list ruleset > ruleset.txtでルールを保存することができる。ルールセットの削除はnft flush ruleseで行い、復元はnft -f ruleset.txtとする。

# nft list ruleset
table ip table01 {
}
# nft list ruleset > ruleset.txt # ルールセットの保存
# nft flush ruleset # ルールセットの削除
# nft list ruleset
# nft -f ruleset.txt # ルールセットの読み込み
# nft list ruleset
table ip table01 {
}

ルールセットの自動読み込み

nftablesコマンドによる設定は、電源を落としたり、再起動したりすると消える。RHELの場合は以下の方法で、システム起動時にnftablesルールを自動で読み込むことができる。これにより、常にシステムにルールが反映されるようにする。

RHELでは、/etc/sysconfig/nftables.confファイルにシステム起動時に読み込むファイルをinclude文で記述する。

/etc/sysconfig/nftables.conf

include "/etc/nftables/_example_.nft"

上記設定により、/etc/nftables/_example_.nftから設定を読み込む。

systemctl restart nftablesで再起動せずに設定を読み込んでくれる。

参考

nftables

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/securing_networks/getting-started-with-nftables_securing-networks

https://linuc.org/study/knowledge/1118/

https://knowledge.sakura.ad.jp/22636/

iptables

https://tech-blog.rakus.co.jp/entry/20220301/iptables

https://www.designet.co.jp/faq/term/?id=aXB0YWJsZXM#

https://knowledge.sakura.ad.jp/4048/

https://www.unix-power.net/networking/post-631