nftとiptablesの使い方

概要

  • nftとiptablesを使ってfirewallを設定する手順について確認したのでまとめる

nftとiptablesの違い

  • nftables は従来の用途ごとに分かれていたフィルタリングツール(iptables, ip6tables, arptables, ebtables)を統合して管理しやすくしたもの。
    • nftables のコマンドが nft になる。
    • 今後はnftが標準になっていくと思われるので新規で覚えるならnftを覚えればいいと思う。

使い方(iptables)

文法

iptables [-t テーブル] -A チェイン ルール     # チェインにルールを追加
iptables [-t テーブル] -D チェイン ルール     # チェインにルールを削除
iptables [-t テーブル] -P チェイン ターゲット # チェイン追加時のデフォルトターゲットの指定("P"olicy)
iptables [-t テーブル] -L [チェイン]          # チェインのルールを一覧表示
iptables [-t テーブル] -F [チェイン]          # チェインのルールを全削除("F"ull remove)
iptables [-t テーブル] -X [チェイン]          # チェインのルールを除外(e"X"clude)
iptables [-t テーブル] -N [チェイン]          # 指定した名前のチェインを新規作成("N"ew, "N"ame?)
iptables -Z                                   # 総てのチェインのパケットカウンタ、バイトカウンタをゼロクリア("Z"ero)

テーブル

テーブル 利用可能なチェイン 説明
raw PREROUTING, OUTPUT 接続追跡の対象から外れるようにパケットを設定する用
filter INPUT, OUTPUT, FORWARD パケットフィルタリング用(デフォルト)
nat PREROUTING, OUTPUT, POSTROUTING ネットワークアドレス変換(NAT)用
mangle all IPヘッダ書き換え用
security INPUT, OUTPUT, FORWARD 強制アクセス変換用(SELinux, MAC関連)
  • テーブル指定はどれを使ってもFirewall自体の処理に違いは無い
    つまり、チェインとしてOUTPUTを使いたい場合に、上記のどれを使っても違いがない
  • 基本的にはfilter以外はあまり使わないみたい

チェイン

チェイン 説明
PREROUTING 受信時(ルーティングの前)に実行, 宛先IP/portを変換
INPUT 受信時(ローカルプロセスに入る前)に実行, パケットの許可/不許可
FORWARD 転送するパケットの許可/不許可
OUTPUT 送信時(ローカルプロセスから出た後)に実行, パケットの許可/不許可
POSTROUTING 送信時(ルーティングの後)に実行, 送信元IP/portを変換

ターゲット

ターゲット 説明
ACCEPT 許可
DROP 破棄(相手への通知無し)
REJECT 拒否(相手への通知あり)
MASQUERADE IPマスカレード, アドレス変換を動的に行う
SNAT ("S"tatic) 送信元アドレスを変換する, 固定IPで利用
DNAT ("D"ynamic) 送信先アドレスを変換する。動的IPで利用
REDIRECT 送信先アドレスを変換する
LOW マッチしたパケットをログに記録

コマンドオプション

Option 説明
-s/--source 送信元のアドレスを指定
-d/--destination 送信先のアドレスを指定
--sport (TCP, UDP拡張) 送信元のport番号の指定
--dport (TCP, UDP拡張) 送信先のport番号の指定
-p/--protocol PROTの指定
-i/--in-interface 受信するインターフェースの指定
-o/--out-interface 送信するインターフェースの指定
-j/--jump 適用するターゲットの指定
-L/--list ルールの一覧表示
-I/--insert [RULE番号] チェインにルールを挿入

実行例

  • テーブルの設定確認
# コマンド
sudo iptables -L -t filter

# 実行結果
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

# 上記のようにデフォルトでは何もルールが無い
# また、ポリシーは全部 ACCEPT になっている。
  • テーブルのチェインにルールを追加
# コマンド
## パケットの送信先がTCP(port 22) = sshの場合に拒否(reject)する
sudo iptables -t filter -A INPUT -p tcp --dport 22 -j REJECT
## パケットの送信先がTCP(port 25) = smtpの場合に破棄(drop)する
sudo iptables -t filter -A INPUT -p tcp --dport 25 -j DROP
## パケットの送信先がTCP(port 80) = httpの場合に許可(デフォルトがacceptの為)
sudo iptables -t filter -A INPUT -p tcp --dport 80

# テーブルの状態
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
REJECT     tcp  --  anywhere             anywhere             tcp dpt:ssh reject-with icmp-port-unreachable
DROP       tcp  --  anywhere             anywhere             tcp dpt:smtp
           tcp  --  anywhere             anywhere             tcp dpt:http

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
  • テーブルのチェインからルールの削除
# コマンド
## 追加のコマンドの"-A"を"-D"に変えるだけ
sudo iptables -t filter -D INPUT -p tcp --dport 22 -j REJECT
sudo iptables -t filter -D INPUT -p tcp --dport 25 -j DROP
sudo iptables -t filter -D INPUT -p tcp --dport 80
## また、以下のコマンド(全消し)でも消せる
sudo iptables -t filter -F

使い方(nft)

はじめに

  • nftはiptablesより自由度が高くなっているので、以下の順序でルールを追加することになる
    1. テーブルの追加
    2. チェインの追加
    3. ルールの追加

文法

nft list ruleset                                              # 作成したルールの確認
nft add table [ファミリー] テーブル                             # テーブルの追加
nft add chain [ファミリー] テーブル チェイン { ベースチェイン } # チェインの追加
nft add rule [ファミリー] テーブル チェイン 条件                # ルールの追加
nft delete table テーブル                                     # テーブルの削除
nft delete chain テーブル チェイン                            # チェインの削除
nft flush table [ファミリー] テーブル                           # 各チェインのルールを全削
nft --handle --numeric list chain テーブル チェイン           # 各条件の連番を表示
nft delete rule テーブル チェイン handle 番号                 # 番号を指定してルールを削除する
nft flush chain テーブル チェイン                             # チェインを指定してルールの一括削除

テーブル/ファミリー

  • iptablesと違い、nftには基本的にデフォルトでテーブルは作成されていない
  • テーブルの作成時に、ファミリー名を指定可能である
  • ファミリー名は省略可能で、省略した場合は"ip"(= iptables)が使われる
  • ファミリー名はiptables系ユーティリティーの区分みたいなもので以下の対応が有る
ファミリー 対応するユーティリティー
ip iptables
ip6 ip6tables
inet iptables, ip6tables
arp arptables
bridge ebtables

チェイン

  • こちらもiptablesと違い、デフォルトのチェインは無いので自分で作成する必要が有る。
  • ベースチェインとレギュラーチェインがある

    • ベースチェインはNetfilter(nft本体)が呼び出す
    • レギュラーチェインは他のチェインから呼び出される
  • ベースチェインの書式、及びパラメータ

    • 各パラメータの詳細はリンク先で確認できる
# 書式
nft add chain ファミリー テーブル チェイン { type タイプ hook フック [device デバイス] priority 優先値; [policy ポリシー;] }

条件 (statements)

  • 条件としては以下のようなものが有る

その他

  • Sets, Maps, Elements ... といろいろ有るが難しいので飛ばす

実行例

  • テーブルの状態確認
sudo nft list rulesets

# 実行結果
table inet filter {
        chain input {
                type filter hook input priority 0; policy accept;
        }
        chain forward {
                type filter hook forward priority 0; policy accept;
        }
        chain output {
                type filter hook output priority 0; policy accept;
        }
}

# テーブルが登録されていれば、上記のように何かしら表示される
# テーブルがなければ、何も表示されない
  • テーブルの追加
sudo nft add table sample

# テーブルの状態
table ip sample {
}

# ファミリー名の指定がデフォルトなので、"ip"になる。
  • チェインの追加
sudo nft add chain sample c1

# テーブルの状態
table ip sample {
          chain c1 {
          }
}
  • ベースチェインの追加
sudo nft add chain sample c2 { type filter hook input priority 0 \; policy accept \; }

# テーブルの状態
table ip sample {
          chain c1 {
          }

          chain c2 {
                  type filter hook input priority 0; policy accept;
          }
}
  • ルールの追加
sudo nft add rule sample c1 tcp dport 22 reject
sudo nft add chain sample c3 { type filter hook input priority 0 \; policy accept \; }
sudo nft add rule sample c3 tcp dport 22 reject

# テーブルの状態
table ip sample {
          chain c1 {
                  tcp dport ssh reject
          }

          chain c2 {
                  type filter hook input priority 0; policy accept;
          }

          chain c3 {
                  type filter hook input priority 0; policy accept;
                  tcp dport ssh reject
          }
}

# 上記は次の様になる。chain c1はレギュラーチェインなので、他から呼び出されない限り使われない。
# chain c2はベースチェインなので、これが呼ばれる。
# chain c3はベースチェインであるが、ベースチェインのc2が存在するので呼ばれない。
# そのため、当該PCへのssh通信が可能な状態になっている。
  • ルールの削除
sudo nft --handle --numeric list chain sample c3
# 実行結果
table ip sample {
          chain c3 {
                  type filter hook input priority 0; policy accept;
                  tcp dport ssh reject # handle 11
          }
}

# 上記の様にルールの後ろにハンドル番号が表示される
# 削除する場合は、ハンドル番号を指定して削除する。
sudo nft delete rule sample c3 handle 11

# c3内のルールを全部削除する場合は以下でも良い
sudo nft flush chain sample c3

# テーブルの状態
table ip sample {
          chain c1 {
                  tcp dport ssh reject
          }

          chain c2 {
                  type filter hook input priority 0; policy accept;
          }

          chain c3 {
                  type filter hook input priority 0; policy accept;
          }
}

# 実行結果は上記(chain c3)の様にベースチェインの情報だけが残る
  • チェインの削除
sudo nft delete chain sample c3

# テーブルの状態
table ip sample {
          chain c1 {
                  tcp dport ssh reject
          }

          chain c2 {
                  type filter hook input priority 0; policy accept;
          }
}
  • テーブルの削除
sudo nft delete table sample

# この状態でテーブルの一覧を確認すると全部消えていることが確認できる

参考サイト