IPv6を安全に扱えるホームルーターをNanoPiで自作する

Posted on Dec 3, 2023

この記事はしょぼねこ Advent Calendar 2023 3日目の記事です。
NanoPiとDebianでルーターを作ったというお話です。

動機

現在、IPv4アドレスへの枯渇問題対策としてIPv6というものが登場し徐々に広まっています。が、このIPv6は単にアドレス空間を広げただけではなくインターネット原理主義的なアンチNA(P)T思想の元、全デバイスがMacアドレスを元にしたグローバルIPアドレスを持つという仕様が混ざっています。結果として大きく分けて2つの以下の問題が発生する訳です

  • プライバシー上の問題: 全デバイスがMacアドレスを元にしたデバイス固有のIDを接続先のサーバーに公開することになるためデバイスレベルでのトラッキングが非常に簡単になる(ランダムアドレス機能で回避できるがランダムアドレスをデフォルトでは使わないデバイスやOSも多い)
  • セキュリティ上の問題: IPv4のような「内側と外側」という概念がない(ローカルリンクアドレスに相当するアドレスはありますが全デバイスがグローバルアドレスを持つことが前提)なので現にそれなりに存在するIPv6のパケットフィルタリングをまともに行わないルーターに接続されたデバイスは各デバイスのファイアウォールでしか保護されず、脆弱な設定のデバイスはインターネットからアクセスし放題になる(特にIoT機器で問題になる(らしい))
    • NATは厳密にはセキュリティ機能ではないのはそうですが、一部の市販ルーターではIPv6のパケットフィルタリングがまともに設定されておらず、結果として各デバイスがローカルアドレスしか持たないIPv4環境の方が安全(無難)であることは間違いない

でこの様々な問題を解決するスーパールーター™を自作して二重目のルーターにしてしまおうという訳です。
具体的には

  • WAN側のインターフェースではランダムアドレスを使う
  • プライバシーとセキュリティ™の確保のため全デバイスがルーターのランダムアドレスで通信するようにNAT66を導入する
  • パケットフィルタリングもちゃんとやる
  • ついでにDoHを使うようにしてDNSも安全にする

みたいな感じでやっていきます。ここまでのことをやってくれる市販家庭用ルーターは存在しません(当社調べ - 見つけたらぜひ教えてください)

注意とおまけ

これだけ偉そうに語っておいて何ですがこの資料には

IPv4のNAPTに相当するNAT66は標準化されていないが実装がある状態

とありNAT66は実はIPv6の仕様的には正式ではないものの必要とされるシーンが多々あるためip6tablesで実装されてる状態みたいです。今回使った方法はGL-iNetのルーターのNAT66機能を元にしています。
また当然ながらこの方法で作ったルーターを使ったからといってIPv4環境では問題にならなかったセキュリティリスクが完全に解消できる訳ではありません。(サーバーを置いてるならSSRFの対策とか不正なルーター広告対策とか ←検証してないので詳しくは知らんけど)

長ったるい前置きは置いておいて登場人物から紹介します。

登場人物

NanoPi R5S

2.5GbpsのNIC x2と1GbpsのNICが付いて1万円ちょいという非常にコスパの良いSBCです。ラズパイと比較してCPUとメモリの性能は微妙ですがルーターやリバースプロキシには十分すぎる性能です。

Debian + networkd

今回は公式のファームウェアではなく有志が公開している普通のDebianを使います。ネットワーク周りは普通に使う分には/etc/network/interfacesの編集で十分ですが今回はnetworkd内臓のDHCPサーバーとIPv6RD(ルーター広告)機能を使いたかったのでDebian標準搭載のnetworkdを使います。networkdを使わないLinuxの場合やそもそもLinuxでない場合はAdGuard HomeのDHCPサーバー機能(IPv6使いたい場合は +radvd)で代替すると楽かもしれません。
ちなみにNanoPiの公式ファームウェアにOpenWRTベースのものがあるので単純に多機能ルーターを建てるだけならこっちを使ったほうが確実で楽です。が今回はネットワークの勉強も兼ねて敢えてDebianで構築してます。

LanceLight

私がGoで開発したnftablesのレンダラーです。firewalldやufwの代替として機能します。

NanoPiの外観

撮影日時埋め込むの切り忘れてギリギリで書いたことがバレバレですがご容赦ください 全体像はこんな感じです。
WANというインターフェースは1Gbpsなので今回は使いません

USBがある面
2.5インチSSDとノートパソコン(Yoga770)との比較

ネットワーク構成

  • LAN1にプロパイダ配布のルーターを接続し、WAN側とする
  • LAN2にはスイッチングハブを繋いでそこに自分のデバイスをぶら下げてLAN側にする
  • IPv6接続のセキュリティとプライバシーを確保するために、LAN1は一時ランダムアドレスを常に使用するようにすると同時にLAN2下の機器からのIPv6接続に関してはIPv4同様NATするようにする
  • LAN内の全てのデバイスがDoH (もしくはDoT)経由でNextDNSを使うようにする

networkdの設定

/etc/systemd/networkdに移動して以下の設定をぶち込みます

lan1.network(WAN側ネットワーク)

[Match]
Name=lan1

[Network]
Address=192.168.1.200/24
Gateway=192.168.1.1
DHCP=ipv6
IPv6DuplicateAddressDetection=1
IPv6PrivacyExtensions=yes

[DHCPv6]
# プロパイダのルーターから配布されたものを使わない
UseDNS=no
UseNTP=no
UseHostname=no

lan2.network(LAN側ネットワーク)

[Match]
Name=lan2

[Network]
Address=192.168.5.1/24
# https://ipinfo.io/bogon に載っている適当なアドレスが望ましいと思われるが仕様が定まってないせいか通信できないことがあるっぽい?
# GL-iNetのルーターではdd04:ff8b:d8b9::1/64になってた
Address=xxxx:xx:xxx:xxx:ff:f100::/64
# DHCPを受け付けない
DHCP=no
# DHCPサーバーとして振る舞う(DHCPv6には多分対応してない)
DHCPServer=yes
# IPv6のルーター広告を送る
IPv6SendRA=yes

[DHCPServer]
EmitDNS=yes
DNS=192.168.5.1

DoHの設定

resolvedの設定でDoHを指定しても良いんですが私はNextDNSの公式クライアントを使いました。resolvedでやる場合は/etc/systemd/resolved.confをNextDNSのダッシュボードに表示されるやつにすれば設定できます

nftablesの設定

自作nftablesレンダラーであるlance-lightを使います。ここではルート設定とLAN側に公開するポートを設定しています。

default:
  allowAllIn: false
  allowAllOut: true
  allowAllFwd: false
  allowPing: true
  enableIPv6: true
  enableLogging: true

ports:
# DNS
- port: 53
  allowIP: "192.168.5.0/24"
  allowInterface: "lan2"

# DHCP
- port: 67
  allowInterface: "lan2"

# 管理用SSH
- port: 22
  proto: "tcp"
  allowIP: "192.168.5.0/24"
  allowInterface: "lan2"

router:
  configAsRouter: true
  wanInterface: "lan1"
  privateNetworks: ["192.168.5.0/24", "xxxx:xx:xxx:xxx:ff:f100::/64"]
  lanInterfaces: ["lan2"]
  forceDNS: "192.168.5.1"

実際に動かしてみて

一応動くことは動きます。がまだDHCPv6に対応していないなど課題まみれなのでそのうちなんとかしたいと思っています。

まとめ

IPv6自体はだいぶ前からあります。しかし冒頭で述べた通りまともにパケットフィルタリングをしないルーターがあったり、ランダムアドレスを標準で使ったり使わなかったり、NAT66の仕様が標準としては定まってなかったり、DHCPv6やらRAやらIPアドレスを配布する仕組みが乱立していたりと色々面倒なのが現状です。それらの問題の全部ではなくとも少なくとも1部はここで紹介した方法で構築したルーターで多少マシになるはずです。
私個人の考えとして将来的にもIPv4は相当長らく使われ続けると思います。廃止できるほどIPv6非対応なデバイスや実装、ソフトが減るまでには相当時間がかかると思われるからです。GoogleやDuckDuckGoで「linux ipv6」と入れると一番上に「linux ipv6 無効化」という候補が出てくることからもなんとなく察せます。しかしこれからIPv6を使う機会が増えることもまた事実です。IPv6 OnlyなVPSを使えば費用をかなり削減できるなどのメリットもあります。

この機会にみなさんもぜひIPv6の設定を見直してみることをおすすめします。環境によってはデフォルトで使ってると少しリスクがある設定かもしれません。