自宅の10G回線をフル活用するルータを作った


ストレージサーバーが遅すぎる

最近、自宅のストレージサーバーがボトルネックになってきた。
大容量のデータを扱うことが多くなって、1GbEじゃもう無理。
ProxmoxのVMをバックアップするだけでまる1日かかると言った状態だった。 Nextcloudで動画ファイルをやり取りするのも遅くて段々としんどくなってきた。

そうだ、10Gにしよう!

思えば家のネットワークは外向けは10G契約だった。 ではまずはとりあえず、宅内のストレージサーバーと通信する部分だけは10Gにしてしまおうと思った。

やろうとしたところ、いろんなことがしたくなってしまった。

  • 今のL2スイッチだと10G対応してるのないから新しいのいれるか
  • Aristaのスイッチが安く手に入る!10Gだし買おう
    • Aristaのスイッチは10G/40G対応だから将来40Gも見据えられる
    • AristaのスイッチはL3もあつかえる!楽しいね
  • L3にするなら既存のルータとVLANいい感じに扱うの面倒そうなのでは?
  • ルータも10Gにして、変な構成は全部見直そう
  • L2のManagementスイッチも廃止できるならしてしまおう!

あれ・・・?気づいたら宅内からインターネットまで全部10G化する計画になってた。
何はともあれ3連休だし、やってみよう! ただ、Minecraftサーバーとして貸し出しをしているし、最低限のダウンタイムでやるぞ!!

ということでやってみた。

多段NATという地獄

当時のネットワーク構成はこんな感じだった:

graph TB
    Internet[インターネット<br/>enひかり 10G v6プラス]
    Buffalo[Buffalo WXR-5950AX12<br/>MAP-E処理・10G対応]
    TPLink[TP-Link TL-ER7206<br/>VLAN制御・1Gbps]
    TPLinkSwitchA[TP-Link L2 Management スイッチ<br/>+ 各種VLAN]
    
    Internet --> Buffalo
    Buffalo --> TPLink
    TPLink -->|ボトルネック!!!| TPLinkSwitchA
    
    style TPLink fill:#ff9999

Buffalo自体は10G対応でMAP-Eもちゃんと動いてた。
これの下にTP-Link TL-ER7206を置いてVLAN制御していたが、こいつがギガビット(1Gbps)しか対応してない
うちの負の遺産。

speedtest.netで測ると850〜900Mbpsで頭打ち。
せっかく10G契約があるなら10Gで通信できたほうが嬉しいよね。

さらにIPv6の配布が全然うまくいかない。
Buffaloのルータは配下に /64 でしか配布しないようだった。
実際は /56 でもらっているのに。
各VLANにRAでプレフィックス配ろうとしても、多段構成だと動かない。
結局Buffaloのルータから、各VLAN用にTP-Linkのルータに有線LANを引いている状態だった。
流石にそろそろこれはやめたいよねと思っていたところだった。

Linuxでやればいいじゃん

「あれ?VLANの処理ってL3スイッチがあれば全部Aristaでできるよね?」
「じゃあルーターは純粋にMAP-Eとルーティングだけでいいんじゃない?」
「全部Linuxでやっちゃえば自由度高いし!」 「友人はOpenWRTでMAP-Eなんかを10Gでやっているし」

ということで、BuffaloとTP-Linkを撤去して自作ルーターに置き換える計画がスタート。

OpenWRTで楽をしようとした

最初は「OpenWRTなら簡単でしょ」って思ってた。
x86_64版をダウンロードして、いざインストール!

試練1:ddが焼けない

dd if=/root/openwrt-24.10.4-x86-64-generic-ext4-combined-efi.img.gz of=/dev/sdb bs=4M status=progress

これはそれはそう。
最初はUbuntuDesktopのLiveUSBから起動しているのが悪いのかと思ってあれ??ってやってた。
zcatで.gzを展開してからddすればいいだけ。
流石にアホすぎた。寝たほうがいい。

正解はこれ。

zcat openwrt-24.10.4-x86-64-generic-ext4-combined-efi.img.gz | dd of=/dev/sdb bs=4M status=progress

試練2:SAS SSDが見えない

とりあえず先の手順でインストールはできた。
ただ、なぜかddで焼いたディスクが認識されなかった。
よくわからないが、おま環っぽい。
仕方ないので、SAS SSDをSATA SSDに変えてインストール。
相変わらずダメだった。
色々試したら、ポート0がうまく動かないっぽい。
SSDをSATA SSDをポート1に挿したら認識された。

試練3:GRUBで止まる

ともかく、ポート1のSATA SSDにインストール。
GRUBは起動する!やったね!

openwrt_error

…と思ったら「メインパーティションが見つかりません」

Waiting for root device PARTUUID=4c5af05c-d0cb-83ed-2c0f-30276dc7a102...

え〜〜〜〜〜〜〜。
どうも、メインのパーティション見当たらないよう。
調べたらRAIDコントローラー(LSI SAS2008)のドライバがOpenWRTに含まれてなかった。

試練4:USBなら動くという皮肉

試しにUSBメモリにOpenWRTをインストールしたら普通に動いた。
流石にUSBメモリで運用は何かなぁ…
さらに、うまく動いても、Broadcomの10GbE NIC(BCM57810)がOpenWRTで認識されていなかった。
だめだー。

Debianという選択

「うーん!!OpenWRTでできるならLinuxでできるやろw」
「どうせNATとパケットフォワードだけだしw」

Debian 13(trixie)をインストール。
全部認識した。RAIDコントローラーもSAS SSDも10GbE NICも。
やっぱり普通のLinuxがいいという。

ハードウェアは友人からのプレゼント

実は今回使ったサーバー、友人が処分に困ってたやつ。
「いらないから持ってて〜」って言われて、合計4台もらってきた。
なんでいらない1Uサーバーを4台も調達したんだろうね。

1台目:今回のルーター
2台目:Grafana + Prometheus 監視サーバー
3,4台目:廊下に放置

友人の推しポイントは「10G SFP+が2つついてるよ!おすすめ!」だった。

スペック:

  • CPU: Intel Xeon E3-1265L v3
  • RAM: 32GB
  • NIC: Broadcom BCM57810 (10GbE SFP+ x2)
  • SSD: 128GB x2 (SATA、RAID1)

10GbE NICがついてるのが最高。追加投資ゼロで10G環境が作れる。
やったね。

SFP+モジュールの相性問題

というわけで普通にDebianをインストールした。
しかし、実はここでもハマった。
最初はArista純正のSFP+モジュールを両側に挿してた。

graph LR
    subgraph sg1 ["構成1:リンク不安定"]
        S1[サーバー] -. "Arista SFP+ ✖ Arista SFP+" .- SW1[Aristaスイッチ]
    end
    
    style S1 fill:#f9f9f9,stroke:#333,stroke-width:2px
    style SW1 fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    
    linkStyle 0 stroke:#d32f2f,stroke-width:3px,stroke-dasharray: 5, 5

この状態だとリンクアップしなかった。
Aristaの方ではどうも何のパケットも受け取ってないと言った状態、ルーターの方ではLink Down。
SFPモジュールはベンダーロックインが多いよと友人に言われていたので、とりあえず家に他にあったAvagoのSFP+モジュールを挿してみた。

graph LR
    subgraph sg2 ["構成2:AVAGO利用"]
        S2[サーバー] -- "AVAGO SFP+ <---> Arista SFP+" --- SW2[Aristaスイッチ]
    end
    
    style S2 fill:#f9f9f9,stroke:#333,stroke-width:2px
    style SW2 fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
    
    linkStyle 0 stroke:#2e7d32,stroke-width:3px

変えたらうまくLinkUpした!ベンダーロックイン微妙…

IPv6

まずIPv6から設定。これは特に問題なかった。

# IPoEでIPv6接続
ip -6 addr add 240b:xx:xxxx:xxxx::xx/64 dev eno1
ip -6 route add default via fe80::xxxx dev eno1

# Cloudflare DNSにping
ping6 2606:4700:4700::1111
# 通った!

IPv6はすんなり疎通。1.1.1.1のv6版にも問題なくアクセスできた。
なぜかAI(Claude sonnet 4.5)はやたらGoogleのDNSにpingを飛ばせとずっと言ってた。
ここまでは見積もり通り。
事前に聞いていた話通り、enひかりのDHCPv6-PDで/56をもらえた。
IPv6 Done!

本命のMAP-E

IP範囲の計算ができない

MAP-E(v6プラス)の設定で最初につまづいた。
自分のIPv4アドレスとポート範囲を計算する必要がある。

enひかりからDHCPv6-PDで/56という巨大なプレフィックスをもらえる(うれしい)。
でも、そこからMAP-E用のIPv4アドレスを計算するのが…

「とりあえず雑にAIに計算してもらおう」

Claude Sonnet 4.5とGemini 3 ProにIP範囲を投げて計算しておいてと言っておいた。
Claudeはどういうわけか、自分は間違ってない、ISPのバグだという主張をしてくる。
GeminiはGeminiで、聞くたびに違う答えを出してくる。
AIはだめ。

結局 https://ipv4.web.fc2.com/map-e.html を使って計算した。

MTU/MSS問題

MAP-Eトンネル作って、動いた!と思ったら…

  • PCは普通に使える
  • スマホがめちゃくちゃ遅い
  • Minecraft(Modrinth)のダウンロードが全く進まない
    • Modはダウンロードできたようだが、Minecraft本体のダウンロードが進まない

なんで?

調べてみたら、MAP-EトンネルのMTUが1460なのに、外部サーバーは1500で送ってくる。
でもICMPのPacket Too Bigが届かないから、永遠にパケットがドロップし続ける。

解決策はTCP MSS Clamping:

# nftables設定
#!/usr/sbin/nft -f

flush ruleset

table ip filter {
    chain forward {
        type filter hook forward priority filter; policy drop;
        
        # MSS書き換えを最初に!(これ重要)
        tcp flags syn tcp option maxseg size set 1412
        
        # その後で通信許可
        ct state established,related accept
        iifname "eno2" oifname "map-wan" accept
    }
}

最初、acceptの後にMSS書き換えを書いてて効かなかった。
nftablesは上から順番に処理されるということを学んだ。

これでMinecraftもダウンロードできるようになったし、スマホも速くなった!

10Gbpsチューニング

MAP-Eの設定が完了したのでとりあえず、speedtest (ookila) で測定してみた。

IPA CyberLab (400G) で測定:

  • Download: 5479 Mbps
  • Upload: 1723 Mbps

speedtest_ipa_1

思ったよりのぼりが出てなかった。
これはNTTのネットワークが混雑している可能性もあったが、ルーターのチューニングでなんとかできるならやってみる。

CPU1コアだけ100%

htopで見たらCPU1コアだけ100%になってた。
ネットワーク処理が1コアに集中してる。

XPS(Transmit Packet Steering)で全コアに分散:

# 8コアの場合は0xff
mask=$(printf '%x' $(( (1 << $(nproc)) - 1 )))

# 全TXキューに適用
ls /sys/class/net/eno1/queues/tx-*/xps_cpus | \
    while read f; do echo $mask | sudo tee $f > /dev/null; done

リングバッファも最大に

# 現在の設定確認
ethtool -g eno1
# RX: 255 → これを最大に

# 最大値(4078)に設定
ethtool -G eno1 rx 4078

なるほど。

結果

IPA CyberLab(400G)で再測定

  • Download: 6277 Mbps
  • Upload: 6794 Mbps

speedtest_ipa_1

時間が遅くなったので混雑が解消しただけかもしれないが、のぼりが大幅に改善した。(気がする)

IPv6配布も完璧に

enひかりのDHCPv6-PDで/56をもらって、各VLANに/64ずつ配布。
TP-Linkでは全然できなかったことがあっさり実現。

graph LR
    subgraph "IPv6プレフィックス配布"
        ISP[enひかり<br/>240b:xx:xxxx:af00::/56]
        Router[Debianルーター]
        V1010[VLAN 1010<br/>...af10::/64]
        V1020[VLAN 1020<br/>...af20::/64]
        V1030[VLAN 1030<br/>...af30::/64]
        
        ISP -->|DHCPv6-PD| Router
        Router --> V1010
        Router --> V1020
        Router --> V1030
    end

各VLANで独立したRA配信ができるようになって、すべてのデバイスが正しいIPv6アドレスを取得できるようになった。

まとめ

自宅のストレージサーバー間の通信速度を改善するのが目的だったが、横道にそれすぎて最終的にルーターを自作することになってしまった。
これが1日でできるので、やっぱりLLMは偉大。 わけのわからないネットワーク構成から解放されたのが一番の収穫だった。
OpenWRTでできたら良かったのだが、結果的にDebianでうまくいったので良しとする。 みんなもDebianでLinuxルーターを作ると何でもできるので良いよ。

まとめ

当初はストレージサーバー間の通信速度を改善するだけの予定だったが、気づけばルーターの自作という大工事になってしまった。典型的な「やりすぎエンジニアリング」かもしれないが、結果的には大正解だった。(かもしれない…)
LLMの助けもあって、この規模の作業が実質1日で完了したのはすごいと思った。複雑怪奇な多段NAT構成から解放され、シンプルで高速なネットワークが手に入ったことが何よりの収穫となった。 OpenWRTで簡単に済ませたかったが、ハードウェアの相性問題でDebianに切り替えることに。しかし結果的にはこれうまくいき、細かいチューニングや将来の拡張性を考えると、むしろDebianで良かったと思える。(運用時に死ぬかも) Debianでルーター作ると本当に何でもできて楽しい。ハマりどころは多いけど、そこも含めて楽しめる人にはおすすめ。10G環境で遊びたい人は、週末の暇つぶしにでも試してみるといいかも。(がんばってね。)

感想

今回、多段NAT構成からDebianルーター1台構成に変えられたことでいろんなメリットが得られた。

  • 900Mbps -> 6Gbpsに高速化
    • (でも外向けに別にこんな帯域使わないんだよな。と)
  • VLANごとのIPv6配布が実現
  • nftablesで自由にルール書ける
    • うれしいね。

設定はほとんどGemini 3 Proに手伝ってもらった。
とりあえず色々設定してもらって、後から環境について説明されるという状態で本当にいいのか…?という状態ではある。

次はWireGuard統合して、外から自宅VLANにアクセスできるようにする予定。
ちなみに、このブログは今回作ったネットワークの中にあるサーバーで動いているknativeだったりする。
まだまだ、がんばるぞい。