iptables後継のnftables基本操作
            目次
2019年9月24日、皆さん待望のCentOS 8がリリースされました。
CentOS 6から7になった際も色々と変化がありましたが、CentOS 7から8でもやはり何点か変化があります。
主要な変化としては以下の様なものが挙げられるでしょう。
- カーネルやミドルウェアのバージョン変更
 - yumからdnfへ移行
 - iptablesからnftablesへの移行
 
これらの差異については他サイトへ譲るとして、今回はnftablesの操作について簡単に紹介します。
nftablesの起動・終了
nftablesはサービスとして導入されています。
そのためsystemctlコマンドで操作が可能です。
# systemctl start nftables # systemctl stop nftables
設定ファイル
nftablesサービスの起動時、設定ファイルとして/etc/nftables.confを読み込みます。
ルールの表示
nftablesの操作にはnftコマンドを使います。
ルールを表示するには、nft list rulesetを実行します。
# nft list ruleset
table inet filter {
        chain input {
                type filter hook input priority 0; policy accept;
        }
        chain forward {
                type filter hook forward priority 0; policy drop;
        }
        chain output {
                type filter hook output priority 0; policy accept;
        }
}
nftablesではiptablesと同様にルールは上から評価されます。
そのためルールの順番が重要です。
操作するルールの位置を表示するためには、--handleパラメータを使います。
# nft list ruleset --handle
table inet filter { # handle 0
        chain input { # handle 1
                type filter hook input priority 0; policy accept;
                iifname "lo" accept # handle 4
        }
..(snip)..
説明のため異なるルールを表示していますが、tableやchain、ルールの末尾にhandleが付くようになりました。
ルールの操作をする際には、この番号を使う事になります。
ルールの構造
nft list rulesetの結果を見ると、iptablesとは出力が全く異なることが分かります。
nftablesでは、
| 名前 | 説明 | 
|---|---|
| table | アドレスファミリー毎にchainをまとめるもの | 
| chain | ruleをまとめるもの | 
| rule | 通信制御ルール | 
というような概念となっています。
table inet filterは、アドレスファミリー:inet、テーブル名:filterというテーブルを示します。
chain inputは、チェイン名:inputというチェインを示します。
アドレスファミリー
アドレスファミリーは以下の種類が定義されます。
| family | 説明 | 
|---|---|
| ip | IPv4を示します | 
| ip6 | IPv6を示します | 
| inet | インターネット(IPv4とIPv6)の両方を示します | 
| arp | ARPを示します。IPv4 ARPを操作できます | 
| bridge | ブリッジを示します。ブリッジデバイスを通るパケットを操作できます | 
| netdev | NICドライバがネットワークスタックに渡した直後の、進入する全てのトラフィックを分類できます。DDoS対策などに有用です | 
inetを使っておけば、IPv4、IPv6の両方を扱えます。
netdevは、iptablesでは扱えなかったファミリーです。Linux kernel 4.2以降が必要です。
チェイン
上の例ではinput、forward、outputチェインが存在しています。
このチェインはiptablesのように事前に定義されたものではなく、単なるチェイン名として名付けられているだけです。
元々はこれらのチェインも存在しません(例示のためにこちらで追加したものです)。
実際にパケットの流入(input)、送出(output)、転送(forward)時に処理をすることを示しているのは、チェインの中のtype filter hook input priority 0; policy accept;というような行です。
このような行を含み、inputやoutput等の基本的なパケットフィルタリングを行うチェインをベースチェインと呼んでいます。
デフォルトでチェインは用意されていないので、まず最初にベースチェインを作成する必要があります。
iptablesにおけるINPUTチェインの様なベースチェインを作成するには、以下の様なコマンドを使います。
## チェインの追加
# nft add chain inet filter input { type filter hook input priority 0\; }
## チェインの表示
# nft list chain inet filter input
table inet filter {
        chain input {
                type filter hook input priority 0; policy accept;
        }
}
上記で追加したベースチェインは以下のような設定になっています。
- チェイン (
chain inet filter inputの部分)- ファミリー:
inet(IPv4/IPv6) - テーブル名:
filter - チェイン名:
input 
 - ファミリー:
 - ルール (
type filter hook input priority 0の部分)- ベースチェインのタイプ(type):
filter - フック(hook):
input - プラオリティ(priority):
0 - ポリシー:
accept(デフォルト) 
 - ベースチェインのタイプ(type):
 
nft addを実行する際、ルール末尾の;(セミコロン)はシェルが特別な意味を持つ文字なので、エスケープが必要です。
チェインのタイプ一覧
type filterのfilter部分は、filterの他に以下から選択できます。
| type | 利用可能なファミリー | 利用可能なフック | 説明 | 
|---|---|---|---|
| filter | all | all | 標準のチェーンタイプ | 
| nat | ip, ip6 | prerouting input output postrouting  | 
アドレス変換を行うチェーンタイプ | 
| route | ip, ip6 | output | 通過したパケットの再度ルート探索を行う IPヘッダの変更を行うルールなどを活用してポリシールーティングなどに利用できる  | 
チェインのフック一覧
hook inputのinput部分は、inputの他に以下から選択できます。
※ファミリーがip, ip6, inetの場合
| hook | 説明 | 
|---|---|
| prerouting | システムに流入しようとするパケットを処理する ルーティングに影響する値をフィルタ、変更したい場合に利用する  | 
| input | システムに流入したパケットを処理する | 
| forward | 他のホストに転送されたパケットを処理する | 
| output | システムによって送出したパケットを処理する | 
| postrouting | システムから流出していくパケットを処理する | 
ルールの追加
ルールを追加するには、nft add ruleまたはnft insert ruleを実行します。
書式:nft add|insert rule family table chain statement
## inputチェイン末尾にルールを追加 # nft add rule inet filter input iifname ens3 tcp dport http accept ## inputチェイン先頭にルールを追加 # nft insert rule inet filter input iifname ens3 tcp dport http accept
ルールを特定の位置に追加するには、positionにhandleの番号を指定します。
書式:nft add|insert rule family table chain position statement
## handle4の後に追加 # nft add rule inet filter input handle 4 iifname ens3 tcp dport http accept ## #handle4の前に追加 # nft insert rule inet filter input handle 4 iifname ens3 tcp dport http accept
ルールの書式
上記の例では、statementはiifname ens3 tcp dport http acceptの部分に該当します。
このstatementは以下の様な意味を持ちます。
- 入力インタフェース名(iifname)
- ens3
 
 - TCP宛先ポート(tcp dport)
- http
 
 - 処理
- accept
 
 
statementに該当する部分にはさらに複雑なルールも指定でき、以下に挙げるような表現を使うことができます。
全容は非常に大量の表現がある為、主要なものに絞って紹介します。
メタ表現
パケットに関連したメタデータにマッチさせることができます。
| Keyword | 値のタイプ | 説明 | 
|---|---|---|
| meta length | integer (32bit) | パケット長(バイト) | 
| iifname | ifname | 
入力インタフェース名 | 
| oifname | ifname | 
出力インタフェース名 | 
| pkttype | pkt_type | 
パケットタイプUnicast, Broadcast, Multicast | 
TCPヘッダ用表現
| Keyword | 値のタイプ | 説明 | 
|---|---|---|
| sport | inet_service | 
Source port。送信元ポート | 
| dport | inet_service | 
Destination port。送信先ポート | 
| flags | tcp_flags | 
TCPのフラグnft describe tcp flagsにより出力されるフラグを指定可能 | 
sport/dport
値のタイプであるinet_serviceですが、この値にはポート番号をそのまま指定するほか、/etc/servicesに定義されているサービス名での指定が可能です。
例えば、tcp dport 80とtcp dport httpは同じ指定となります。
UDPヘッダ用表現
| Keyword | 値のタイプ | 説明 | 
|---|---|---|
| sport | inet_service | 
Source port。送信元ポート | 
| dport | inet_service | 
Destination port。送信先ポート | 
| length | integer (16bit) | 全体のパケット長 | 
ICMPヘッダ用表現
| Keyword | 値のタイプ | 説明 | 
|---|---|---|
| type | icmp_type | 
ICMPタイプnft describe icmp typeにより出力されるタイプを指定可能 | 
| code | integer (8bit) | ICMPコード | 
| gateway | integer (32bit) | ゲートウェイのIPアドレス | 
| mtu | integer (16bit) | 経路MTU探索のMTU | 
ICMPv6ヘッダ用表現
| Keyword | 値のタイプ | 説明 | 
|---|---|---|
| type | icmpv6_type | 
ICMPv6タイプnft describe icmpv6 typeにより出力されるタイプを指定可能 | 
| code | integer (8bit) | IMCPv6コード | 
CT (Conntrack, Connection Tracking) 表現
ステートフルなファイアウォールのため、パケットの状態にマッチさせることができます。
| Keyword | 値のタイプ | 説明 | 
|---|---|---|
| state | ct_state | 
パケットのステートnft describe ct stateにより出力される値を指定可能 | 
| direction | ct_dir | 
パケットの方向originalまたはreplyを指定可能 | 
| status | ct_status | 
パケットの状態 nft describe ct statusにより出力される値を指定可能  | 
処理の表現
| Keyword | 説明 | 
|---|---|
| accept | ルールの評価をここで終了し、パケットを許可 | 
| drop | ルールの評価をここで終了し、パケットを破棄 | 
| queue | ルールの評価をここで終了し、ユーザスペースのアプリケーションにパケットを渡す | 
| continue | ルールの評価を続ける | 
| return | 現在のチェインから抜けて、一つ前のチェインの次のルール評価を続ける ベースチェインで returnすると、処理はacceptされる | 
| jump chain | 別のchainへ飛んで、chainの最初のルールから評価を始める chainの全ルールの評価が終わった、もしくは returnした場合に次の行から評価を続ける | 
| goto chain | 別のchainへ飛んで、chainの最初のルールから評価を始める chainの全ルールの評価が終わった、もしくは returnしても次の行の評価はしない(終了する) | 
サンプル表現
## 以下全てtype filter hook inputのベースチェイン内のルール
# ステートがestablishedまたはrelatedのパケットを許可
iifname ens3 ct state established, related accept
iifname ens3 ct state { established, related } accept # このように書いてもよい
# 22/tcp宛のパケットを許可
iifname ens3 tcp dport ssh accept
# 22/tcp、80/tcp宛のパケットを許可
iifname ens3 tcp dport { ssh, http } accept
# icmpの宛先到達不可能通知、エコー応答通知を許可
iifname "ens3" icmp type { destination-unreachable, echo-request } accept
なぜだか分かりませんが、ct stateでは{ }で囲わなくても良さそうです。
ルールの削除
ルールを削除するには、nft delete ruleを実行します。
## ルールをhandle付で表示
# nft list ruleset --handle
table inet filter { # handle 0
        chain input { # handle 1
                type filter hook input priority 0; policy accept;
                iifname "lo" accept # handle 4
        }
..(snip)..
## handle4のルールを削除
# nft delete rule inet filter input handle 4
ルールを全て削除するには、nft flush rulesetを実行します。
ルールの保存
(2020/03/05 嘘が混ざっていたので修正)
ルールを保存するには、ルールを/etc/nfttables/rules.nftへ出力します。
ファイル名は何でも良いですが、/etc/sysconfig/nftables.confでincludeしているファイル名である必要があります。
# echo -e "#!/usr/sbin/nft -f\n\nflush ruleset\n\n" > /etc/nftables/rules.nft # nft list ruleset >> /etc/nftables/rules.nft
nftables.confの方は以下の様にしておきます。
# # This this will contain your nftables rules and # is read by the systemd service when restarting # # These provide an iptables like set of filters # (uncomment to include) # include "/etc/nftables/bridge-filter.nft" # include "/etc/nftables/inet-filter.nft" # include "/etc/nftables/ipv4-filter.nft" # include "/etc/nftables/ipv4-mangle.nft" # include "/etc/nftables/ipv4-nat.nft" # include "/etc/nftables/ipv6-filter.nft" # include "/etc/nftables/ipv6-mangle.nft" # include "/etc/nftables/ipv6-nat.nft" include "/etc/nftables/rules.nft"

    
    
    
    
    
最近のコメント