NanoPi NEO3をv6プラスのルーターにする systemd-networkd + nftables

NanoPi NEO3

これまでNanoPi NEO2をv6プラスのIPv4用(MAP-E)のルーターにしていたが、NanoPi NEO2はGbEのポートが1つとUSB2.0ポートが1つあるだけなので、USBネットワークアダプタを使って2ポートのルーターにしても片側は900Mbpsほど出る可能性があるもののUSB側は頑張っても350Mbps程度しか出ない。つまり、NanoPi NEO2をルーターにするとフレッツ回線の名目1Gbpsにはほど遠い。そこで2020年7月に販売開始されたUSB3.0ポート搭載のNanoPi NEO3を購入してみた。(ルーターなら中身が似たもの姉妹モデルのNanoPi R2Sの方が良いかも)
これで、名目上はネットワーク2ポート共に1Gbps対応になる。

以前に書いた「NanoPi NEO2をv6プラスのルーターにする 後編」ではスクリプト1つを挙げたけど、シンプルでわかり易いがやり方として古さが否めない。それと、NetworkManagerは簡単で良い部分はあるけど勝手な動作のせいで最近のArmbian(のDebian Buster)では挙動がおかしいことがあるのよね。SLAACで自動的にVNEとIPv6で繋がる筈が全く繋がらないとか・・

正直なところ、ずっとFreeBSDしか触ってなかったのでLinuxのCLIを触りまくるようになったのはNanoPi NEOで遊び始めてから。NanoPi NEO2をMAP-Eのルーターにしたのも時期的には大して変わらない。だからド素人なのでその頃だと「systmed、ナニそれ美味しいの?」状態。最近ようやくLinuxにも慣れてきてやりたいことがあったらどういう方向で設定すれば良いかちょっぴり解り始めてきた。だから、以前とは違うやり方でやりたいと思った。

そこでネットワークの接続には NetworkManager ではなく systemd-networkd を使い、フィルタリングには iptables の代わりに nftables を使う。これで用意するファイルはバラけるもののだいぶモダン??な感じに。

これまで使ってきたNanoPi NEO2のルーターを置き換えるものだが、ネットワークの構成は以前の記事とはちょっと違う。(というか、以前の記事のときには図を簡単にするためにNAT66のLANを書かなかった)
2ポートのルーターで、片側はLANに、他方がVNEに、要するにONUの直下(のL2SW)に。このVNE側のNIC上にIPv4 over IPv6のトンネルを作る。LAN側はIPv4だけで通信する。
この記事のルーター設定には関係ないが、ONU直下のL2SWには別のルーターがぶら下がっていてそいつはIPv6専用でNAT66のLANを作っている。そのIPv6のLANに今回作るルーターのIPv4でデュアルスタックする。1台のルーターでIPv6とIPv4の両方のルーターにするわけではないので念の為。

$ sudo apt update    #パッケージデータベースを更新
$ sudo install iptables

以前と同じmap.shでやるなら、Armbianのミニマルにはiptablesは入っていないのでインストールする。他は特にはなくても動作そのものには困らない。このときに上の例だと素のiptablesが入るかもなのでiptablesではなくnftablesを指定してインストールする方が良いかも。(記事の後半で)

LAN側・VNE側の接続設定

USBネットワークアダプタをNanoPi NEO3に接続する。

$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
3: enxa0cec81818aa <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether yy:yy:yy:yy:yy:yy brd ff:ff:ff:ff:ff:ff

NICの名称は eth0 (これはNanoPi NEO3標準のネットワークポートの方)、USBネットワークアダプタが enxa0cec81818aa 。これをメモる。

今回はNetworkManagerを使わずに systemd-networkd を使う。そこで NetworkManager のサービス2つを無効にして systemd-networkd と systemd-resolvedを有効にする。

$ sudo systemctl disable NetworkManager-dispatcher.service
$ sudo systemctl disable NetworkManager.service
$ sudo systemctl enable systemd-networkd.service
$ sudo systemctl enable systemd-resolved.service

ここでシステムを停止すると、次回システム起動時にネットワークに繋がらなくなる可能性が高いので、少なくとも次の /etc/systemd/network/10-eth0.network だけは設定を書いておく。

/etc/systemd/network/10-eth0.network (新規)
1
2
3
4
5
[Match]
Name=eth0

[Network]
Address=192.168.0.10/24

eth0がLAN側のNICとする。この例ではIPアドレスを 192.168.0.10 とした。今回はルーターにするホストなのでこのNICの設定にはデフォルトゲートウェイなどは要らない。

/etc/systemd/network/11-enxa0cec81818aa.network (新規)
1
2
[Match]
Name=enxa0cec81818aa

enxa0cec81818aaがWAN側というかVNE側。フレッツの俗にいうIPoEならSLAACで自動設定されるが、MatchセクションにNameでNICの名前(システムに認識されている名前)を書かないとリンクアップしてもネットワーク的には存在しない同然になるので必ず設定。逆に、SLAACなので上の例で書いた2行以外はこの時点では不要。(書きたければご自由に)

$ ip addr
中略
3: enxa0cec81818aa:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether a0:ce:c8:18:50:cc brd ff:ff:ff:ff:ff:ff
    inet6 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 2591982sec preferred_lft 604782sec
    inet6 fe80::yyyy:yyyy:yyyy:yyyy/64 scope link 
       valid_lft forever preferred_lft forever

システムを起動してみて、WAN側(フレッツ側)のNICに自動的にIPv6アドレスが割り振られることを確認する。
ここで、inet6の行が表示されないならネットワークの物理接続が正しくないか設定を間違っていて、VNEとIPv6で繋がっていない状態。
確認するのは、上の例だと 24xx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/64 というアドレスがそれ。fe80の方は存在することだけ確認。これでVNEと繋がった(筈)。

/etc/resolv.conf (編集)
これはテキトーにネームサーバだけ書いておけば良い。(この記事では省略)

/etc/sysctl.conf (2行追加)
1
2
net.ipv4.ip_forward=1      #ルーターにするのでとりあえず追加(後で消す)
net.ipv6.conf.eth0.disable_ipv6=1    #これはLAN側でIPv6の通信したくない場合に追加。普通は不要。

ここで、以前と同じmap.shを起動すれば機能する。

ここまで、LAN側とVNE側をsystemd-networkd用の設定にしたので、ついでにトンネルもsystemd-networkd用の設定にしたい。

先に作ったVNE側のネットワーク設定ファイルを触る。
/etc/systemd/network/11-enxa0cec81818aa.network (空行+Networkセクションの3行追加)

1
2
3
4
5
6
[Match]
Name=enxa0cec81818aa

[Network]
Address=CEのIPv6アドレス/64
Tunnel=v6ptnl0

AddressはVNE側に設定したいIPv6アドレスで、MAP-EではIPv6のプリフィックス等から決められた計算方法で求めたもの。以前のスクリプトではip -6 addr add $CE dev $WANDEVに相当するもの。最後にスラッシュとプリフィックスのビット数も書く。
Tunnelのv6ptnl0はv6プラス用トンネルとして勝手に決めた名前。以前のスクリプトだとip6tnl1。これは好きな名前でどうぞ。

トンネル用の設定

/etc/systemd/network/12-v6ptnl.network (新規)ファイル名のv6ptnlの部分は任意
1
2
3
4
5
6
7
8
[Match]
Name=v6ptnl0

[Network]
IPForward=ipv4

[Route]
Destination=0.0.0.0/0

MatchセクションのNameは先のVNE側.networkで決めたTunnelと同じ名前を指定。
NetworkセクションのIPForward=ipv4は以前だと/etc/sysctl.confにnet.ipv4.ip_forward=1とか書いてたやつ。このトンネルデバイスでフォワーディングするのでここで書いてしまう。/etc/sysctl.confのnet.ipv4.ip_forward=1は要らなくなったので消す。
Routeセクションでデフォルトルートを指定。以前のスクリプトでは route add default dev $TUNDEV に相当。

/etc/systemd/network/v6ptnl.netdev (新規)ファイル名のv6ptnlの部分は任意
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[NetDev]
Name=v6ptnl0
Kind=ip6tnl
#MTUBytes=1460

[Tunnel]
Mode=ipip6
Local=CEのIPv6アドレス
Remote=BRのIPv6アドレス
DiscoverPathMTU=yes
EncapsulationLimit=none

NetDevセクションのNameは先のVNE側.networkで決めたTunnelと同じ名前を指定。
Kindは名前と役割が決まっている30種類以上から選択して指定。今回はIPv4 over IPv6のトンネルにするのでip6tnlを指定。 MTUBytesは1460を指定。これは以前のスクリプトのip link set dev $TUNDEV mtu 1460に相当。ただし、この行が無くても種類がip6tnlだと勝手に1460になるっぽい?上の例ではコメントにしている。

TunnelセクションのModeはipip6。これはiproute2あたりのマニュアルを見た。
LocalとRemoteはトンネルの入り口と出口。Localは以前のスクリプトだと$CEに入れたIPv6アドレスで、VNE側のNICに自動的に割り振られたIPv6アドレスではなく、MAP-E用に決められた計算方法で求めたもの。Remoteは以前のスクリプトだと$BRに入れたIPv6アドレスで、これは各VNEのNTTの東西エリアそれぞれ決まったBorder RelayホストのIPアドレス。BRのアドレス情報は「がとらぼ」では書かないが、ググれば見つかる筈。
DiscoverPathMTU=trueは、Path MTU Discoveryの自動検出を「あり」にしたつもり。これの動作は確認できていない。
最後のEncapsulationLimit=noneは以前のスクリプトでは ip -6 tunnel・・・ encaplimit none の最後の部分に相当。

これで、トンネルが掘れる。

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether ??:??:??:??:??:?? brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.10/24 brd 192.168.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link 
       valid_lft forever preferred_lft forever
3: enxa0cec81818aa: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether ??:??:??:??:??:?? brd ff:ff:ff:ff:ff:ff
    inet6 24xx:自動で割り当てられたIPv6アドレス/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 2591609sec preferred_lft 604409sec
    inet6 CEのIPv6アドレス/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::yyyy:yyyy:yyyy:yyyy/64 scope link 
       valid_lft forever preferred_lft forever
4: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000
    link/tunnel6 :: brd ::
5: v6ptnl0@enxa0cec81818aa: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1460 qdisc noqueue state UNKNOWN group default qlen 1000
    link/tunnel6 CEのIPv6デバイス peer BRのIPv6アドレス
    inet6 fe80::zzzz:zzzz:zzzz:zzzz/64 scope link 
       valid_lft forever preferred_lft forever

システムを再起動してから ip addr を実行。いつの間にか存在するip6tnl0は以前の記事でも書いたけどIPv4 over IPv6トンネルを作ると勝手に出来るもので、これは無視。設定ファイルで指定したトンネルデバイス(この記事の例ではv6ptnl0)が出来ていることを確認。ip addrでなくifconfig -aを実行した時ロケールが日本語だと「不明なネット」とか表示されるのは無視してよい。
v6ptnl0(名前は設定に書いたもの)が求めているもの、これがVNE側のNICに出来ていること(@enxa0cec81818aaの部分)。CEとBRのアドレスが入っていてトンネルとして正常に作成されていることを確認する。(実際にはこれを見ただけで正常か判らないかもだけど)

DS-Liteと異なりMAP-Eはトンネルが出来ただけだとルーターとして期待される通信はできないのでiptablesを動かす。
以前のmap.shの TUNDEV='ip6tnl1' を 今回の名称に変更する。TUNDEV='v6ptnl0'。
ip -6 hogeの2行、ip link hogeの2行、route hogeの2行、計6行を削除またはコメントにしてシステム起動後に実行。要するにiptables関連の部分だけ残したスクリプトにして実行。

map.shを実行するとルーターとして普通に動いている筈。

  1. NetworkManager(OS初期状態)を使ってLAN側と通信可能で、VNEのネットワーク側とIPv6でつながることを確認。
  2. ネットワークの情報をメモる。
  3. systemd-networkdでLAN側、VNE側の両方と接続できる設定を作る。
  4. NetworkManagerを無効化しsystemd-networkdを有効化する。
  5. LAN側と通信可能で、VNEのネットワーク側とIPv6でつながることを確認。
  6. メモったネットワーク情報からMAP-Eのためのアドレス等を作成する。
  7. systemd-networkdでトンネル用の設定を作る。
  8. トンネルが正常に作成されることを確認する。
  9. map.shのiptables部分だけを実行。(要iptables)
  10. IPv4のルーターとしての動作を確認。

段階を設定して各段階で動作確認することが大事。何もかも1度にしようとするとIPv4のルーターとして動作しないとなったときにどこが間違っているのか探しにくい。

NanoPi NEO3のプラスチックケース入りは放熱が下手くそなのでアイドル状態でも80℃以上(室温25℃)これはArmbianでSoCクロックが1.5GHzのとき。LinuxではガバナーがondemandならSoCがアイドルならクロックが下がるものだと思っていたけど、ステージがWIPのArmbianではアイドルでも基本1.5GHzでSoCが忙しいときに時々1.008GHzくらいまで落ちる。クロックの変化の仕方としては逆だと思うし温度が急上昇したわけでもないのになぜクロックが下がるのかは判らない。ただ、このクロックの動きのせいなのかは判らないが、ルーターとしての動作がスムースだったりガックガク(停まった?)になることが多々ある。1.008GHzでクロック固定したところ、温度は70℃(風を当てると60℃)に下がり、遅くなったり速くなったりもなくなったような・・・

ポートマッピングにパケットフィルタnftablesを使う

$ sudo iptables --version
iptables v1.8.2 (nf_tables)

iptablesのバージョンを確認して上の例のようにカッコの中にnf_tablesと表示されたらiptablesを使っているつもりで既にnftablesを使っている。カッコが無いなら本来のiptablesを使っている。

$ sudo apt install nftables

nftablesのパッケージをインストール。nftablesの設定ファイル(自動で読み込まれるルールファイル)は /etc/nftables.conf 。この /etc/nftables.conf が実行可のパーミッションになっていることを確認しておく。

/etc/nftables.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#!/usr/sbin/nft -f

flush ruleset

table inet filter {
        chain input {
                type filter hook input priority 0;
        }
        chain forward {
                type filter hook forward priority 0;
        }
        chain output {
                type filter hook output priority 0;
        }
}
パッケージインストール直後の未変更状態ならこんな感じ。
iptables部分だけに書き換えたmap.shの最後の行がnftablesでは互換性がない部分があるので修正。(問題なく動くけど)
iptables -t mangle -o $TUNDEV --insert FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

map.shを実行。
ルーターとして機能することを確認。

$ sudo nft list ruleset

map.shで適用したiptablesのルールをnftablesのルール書式で表示。

この内容を/etc/nftables.confの後に追記する。もしくは既存のtable inet filterは要らないのでflush rule set の次の行から最後までを消してから追加。
chain PREROUTINGの中にある counter packets xx bytes xxxx meta の部分を15行全てで削除。
chain POSTROUTINGの中にある counter packets xx bytes xxxx の部分を45行全てで削除。
chain OUTPUTの中にあるcounter packets xx bytes xxxx meta の部分を15行全てで削除。
つまり、
%s/counter.*meta//g
%s/counter.*snat/snat/g
エディタで置換2回で終わり。綺麗じゃないけど置換無しでも動くのは動く。
置換対象のテーブルのtable ip natのルールだけなら nft list table ip nat でも。こちらは置換は要らないが、当然table ip natのルールしか見えないので table ip mangle のルールも足す必要がある。テーブルリストを見るなら nft list tables

/etc/nftables.conf (変更後の例)
#!/usr/sbin/nft -f

flush ruleset

table ip nat {
        chain PREROUTING {
                type nat hook prerouting priority -100; policy accept;
                numgen inc mod 15 0  mark set 0x11 
                numgen inc mod 15 1  mark set 0x12 
                numgen inc mod 15 2  mark set 0x13 
                numgen inc mod 15 3  mark set 0x14 
                numgen inc mod 15 4  mark set 0x15 
                numgen inc mod 15 5  mark set 0x16 
                numgen inc mod 15 6  mark set 0x17 
                numgen inc mod 15 7  mark set 0x18 
                numgen inc mod 15 8  mark set 0x19 
                numgen inc mod 15 9  mark set 0x1a 
                numgen inc mod 15 10  mark set 0x1b 
                numgen inc mod 15 11  mark set 0x1c 
                numgen inc mod 15 12  mark set 0x1d 
                numgen inc mod 15 13  mark set 0x1e 
                numgen inc mod 15 14  mark set 0x1f 
        }

        chain INPUT {
                type nat hook input priority 100; policy accept;
        }

        chain POSTROUTING {
                type nat hook postrouting priority 100; policy accept;
                oifname "v6ptnl0" meta l4proto icmp mark 0x11 snat to IPv4アドレス:6xxx-6xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x11 snat to IPv4アドレス:6xxx-6xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x11 snat to IPv4アドレス:6xxx-6xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x12 snat to IPv4アドレス:10xxx-10xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x12 snat to IPv4アドレス:10xxx-10xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x12 snat to IPv4アドレス:10xxx-10xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x13 snat to IPv4アドレス:15xxx-15xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x13 snat to IPv4アドレス:15xxx-15xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x13 snat to IPv4アドレス:15xxx-15xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x14 snat to IPv4アドレス:19xxx-19xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x14 snat to IPv4アドレス:19xxx-19xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x14 snat to IPv4アドレス:19xxx-19xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x15 snat to IPv4アドレス:23xxx-23xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x15 snat to IPv4アドレス:23xxx-23xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x15 snat to IPv4アドレス:23xxx-23xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x16 snat to IPv4アドレス:27xxx-27xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x16 snat to IPv4アドレス:27xxx-27xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x16 snat to IPv4アドレス:27xxx-27xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x17 snat to IPv4アドレス:31xxx-31xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x17 snat to IPv4アドレス:31xxx-31xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x17 snat to IPv4アドレス:31xxx-31xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x18 snat to IPv4アドレス:35xxx-35xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x18 snat to IPv4アドレス:35xxx-35xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x18 snat to IPv4アドレス:35xxx-35xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x19 snat to IPv4アドレス:39xxx-39xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x19 snat to IPv4アドレス:39xxx-39xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x19 snat to IPv4アドレス:39xxx-39xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x1a snat to IPv4アドレス:43xxx-43xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x1a snat to IPv4アドレス:43xxx-43xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x1a snat to IPv4アドレス:43xxx-43xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x1b snat to IPv4アドレス:47xxx-47xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x1b snat to IPv4アドレス:47xxx-47xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x1b snat to IPv4アドレス:47xxx-47xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x1c snat to IPv4アドレス:51xxx-51xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x1c snat to IPv4アドレス:51xxx-51xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x1c snat to IPv4アドレス:51xxx-51xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x1d snat to IPv4アドレス:56xxx-56xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x1d snat to IPv4アドレス:56xxx-56xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x1d snat to IPv4アドレス:56xxx-56xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x1e snat to IPv4アドレス:60xxx-60xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x1e snat to IPv4アドレス:60xxx-60xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x1e snat to IPv4アドレス:60xxx-60xxx
                oifname "v6ptnl0" meta l4proto icmp mark 0x1f snat to IPv4アドレス:64xxx-64xxx
                oifname "v6ptnl0" meta l4proto tcp mark 0x1f snat to IPv4アドレス:64xxx-64xxx
                oifname "v6ptnl0" meta l4proto udp mark 0x1f snat to IPv4アドレス:64xxx-64xxx
        }

        chain OUTPUT {
                type nat hook output priority -100; policy accept;
                numgen inc mod 15 0  mark set 0x11 
                numgen inc mod 15 1  mark set 0x12 
                numgen inc mod 15 2  mark set 0x13 
                numgen inc mod 15 3  mark set 0x14 
                numgen inc mod 15 4  mark set 0x15 
                numgen inc mod 15 5  mark set 0x16 
                numgen inc mod 15 6  mark set 0x17 
                numgen inc mod 15 7  mark set 0x18 
                numgen inc mod 15 8  mark set 0x19 
                numgen inc mod 15 9  mark set 0x1a 
                numgen inc mod 15 10  mark set 0x1b 
                numgen inc mod 15 11  mark set 0x1c 
                numgen inc mod 15 12  mark set 0x1d 
                numgen inc mod 15 13  mark set 0x1e 
                numgen inc mod 15 14  mark set 0x1f 
        }
}
table ip mangle {
        chain PREROUTING {
                type filter hook prerouting priority -150; policy accept;
        }

        chain INPUT {
                type filter hook input priority -150; policy accept;
        }

        chain FORWARD {
                type filter hook forward priority -150; policy accept;
                oifname "v6ptnl0" meta l4proto tcp tcp flags & (syn|rst) == syn  tcp option maxseg size set rt mtu
        }

        chain OUTPUT {
                type route hook output priority -150; policy accept;
        }

        chain POSTROUTING {
                type filter hook postrouting priority -150; policy accept;
        }
}
ポート番号など異なる部分はあるかもだけどこんな感じになる筈。
$ sudo systemctl enable nftables.service

nftablesパッケージをインストールした場合は有効化されていない可能性があるので実行しておく。既に有効化されていても影響無し。

次回からはシステム起動時にnftablesが自動的にこのルールを読み込むのでmap.shを自動実行する設定にしていたならそれを消す。
動作確認としてシステムを再起動してルーターとして機能することを確認。

なお、この記事では「ルーターとして機能することを確認」とか書いてるけど、LANの中の端末がIPv4でインターネット側と通信したいときにこいつがそのルーターであることを勝手に知ってはくれない。それぞれの端末にデフォルトゲートウェイの設定を固定で書くか、DHCPサーバのルーターオプションに指定するか。これは別途行ってください。

これで、気分は一新。ただし、設定の書き方が違うだけで実際は何も変わってないんじゃないかという気はしないでもない。もしかしたらnftablesの設定の書き方によってはフィルタリング処理が高速化したり違いを出せるのかもしれないけど、nftables本来の設定の書き方を見るのも触るのも今回が始めてなので良く解ってない。

関連記事:

コメント: NanoPi NEO3をv6プラスのルーターにする systemd-networkd + nftables

  1. すでに同じようなことをされていたのですね。気付かなくてスミマセン。「がとらぼ」へのリンクもありがとうございます。
    nftablesに変更してからv6プラスのポート240個が適切に使われているのか自信がなかったのですが、その辺りも書かれていたので参考にさせて貰います。nftablesのカウンターを使うと使われていないポートグループが判る?
    コメント欄はWordPressの標準機能そのままなのでマルチバイト文字のドメインはpunyで書かないと弾かれるかも。

コメントは締め切られています。