Help us understand the problem. What is going on with this article?

netfilterとfirewalldとiptablesとnftablesの関係

はじめに

netfilterについて少し調べてみました。
いろいろと認識の相違があったことがわかったので、記録します。

認識の相違

CentOS8(に限らずだけど)では、以下のことがわかった。
iptablesはiptablesではなくnftablesである
firewall-cmdで設定したルールはiptablesでは表示されない
すべてのルール確認はnftを使う

Linuxでのパケットの流れについて

netfilter

netfilterはLinuxでパケットの処理をする基本ルール
インタフェイスで受信したパケットがどんな処理をされていくか、というやつです。

netfilter.orgによると、

netfilterは、カーネルモジュールがネットワークスタックにコールバック関数を登録できるようにするLinuxカーネル内の一連のフックです。登録されたコールバック関数は、ネットワークスタック内の各フックを通過するすべてのパケットに対してコールバックされます。

だそうです。ありがとうgoogle翻訳!

つまり、パケットがネットワークスタックを通り抜けるときに、netfilterで定義した「フック」というものにより、何らかの処理を挟み込めるようにした仕組み。ということでしょうか。

netfilterのchain

ネットワークスタックを通り抜ける一連の処理のことをchainと呼びます。
chainは、以下のものから構成されます。

名称 意味
hook (ネットワークスタックの)どの部分 で
priority どのような順番 で
type どのような処理をする か

基本は以下の図です。

Screenshot from Gyazo

参考:https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg

netfilterのchainのhook

「(ネットワークスタックの)どの部分」で、処理が行われるか、を表現したものが、hookです。
つまり、ひっかけるタイミングを表現しています。

上図の中央付近にある、 routing decision の部分で処理が変わっているのがわかると思います。
流入したパケットが「ローカル宛て」か、「ローカル宛てじゃない(=転送する)」かで、使われるhookが変わります。

hookの部分にフォーカスしたものが以下です。

                                             Local
                                            process
                                              ^  |      .-----------.
                   .-----------.              |  |      |  Routing  |
                   |           |-----> input /    \---> |  Decision |----> output \
--> prerouting --->|  Routing  |                        .-----------.              \
                   | Decision  |                                                     --> postrouting
                   |           |                                                    /
                   |           |---------------> forward --------------------------- 
                   .-----------.

参考:https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks

つまり、宛先によって、使われるhookが以下の2通りになります。

ローカルあての場合
prerouting -> input -> output -> postrouting

転送する場合
prerouting -> forward -> postrouting

(このほかにも、ingressというL2へのパケットに対するhookもあるみたいです。)

netfilterのchainのpriority

「どのような順番」で、処理が行われるか、を表現したものが、priorityです。
つまり、各hookの中での処理の順序を表現しています。

priorityは正負の数値で表現されますが、別名が定義されています。
dstnatとscrnatはそれぞれ、preroutingとpostroutingのhookでのみ利用可能です。

ですが、実体は飽くまで数値です。

通称 定義 priority 利用可能なhook
- NF_IP_PRI_RAW_BEFORE_DEFRAG -450 すべて
- NF_IP_PRI_CONNTRACK_DEFRAG -400 すべて
raw NF_IP_PRI_RAW -300 すべて
- NF_IP_PRI_SELINUX_FIRST -225 すべて
- NF_IP_PRI_CONNTRACK -200 すべて
mangle NF_IP_PRI_MANGLE -150 すべて
dstnat NF_IP_PRI_NAT_DST -100 prerouting
filter NF_IP_PRI_FILTER 0 すべて
security NF_IP_PRI_SECURITY 50 すべて
srcnat NF_IP_PRI_NAT_SRC 100 postrouting
- NF_IP_PRI_SELINUX_LAST 225 すべて
- NF_IP_PRI_CONNTRACK_HELPER 300 すべて

参考:http://git.netfilter.org/nftables/tree/include/linux/netfilter_ipv4.h
参考:https://manpages.debian.org/testing/nftables/nft.8.en.html

いわゆる「テーブル」ってやつに似てますね。

netfilterのchainのtype

「どのような処理をする」のか、を表現したものが、typeです。
つまり、具体的にパケットをどうするのか、ということを表現しています。

type 利用可能なhook
filter すべて
nat prerouting,postrouting,input,output
route output

あれ?こっちも「テーブル」ってやつに似てますね。
だから紛らわしいんだよ!

参考:https://www.netfilter.org/projects/nftables/manpage.html

firewalldとiptablesとnftables

netfilterを構成するものについては、上で解説しましたが、じゃあnetfilterをどう操作するの?
ということで、それらを操作するソフトウェアの話です。

firewalld ってなんだ?

firewalld が最上位にいて、バックエンドでiptablesもしくはnftablesが動作している。
バックエンドで動作するiptablesもしくはnftablesがnetfilterの操作をしている。

古いバージョンの firewalld ではバックエンドに iptables が、
新しいバージョンの firewalld ではバックエンドに nftables が、採用されている。

Screenshot from Gyazo

とても分かりやすい。
てか、本稿のタイトルはもはやこれ1枚でいいんではなかろうか。

参考:https://firewalld.org/documentation/concepts.html

iptables ってなんだ?

iptablesはnetfilterを操作できるツールだ。
firewalldが導入される前の古いCentOSでは、iptablesをiptables-serviceというものでデーモン化(サービス化?)していた。
つまり、iptablesコマンドでiptablesのルールを直接変更したり、特定のファイルを読み込ませたりすることで、フィルタリングなりNATなりをしていたんだ。

CentOS8にもiptablesはあるが、実体はnftablesで動作している。

# iptables --version
iptables v1.8.2 (nf_tables)

とはいえ、すでに iptables は iptables ではない。

# ll /usr/sbin/iptables
lrwxrwxrwx. 1 root root 17 11月  9 03:40 /usr/sbin/iptables -> xtables-nft-multi

# man xtables-nft
NAME
       xtables-nft ― iptables using nftables kernel api

DESCRIPTION
       xtables-nft  are versions of iptables that use the nftables
       API.  This is a set of tools to help the system administra‐
       tor  migrate  the  ruleset  from iptables(8), ip6tables(8),
       arptables(8), and ebtables(8) to nftables(8).

iptablesを叩くと、それっぽい書式でルールが見える。
けど、iptablesからは、後述するnftablesで追加したテーブルが見えない。
だから、iptables -L -nv -t nat|filter で表示されるルールと実際の動作が噛み合わないことがある。

例えば、Dockerホストからbridge接続されているコンテナへポート転送をするために firewall-cmd --add-masquerade としたとき。nftでchainを確認すると、以下の動作が見える。

# nft list chain ip firewalld nat_POST_public_allow
table ip firewalld {
        chain nat_POST_public_allow {
                oifname != "lo" masquerade
        }
}

けど、iptablesから firewalld というテーブルは見れない。

# iptables -L -t firewalld
iptables v1.8.2 (nf_tables): table 'firewalld' does not exist
Perhaps iptables or your kernel needs to be upgraded.

man iptablesでTABLESの部分をみてみると、iptablesでは、決められたキーワードのテーブルしか確認ができない。

TABLES
       There  are  currently  five  independent tables (which tables are present at any time depends on the kernel configuration options and which modules are
       present).

       -t, --table table
              The tables are as follows:
              filter:
              nat:
              mangle:
              raw:
              security:

つまり、firewalldのバックでnftablesが動作している場合、 iptablesで表示したルールは正しくない!
ので、ルール確認は、 iptablesでなくnftを使う!

nftables ってなんだ?

nftablesもnetfilterを操作できる、iptabesに置き換わるツールだ。
前述のiptablesと同じような感じで、nftablesもサービス化できるみたいだけど、、、

# systemctl status nftables
● nftables.service - Netfilter Tables
   Loaded: loaded (/usr/lib/systemd/system/nftables.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:nft(8)

CentOS8ではfirewalldが動作していて、nftablesが裏で動作しているので、nftablesとしてのデーモンは休んでいるみたい。

その中身は、以下のように、 nft コマンドでルールのflush(=除去)と設定ファイルの読み込みをしている。
iptablesをデーモン化したときと似ているね。

# cat /usr/lib/systemd/system/nftables.service  | grep nft
Documentation=man:nft(8)
ExecStart=/sbin/nft -f /etc/sysconfig/nftables.conf
ExecReload=/sbin/nft 'flush ruleset; include "/etc/sysconfig/nftables.conf";'
ExecStop=/sbin/nft flush ruleset

debian/arch/ubuntu/fedora では、nftablesのデーモン動作がデフォルトになっているようだ。

参考:https://wiki.nftables.org/wiki-nftables/index.php/Nftables_from_distributions

基本的なnftablesの使い方

nft

nftablesは nft というコマンドで提供されます。
nftで設定するルールは、処理そのものであるchainと、chainをひとまとめにしたtableとして表現されます。

chainは特定のhookで特定のtypeで表現される処理をまとめたものであり、「(ネットワークスタックの)どの部分」で「どのような順番」で「どのような処理をする」かは、ひとつのchainでまとめられます。
tableは複数のchainをまとめた仮想的なグループとしてとらえます。

設定の確認は nft list というコマンドを使います。

nft list table(s)

設定されているすべてのtableの名称のみ表示します。

# nft list tables
table ip filter
table ip6 filter
(とか、たくさん)

指定したtableの設定されているすべてのchainを表示します。

# nft list table ip nat
table ip nat {
        chain PREROUTING {
                type nat hook prerouting priority -100; policy accept;
                fib daddr type local counter packets 0 bytes 0 jump DOCKER
        }
(table ip natに含まれるchainがすべて表示されます)

nft list chain(s)

設定されているすべてのchainに対して、各chainがどのtableに含まれているか、発動条件である「(ネットワークスタックの)どの部分」で「どのような順番」の処理を行うのか、が表示されます。
(具体的な処理内容は表示されません)

# nft list chains
table ip filter {
        chain INPUT {
                type filter hook input priority 0; policy accept;
        }
        chain FORWARD {
                type filter hook forward priority 0; policy drop;
        }
(たくさん表示されます)

指定したchainを表示します

# nft list chain ip filter FORWARD
table ip filter {
        chain FORWARD {
                type filter hook forward priority 0; policy drop;
                counter packets 0 bytes 0 jump DOCKER-USER
(たくさん表示されます)

すべてのルールの表示

設定されているすべてのルールが表示されます。

# nft list ruleset
table ip filter {
        chain INPUT {
                type filter hook input priority 0; policy accept;
        }

        chain FORWARD {
                type filter hook forward priority 0; policy drop;
                counter packets 0 bytes 0 jump DOCKER-USER

(すごくたくさん表示されます)

さいごに

netfilterはじめ、パケットの取り扱いは奥が深い。
これでもまちがった理解をしているかもしれないし、テキトーに設定してもなんとか動いちゃうこともある。
なるべく正しい知識を取り入れたい。

bashaway
2019/1/1よりQiita利用開始しました。よろしくお願いします。 趣味は自宅ラボ&ホビープログラム。いまはcactiのcisco用コンフィグ取得プラグインの作成中。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away