nft によるMSQUERADE(iptables MASQUERADEからの移行)
iptablesでマスカレード(またはSNAT)は古くから行われている枯れた手法。これをnft(nftables)に書き換える場合のメモ
次のような、マスカレード(NAT)をiptablesで追記しているとする。
iptables -I FORWARD -o ${interface} -j ACCEPT
iptables -t nat -A POSTROUTING -o ${interface} -j MASQUERADE
たとえば、このように。ルーティングと組み合わせて使ってる。
DEST_NET=10.1.1.0/24
interface=vpn0
router=10.1.1.1.1
ip route add ${DEST_NET} via ${router} dev ${interface}
##
iptables -I FORWARD -o ${interface} -j ACCEPT
iptables -t nat -A POSTROUTING -o ${interface} -j MASQUERADE
これをnft(nftables)に書き換えてみると。
nft コマンドでは次のようになる。 テーブル追加とチェインの追加、そして、ルールの追加である。
interface=vpn0
router=10.1.1.1.1
TABLE=my_vpn_nat
nft add table ip ${TABLE};
# 冗長じゃない?
nft add chain ${TABLE} prerouting { type nat hook postrouting priority srcnat \; }
nft add chain ${TABLE} postrouting type nat hook postrouting priority srcnat accept;
nft add rule ${TABLE} postrouting oifname ${interface} masquerade
nft add rule ${TABLE} postrouting oifname ${interface} masquerade
テーブルの追加
nft add table ip ${TABLE};
一般形式は次のようになっていて。
nft add table <?family> <name>
<?family> にはip, ip6, inet ,arp, bridge が使える。省略時は ip である。ipはv4 アドレスを意味する。inet はinet = ip + ip6であり、v6/v4に無関係(双方)を指す。
テーブルを削除する場合 add を delete にかえるだけである。(2023-08-29 現在 del ではエラーになる)
nft delete table <?family> <name>
サンプル
nft add table my_sample nft list tables # チェック nft delete table my_sample nft list tables # チェック
チェインの追加
チェインは、テーブル内部に作られる。チェインの中にはパケットのルールが入る。ルールをグループにして一括りにする。
nft add chain <?family> <table> <chain_name> { \
type <type> hook <hook> priority <priority> \; \
policy <policy> \;
}
hook はチェインが実行されるタイミング。type は何をするか。
{ ... } で括られた部分が、チェインに入るruleである。
ip/ip6/inetにおいては、
hook={prerouting, input, forward, output, postrouting}から一つ.type={filter,nat,route}から一つを選ぶ。policy ={accept,drop}から一つを選ぶ。priorityは、他のチェイン・ルールとの優先度±1 を書く。基本は0を書いておく。
ベースチェインの候補は、テーブル名やチェイン名と混同するような類似キーワードが多く初見殺しである。
以下をよく覚えておく。
type <type_name> hook <hook_name> priority <num|name>
例えばよくあるサンプルでは次のようになっている
nft add chain vpn_nat postrouting { type nat hook postrouting priority srcnat; policy accept; }
この場合、ベースチェインの名前=postrouting となり、hook = postrouting であり、type=nat であり、priority=srcnatである。postroutingとnatが、名前にもキーワードにも登場し、ややこしくなる。これが初見殺しである。
ベースチェインとはiptablesでも使っていた、mangle や nat のような特定パケットに一致する機能である。
ベースチェインのタイプ未指定にしたら、単なる関数になる。独立したチェインとして登録され、他チェインから呼び出されるために存在できる。
## ベースチェイン(タイプあり)の例
nft add chain ip MyMangle prerouting { type filter hook prerouting priority mangle \;}
## 単純チェイン(ベースタイプなし)の例
nft add chain ip MyMangle my_chain
詳しくは、公式wikiを参考にする。
ベースチェインは「パケットが条件一致したら呼び出される手順」、関数は「他チェインのルールから使われる手順」という違いがある。
マスカレード対象のフォワードをAcceptする。
iptable の場合は次のように先頭に書けば良い。
iptables -I FORWARD -o $TARGET_IF -i br0 -j ACCEPT
nftables の場合は次のように、対象のチェインに追記すると良い
nft insert rule inet fw4 forward iifname br0 oifname $TARGET_IF accept;
nftablesの場合は、同じチェイン内でaccept したら打ち止めになるが、ほかテーブルを参照している場合、他テーブルでDROPされる可能性もあるので注意する。デフォルトがDROPなどであれば、add は使わずに、insert でチェイン先頭にacceptを追記するようにする。