Linux・systemd・nftables でv6プラス・OCNバーチャルコネクト用ルーターを作る(2024年版)

[この記事](https://qiita.com/kakinaguru_zo/items/2764dd8e83e54a6605f2) の2021年のソフトウェアを用いた書き直しです。IPv4通信をするときにPPPOEを使うと遅いですが、IPv4通信をIPv6通信に包んで送ると速くなります。IPv4通信をIPv6で包むやり方には幾つがありますが、Biglobe, OCNバーチャルコネクト, v6プラスなどで使われているMAP-E方式を提供するISPのために、家庭内のIPv4通信をIPv6に変換して高速化するルーターをLinux・systemd・nftablesのみを用いて作る手順を示します。Debian 11 BullseyeやUbuntu 21.04 Hirsuteで使えます。`systemd` バージョン247以降が必要です。(自宅のラズパイで Debian 12 Bookwormで以下の方針でルーター作って問題なく運用できています(2024年7月))
Debian trixie (Debian 13) にしたらsystemdが新しくなり設定が変わっていたので更新した（2024年12月29日）

# 前提と目標
* Linux機器には一つだけネットワークインターフェースがありその名前は `eth0` で、そのIPv4アドレスは`192.168.1.2` に固定して設定する
* IPv6パケットをISPとやり取りするIPv6ルーター（普通はNTTのレンタルルーター(HGW)）がLinux機器とは別にあり、家庭内の機器にIPv6アドレスをIPv6 RAやDHCPv6で配布する。家庭内のIPv6デフォルトルートはIPv6ルーターになっている。~~IPv6ルーターのIPv4アドレスは`192.168.1.1`に固定されている~~
* [フレッツ・ジョイント](https://note.com/noblehero0521/n/n0265f3ac371b) を __使っていない__
* IPv4デフォルトルートをLinux機器に設定し、家庭内のIPv4パケットをLinux機器に集めて、Linux機器はIPv4パケットとIPv6パケットを相互に変換する
* この変換を行う仮想ネットワークの名前を `ip6tnl1` に設定する
* Linux機器の上でDNSキャッシュサーバーを稼働させてDNS問い合わせをv6アドレスを持つDNSサーバーに送らせる。これはNAT変換ポートの枯渇を避けるためである (いわゆるニチバン対策の一種)
* Linux機器はDHCPv4サーバーを稼働させ、eth0に接続された機器のIPv4デフォルトルーターとDNSサーバーとしてLinux機器を設定させる
* それ以外のDHCPv4サーバーは停止する
* NTTレンタルルーターのPPPoE接続は残してもよいし、すべて解除してもどちらでもいいです

# systemd-networkd によるネットワークの設定
## ネットワーク設定を行う他のソフトウェアのアンインストール
`apt-get --autoremove remove dhcpcd5 ifupdown network-manager netplan.io networkd-dispatcher`

## eth0 の設定
`$CE` は https://qiita.com/kakinaguru_zo/items/2764dd8e83e54a6605f2#%E8%AC%8E%E3%81%AE%E3%82%B5%E3%82%A4%E3%83%88-httpipv4webfc2commap-ehtml-%E3%81%A7ipv6%E3%81%A7%E3%81%8F%E3%82%8B%E3%82%93%E3%81%A0ipv4%E3%83%91%E3%82%B1%E3%83%83%E3%83%88%E3%81%AE%E9%80%81%E3%82%8A%E5%85%88%E3%81%AA%E3%81%A9%E3%82%92%E8%AA%BF%E3%81%B9%E3%82%8B の手順に従い予め調べて以下に記入する

```config:/etc/systemd/network/eth0.network
[Match]
Name=eth0

[Link]
RequiredForOnline=routable

[Network]
Tunnel=ip6tnl1
IPForward=ipv4
# ↑新しい systemd だと 「IPv4Forwarding=yes」にしないとダメ
LinkLocalAddressing=ipv6
IPv6AcceptRA=yes
DHCP=ipv6
DHCPServer=yes

[Address]
Address=192.168.1.2/24

[Address]
Address=$CE/64

[DHCPServer]
EmitDNS=yes
DNS=192.168.1.2
EmitRouter=yes
PoolOffset=129
PoolSize=40

[PFIFOHeadDrop]
PacketLimit=1024
```

## ip6tnl1 の設定
`$BR` は前述の `$CE` と同じ手順で調べて以下に記入する

```config:/etc/systemd/network/ip6tnl1.netdev
[NetDev]
Name=ip6tnl1
Kind=ip6tnl

[Tunnel]
Mode=ipip6
Local=$CE
Remote=$BR
DiscoverPathMTU=yes
EncapsulationLimit=none
```

`$IP4` を前述の `$CE`, `$BR` と同じ手順で調べて以下に記入する

```config:/etc/systemd/network/ip6tnl1.network
[Match]
Name=ip6tnl1

[Link]
RequiredForOnline=routable

[Network]
# 新しい systemd だと 「IPv4Forwarding=yes」を書かないとダメ（パケット転送の可否をインターフェースごとに設定するように変わった
BindCarrier=eth0
DefaultRouteOnDevice=yes
DHCP=no
IPv6AcceptRA=no
LinkLocalAddressing=no
MulticastDNS=no
LLMNR=no

[Address]
Address=$IP4/32
```

## systemd-networkd の自動起動
`systemctl enable systemd-networkd`

# DNS キャッシュサーバーの設定

[systemd でDoT (DNS over TLS) と DNSSEC に対応したDNSキャッシュサーバーを作る](https://qiita.com/kakinaguru_zo/items/6a0bd4f43bf0ee4ea85f) を参照してほしい。 DNSとDHCPが一体になっている dnsmasq などを用いてもよいが、その場合上記 `eth0.network` の `DHCPServer=` を `no` に変える。 

# nftables の設定
1. https://qiita.com/kakinaguru_zo/items/2764dd8e83e54a6605f2#%E3%81%8A%E3%81%BE%E3%81%91%EF%BC%91-systemd-%E3%81%A8-nftables--usrsbinnft%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89-%E3%81%AB%E4%B8%8A%E8%A8%98%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E5%88%9D%E6%9C%9F%E5%8C%96%E3%82%92%E8%B5%B7%E5%8B%95%E6%99%82%E3%81%AB%E3%82%84%E3%82%89%E3%81%9B%E3%82%8B%E6%96%B9%E6%B3%95 に従って `nftables.conf` を作成し `/etc` に置く
1. `apt-get install nftables`
1. `systemctl enable nftables`
            
# 再起動する
これで上手くいくはず