NanoPi R4S + OpenWrtでv6プラス固定IPを使ってみる

NanoPi R4S

Gigabit LAN x 2 で映像出力なしというミニルータに特化したようなデバイスで4G RAMモデルと1G RAMモデルがあり、今回は4Gでケース付きを購入した。

ストレージはSBCらしくmicro SDカードで、無線LANはついていない。

CPUはRockchipのarmv8でRK3399というものらしい。

OpenWrt

市販のルータで動作できるほど軽量なLinux distributionで、市販のルータの真の力を解放するらしい。

openwrt.org

しかし残念ながら、NanoPi R4S向けにはstable releaseされておらず開発版のsnapshotを使う必要がある。

初期設定

OS書き込み

downloads.openwrt.org から openwrt-rockchip-armv8-friendlyarm_nanopi-r4s-ext4-sysupgrade.img.gz をダウンロードし、適当なライターでmicroSDに書き込む。

microSDをNanoPiに挿し電源をつけてLANポートとPCを有線で繋ぐと、DHCPで192.168.1.0/24のアドレスが降ってくる。

$ ssh root@192.168.1.1

sshで繋ぐとパスワードなしにログインできるので、すかさず

root@OpenWrt:~# passwd

パスワードの設定をする。

一旦exitでPCに戻りssh-keyの設定をする(OpenWrtで使われているSSHサーバであるdropbearはyubikeyで使ってるecdsaに対応していないため、新たにed25519で鍵を作る必要があり、ここで結構ハマった…)。

ssh-copy-idを使うとdropbearに合わせた設定をしてくれるので便利(~/.ssh/authorized_keyではなく/etc/dropbear/authorized_keysに追記する必要がある)。

$ cd ~/.ssh
$ ssh-keygen -t ed25519
$ ssh-copy-id -i id_ed25519 root@192.168.1.1

これで

$ ssh root@192.168.1.1

でパスワードなしでログインできるようになった。

ネットワークの初期設定

OpenWrtでは各種設定は/etc/config/以下に保存されておりuciコマンドで操作することができる。

例えばネットワークに関する設定は/etc/config/networkにあり、初期状態ではこのようになってる

root@OpenWrt:~# cat /etc/config/network

config interface 'loopback'
    option device 'lo'
    option proto 'static'
    option ipaddr '127.0.0.1'
    option netmask '255.0.0.0'

config globals 'globals'
    option ula_prefix 'fd56:d548:f6c2::/48'

config device
    option name 'br-lan'
    option type 'bridge'
    list ports 'eth1'

config device
    option name 'eth1'
    option macaddr 'ab:cd:ef:gh:ij:kl'

config interface 'lan'
    option device 'br-lan'
    option proto 'static'
    option ipaddr '192.168.1.1'
    option netmask '255.255.255.0'
    option ip6assign '60'

config device
    option name 'eth0'
    option macaddr '12:34:56:78:90:ab'

config interface 'wan'
    option device 'eth0'
    option proto 'dhcp'

config interface 'wan6'
    option device 'eth0'
    option proto 'dhcpv6'

このファイルをuciコマンド経由で見ると

root@OpenWrt:~# uci show network
network.loopback=interface
network.loopback.device='lo'
network.loopback.proto='static'
network.loopback.ipaddr='127.0.0.1'
network.loopback.netmask='255.0.0.0'
network.globals=globals
network.globals.ula_prefix='fd56:d548:f6c2::/48'
network.@device[0]=device
network.@device[0].name='br-lan'
network.@device[0].type='bridge'
network.@device[0].ports='eth1'
network.@device[1]=device
network.@device[1].name='eth1'
network.@device[1].macaddr='ab:cd:ef:gh:ij:kl'
network.lan=interface
network.lan.device='br-lan'
network.lan.proto='static'
network.lan.ipaddr='192.168.1.1'
network.lan.netmask='255.255.255.0'
network.lan.ip6assign='60'
network.@device[2]=device
network.@device[2].name='eth0'
network.@device[2].macaddr='12:34:56:78:90:ab'
network.wan=interface
network.wan.device='eth0'
network.wan.proto='dhcp'
network.wan6=interface
network.wan6.device='eth0'
network.wan6.proto='dhcpv6'

このようになる。

OpenWrtはデフォルトでLANデバイスとWLANデバイスをブリッジしているため、br-lanというデバイスが定義されており、それがlanインターフェイスとなっている。 しかし、NanoPi R4SにはWLANデバイスはないためこのブリッジデバイスを削除しておく。

ファイルを直接編集してもいいしuciコマンドで設定してもいいが、今回はuciコマンドで設定を行う。

ついでにlanにあるipv6の設定も消しておく。

root@OpenWrt:~# uci delete network.@device[0]
root@OpenWrt:~# uci set network.lan.device=eth1
root@OpenWrt:~# uci delete network.lan.ip6assign='60'
root@OpenWrt:~# uci show network
network.loopback=interface
network.loopback.device='lo'
network.loopback.proto='static'
network.loopback.ipaddr='127.0.0.1'
network.loopback.netmask='255.0.0.0'
network.globals=globals
network.globals.ula_prefix='fd56:d548:f6c2::/48
network.@device[0]=device
network.@device[0].name='eth1'
network.@device[0].macaddr='ab:cd:ef:gh:ij:kl'
network.lan=interface
network.lan.device='eth1'
network.lan.proto='static'
network.lan.ipaddr='192.168.1.1'
network.lan.netmask='255.255.255.0'
network.@device[1]=device
network.@device[1].name='eth0'
network.@device[1].macaddr='12:34:56:78:90:ab'
network.wan=interface
network.wan.device='eth0'
network.wan.proto='dhcp'
network.wan6=interface
network.wan6.device='eth0'
network.wan6.proto='dhcpv6

commitを行うことにより設定ファイルが更新される。

root@OpenWrt:~# uci commit network
root@OpenWrt:~# cat /etc/config/network

config interface 'loopback'
    option device 'lo'
    option proto 'static'
    option ipaddr '127.0.0.1'
    option netmask '255.0.0.0'

config globals 'globals'
    option ula_prefix 'fd56:d548:f6c2::/48'

config device
    option name 'eth1'
    option macaddr 'ab:cd:ef:gh:ij:kl'

config interface 'lan'
    option device 'eth1'
    option proto 'static'
    option ipaddr '192.168.1.1'
    option netmask '255.255.255.0'

config device
    option name 'eth0'
    option macaddr '12:34:56:78:90:ab'

config interface 'wan'
    option device 'eth0'
    option proto 'dhcp'

config interface 'wan6'
    option device 'eth0'
    option proto 'dhcpv6'

パッケージの更新・追加

ここでNanoPiのWANポートに既存インターネット(DHCPでアドレスが割り当てられる)を接続する。

# 初回は証明書が切れてたりするためチェックをせずに行う
root@OpenWrt:~# opkg update --no-check-certificate

# Webインターフェイス
root@OpenWrt:~# opkg install luci-ssl

IPIP6パッケージの作成

v6プラス固定IPで使用するIPIP6トンネルに関するパッケージは公式にはないため、 github.com こちらを使用させていただいた。

カスタムビルドするのはかなり手間なのでパッケージを手作りすることにした。

# ipip6パッケージ作成

$ mkdir ipip6
$ cd ipip6

## control.tar.gzの作成

$ mkdir control
$ cd control

$ cat << EOS > ./control
Package: ipip6
Version: 0.1
Depends: libc, kmod-ip6-tunnel, resolveip
Source: feeds/base/package/network/ipv6/ipip6
SourceName: ipip6
License: GPL-2.0
Section: net
SourceDateEpoch: 1641284700
Maintainer: kenjiuno <ku@digitaldolphins.jp>
Architecture: all
Installed-Size: 2716
Description: Provides support for ipip6 (RFC2473) in /etc/config/network.
EOS

$ cat << EOS > ./postinst
#!/bin/sh
[ "${IPKG_NO_SCRIPT}" = "1" ] && exit 0
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
. ${IPKG_INSTROOT}/lib/functions.sh
default_postinst $0 $@
EOS

$ cat << EOS > ./postinst-pkg
[ -n "${IPKG_INSTROOT}" ] || { rm -f /tmp/luci-indexcache
    rm -rf /tmp/luci-modulecache/
    killall -HUP rpcd 2>/dev/null
    exit 0
}
EOS

$ cat << EOS > ./prerm
#!/bin/sh
[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0
. ${IPKG_INSTROOT}/lib/functions.sh
default_prerm $0 $@
EOS

$ chmod +x postinst postinst-pkg prerm

$ tar --numeric-owner --group=0 --owner=0 -czf ../control.tar.gz ./

$ cd ..

## data.tar.gzの作成

$ mkdir data
$ cd data

$ mkdir -p ./lib/netifd/proto
$ mkdir -p ./www/luci-static/resources/protocol

$ wget -O ./lib/netifd/proto/ipip6.sh https://github.com/HiraokaHyperTools/openwrt-ipip6/raw/main/net/ipv6/ipip6/files/ipip6.sh
$ wget -O ./www/luci-static/resources/protocol/ipip6.js https://github.com/HiraokaHyperTools/openwrt-ipip6/raw/main/net/ipv6/ipip6/files/ipip6.js

$ chmod +x ./lib/netifd/proto/ipip6.sh

$ tar --numeric-owner --group=0 --owner=0 -czf ../data.tar.gz ./

$ cd ..

## debian-binaryの作成

$ cat << EOS > ./debian-binary
2.0
EOS

## ipip6_0.1_all.ipkの作成

$ tar --numeric-owner --group=0 --owner=0 -czf ./ipip6_0.1_all.tar.gz ./debian-binary ./data.tar.gz ./control.tar.gz
$ mv ipip6_0.1_all.tar.gz ../ipip6_0.1_all.ipk

出来上がった、ipip6_0.1_all.ipkをNanoPiに持っていき、インストールする。(なんかbasenameに関するエラーが出るがうまく動いてるのでヨシとする…どなたか原因を教えていただけると幸いです。)

root@OpenWrt:~# opkg install ./ipip6_0.1_all.ipk
Installing ipip6 (0.1) to root...
Configuring ipip6.
basename: unrecognized option: z
BusyBox v1.35.0 (2022-03-17 07:05:03 UTC) multi-call binary.

Usage: basename FILE [SUFFIX] | -a FILE... | -s SUFFIX FILE...

Strip directory path and SUFFIX from FILE

    -a      All arguments are FILEs
    -s SUFFIX   Remove SUFFIX (implies -a)

ここでNanoPiを再起動し、WANに挿していたケーブルをONU直結へと変える。

IPv6パススルーの設定

Webインターフェイス(https://192.168.1.1)を開き、Network->InterfaceにいきWAN6をEditする。

DHCP Serverのタブに行き、Set up DHCP Serverを押す。

IPv6 Settingsのタブに行き、Designated masterにチェックを入れ、全てrelay modeにする。

同様にLANも設定する。

今度はDHCPv6 Serviceのみserver modeにし、それ以外はrelay modeにする。

Announced IPv6 DNS serversにPublic DNSサーバのIPv6アドレスを入れる。

  • 2001:4860:4860::8888 # Google
  • 2606:4700:4700::1111 # CloudFlare

NDP-Proxy slaveにはチェックを入れない

次にAdvanced Settingsのタブに行きDHCP伝えるDNSサーバの設定をする 。

DHCP-Optionsのところに 6,8.8.8.8,1.1.1.1と入れる。

atmarkit.itmedia.co.jp

6がDNSの設定でそれ以降にコンマ区切りで、アドレスを入れる。

これでLAN側につなげたPCからIPv6アクセスが可能となる。

WAN6のインターフェイスIDの固定化

固定IPサービスのIPIP6トンネルを張るにはローカル(自身)のIPv6アドレスのインターフェイスIDが指定されたものでないといけないので上書きする。

root@OpenWrt:~# uci set network.wan6.ifaceid='::[ISPから通知されたインターフェイスID]'
root@OpenWrt:~# uci commit network

IPv4 over IPv6の設定

Add new interface...を押し、ProtocolIPv4 over IPv6 (ipip6)を選択する。

Tunnel remote IPv6 addressにv6プラスのBRのアドレスを入れる。 Your global IPv4 addressにはISPから通知された固定IPv4アドレスを入れる。 Local IPv6 addressは空にする(スクリーンショットでは例示用アドレスを入れてある)。

Firewall Settingsのタブでwanゾーンに適応する。

これで、IPv4でのアクセスが可能となる。

スナップショットのアップグレード

アップグレードを行うと設定は保持されるが、パッケージは初期状態になるので再度インストールする。

root@OpenWrt:~# wget https://downloads.openwrt.org/snapshots/targets/rockchip/armv8/openwrt-rockchip-armv8-friendlyarm_nanopi-r4s-ext4-sysupgrade.img.gz
root@OpenWrt:~# sysupgrade -v ./openwrt-rockchip-armv8-friendlyarm_nanopi-r4s-ext4-sysupgrade.img.gz

# 再起動がかかり更新される
root@OpenWrt:~# opkg update
root@OpenWrt:~# wget https://static.akashisn.info/packages/openwrt/ipip6_0.1_all.ipk
root@OpenWrt:~# opkg install ./ipip6_0.1_all.ipk
root@OpenWrt:~# opkg install luci-ssl luci-i18n-base-ja luci-i18n-firewall-ja luci-i18n-opkg-ja

# 以下お好みで
root@OpenWrt:~# opkg install map ds-lite iptables-mod-ipopt
root@OpenWrt:~# opkg install ca-certificates
root@OpenWrt:~# opkg install wireguard-tools luci-proto-wireguard luci-app-wireguard luci-i18n-wireguard-ja
root@OpenWrt:~# opkg install openvpn-mbedtls kmod-ovpn-dco luci-app-openvpn luci-i18n-openvpn-ja
root@OpenWrt:~# opkg install ddns-scripts-cloudflare luci-app-ddns luci-i18n-ddns-ja

root@OpenWrt:~# reboot

速度測定

2スレッドしか使われていないようだが、

十分に速度が出ている。