OpenWrtで10Gルーターを自作してみた
今年から自宅の回線を光クロスへ移行したのでWAN LAN両方10G対応のルーターを買おうとしてたのですが、あまりにも高いので自作することにしました。
基本的にこちらの記事の通りに進めましたが、一部openwrtのバージョンや環境の違いがあったので手順を変えています。
用意したもの
Lenovo ThinkCentre M720q
ヤフオクでi5-8600Tとメモリ4GBが載ったものを購入
Intel Optane Memory 16GB
ストレージとして使用します。今や誰も存在を覚えていないであろうOptaneですが、SSDが高騰している昨今でも1000円程度で買える唯一のnvmeです。16GBあればOpenWrt動かすには十分ですからね。

Intel X520-DA2
10G対応のSFP+ NICです。アリエクで購入
ライザーカード
M720qのpcieスロットは独自規格のためライザーカードが必要になります。こちらもアリエクで購入
このライザーカードはいくつか世代があり、01AJ940が一番最新のものになります。
SFP+ to RJ45モジュール
SFP+のNICを使うならONUとルーター間の接続で1個は必要になります。
Broadcom BCM84891のチップが載った80Mのモジュールは比較的発熱しないらしいのでこちらを購入。
SFP DACケーブル
アリエクで購入。光ケーブルは取り回しがしんどそうなので銅にしました
実際にかかった費用は以下の通りです。アリエクのセールやクーポンを駆使したあとの金額ですのでご了承ください
| 機材 | 金額 |
|---|---|
| M720q Core i5-8600T 4GB | 11,000円 |
| Optane Memory 16GB | 558円 |
| Intel X520-DA2 | 2,740円 |
| ライザーカード | 800円 |
| Lenovo 65W ACアダプター | 1,199円 |
| SFP+モジュール | 4,473円 |
| SFP DACケーブルx2 | 1,631円 |
| 合計 | 22,403円 |
OpenWrtのインストール
OpenWrtにはインストーラーなるものがありません
m.2スロットが余ってるpcかUSBの変換を使ってイメージを書き込む必要があります
M720qへ取り付けてOpenWrtを起動する
作成したIntel OptaneをM720qへ戻し、Intel X520-DA2もPCIeライザー経由で取り付けます。
OpenWrtが起動したら、最初にrootパスワードを設定
passwd
NICの割り当てを確認
ip -br link
M720qにはオンボードの1GbE NICが1ポートあり、X520-DA2を追加すると合計3ポートになります。
私の場合はこのように割り当てました
eth0(オンボード 1GbE): LANeth1(X520-DA2 ポート1): WANeth2(X520-DA2 ポート2): 10GbE LAN
LANブリッジの設定
オンボード1GbEの eth0 とX520-DA2の eth2 を同じLANとして使用します。
LuCIの画面で Network → Interfaces → Devices → br-lan → Configure を開き、Bridge ports に eth0 と eth2 を追加します。
これでオンボード1GbEと10GbEポートの両方がLANになります。
WAN6の設定
X520-DA2の eth1 をONUへ接続します。
LuCIで Network → Interfaces → Add new interface を開き、WAN6を作成します。
| 項目 | 設定値 |
|---|---|
| Name | wan6 |
| Protocol | DHCPv6 client |
| Device | eth1 |
| Request IPv6-address | try |
| Request IPv6-prefix of length | Automatic |
BIGLOBE 光クロスではIPv4通信もMAP-Eを利用するため、IPv4側で通常のDHCP WANを取得する構成にはしていません。
LAN側へIPv6を配布する
LuCIで Network → Interfaces → LAN → Edit → DHCP Server → IPv6 Settings を開きます。
| 項目 | 設定 |
|---|---|
| RA-Service | Server mode |
| DHCPv6-Service | Server mode |
| NDP-Proxy | Disabled |
正常にWAN6が接続されると、LuCIのインターフェース画面にIPv6-PDが表示されます。

IPv6-PDを取得できない場合
OpenWrt 25.12系では、DHCPv6クライアントの既定DUIDとしてDUID-UUID type 4が使用されます。一方、フレッツ光クロスでは端末側のDUIDとしてDUID-LLまたはDUID-LLTが要求されているため、既定設定のままではDHCPv6-PDを取得できない場合があります。
私の環境ではWAN6のClient IDをDUID-LLへ変更することでIPv6-PDを取得できました。
まずWAN側NICのMACアドレスを確認します。
cat /sys/class/net/eth1/address
例えばMACアドレスが aa:bb:cc:dd:ee:ff の場合、Ethernet用DUID-LLは次のようになります。
00030001aabbccddeeff
内訳:
0003: DUID-LL0001: Ethernetaabbccddeeff: NICのMACアドレス
WAN6へClient IDを設定して再接続します
uci set network.wan6.clientid='00030001aabbccddeeff'
uci commit network
ifdown wan6 && ifup wan6
MAP-Eの設定
詳しいことはこちらの記事を見た方が早いと思います
パッケージの導入
apk update
apk add map
MAP-Eのパラメータを取得
MAP-Eの設定値は、回線側から取得したIPv6プレフィックスによって変わります。
LuCIの Network → Interfaces からWAN6に割り当てられたIPv6-PDを確認し、こちらの計算ツールへ入力
設定
LuCIの画面で Network → Interfaces → Add new interface を開きます。
- Protocol: MAP / LW4over6
- Name: map
- General Settings: 算出した各パラメータを入力
- Advanced Settings:
- Tunnel Link: wan6
- Use legacy MAP: 有効
- Firewall Settings: wan ゾーンを選択
再起動後、LuCIでMAP-EインターフェースがUpになっていれば設定完了です。
MAP-Eにおけるポート枯渇問題の対策
OpenWrtのMAP-Eの実装では、割り当てられたポート群のうち先頭の16ポートしか利用されず、IPv4のセッションが枯渇する問題が発生していたため、nftablesの numgen を利用して、割り当てられた全240ポートへ均等にセッションを分散させます。
OpenWrt本体に含まれる /lib/netifd/proto/map.shを直接書き換える方式が主流らしいですが、Attended Sysupgradeや owut で map.sh が上書きされるとのことでしたので、こちらで実装されていたhotplug方式を採用しました。
nft list table inet mape を実行して、numgen inc mod 240 を使ったSNATルールが適用されていることを確認できれば完了です。
IPv4とIPv6の接続を確認
でテストし、すべてOKになれば完了です
(おまけ)AdGuard Homeのインストール
パッケージをインストールしたら、自動起動を有効にして起動させます
apk add adguardhome
service adguardhome enable
service adguardhome start
dnsmasqを54番ポートへ移動する
dnsmasqが53番ポートを使用しているので、54に移動させてAdGuard HomeをメインDNSとして53番で待受させます。
uci set dhcp.@dnsmasq[0].port='54'
uci set dhcp.@dnsmasq[0].domain='lan'
uci set dhcp.@dnsmasq[0].local='/lan/'
uci set dhcp.@dnsmasq[0].expandhosts='1'
uci set dhcp.@dnsmasq[0].cachesize='0'
uci set dhcp.@dnsmasq[0].noresolv='1'
uci -q delete dhcp.@dnsmasq[0].server
uci commit dhcp
service dnsmasq restart
初回セットアップ
次のように設定しました
| 項目 | 設定 |
|---|---|
| 管理画面のListen interface | 192.168.0.1 |
| 管理画面のPort | 8080 |
| DNSのListen interface | All interfaces |
| DNSのPort | 53 |
LAN内クライアントへのDNS通知設定
LAN内の機器が自動的にAdGuard Homeを経由して名前解決を行うように設定します。
- IPv4クライアント向けの設定:
- LuCIで Network → Interfaces → LAN → Edit → DHCP Server → Advanced Settings を開く
- DHCP-Options に
6,192.168.0.1を追記して保存・適用
- IPv6クライアント向けの設定:
- LuCIで Network → Interfaces → LAN → Edit → DHCP Server → IPv6 Settings を開く
- 「ローカル IPv6 DNS サーバー」を有効
- 「Announce IPv4/6 DNS servers」の項目は空欄にしておきます(Cloudflareなどの外部DNSを直接端末へ通知すると、AdGuard Homeを迂回されてしまうためです)。
ローカルホスト名の解決連携
インターネット向けのDNS問い合わせはAdGuard Homeが処理し、LAN内機器のホスト名解決(.lan)は54番ポートへ退避させたdnsmasqへ転送するように設定します。
- AdGuard Homeの管理画面(
http://192.168.0.1:8080)を開きます。 - 設定 → DNS設定 を開きます。
- アップストリームDNSサーバー に以下の行を追加します:
[/lan/]127.0.0.1:54 - プライベート逆引きDNSサーバー に以下を設定します:
127.0.0.1:54
これでLAN内のホスト名もAdGuard Home経由で正常に名前解決できるようになります。
パフォーマンスと運用の確認
Flow Offloadingの有効化
LuCIで Network → Firewall → Routing/NAT Offloading を開き、Software flow offloading および Hardware flow offloading を有効にします
uci show firewall.@defaults[0] および nft list flowtable inet fw4 ft を実行して、設定が反映されていることを確認します。
SFP+モジュールの温度の監視
発熱しやすい10GBASE-T SFP+モジュールの動作温度を監視します。
apk add ethtool-full
ethtool -m eth1 | grep temperature
Module temperature : 59.31 degrees C / 138.76 degrees F
Module temperature high alarm : Off
Module temperature low alarm : Off
Module temperature high warning : Off
Module temperature low warning : Off
Module temperature high alarm threshold : 80.00 degrees C / 176.00 degrees F
Module temperature low alarm threshold : -10.00 degrees C / 14.00 degrees F
Module temperature high warning threshold : 75.00 degrees C / 167.00 degrees F
Module temperature low warning threshold : -5.00 degrees C / 23.00 degrees F
59度でした。思ったより熱いな…?
エアフローの改善
エアフローを改善するためMakerWorldで公開されていた全面メッシュのフタを印刷してみました。
これで多少はマシになるといいですが、NICを直接冷やすようにファンを追加した方が早いかもです。

スピードテスト
最後に速度を計っておきます。 測定環境はM4 Macbook Pro とRTL8159 10G NICです
マンションタイプの10Gの割にはかなり早くて大満足です。
