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"

最近のコメント