NanoPiR4S+OpenWrtでv6プラス固定IPを使う

NanoPi R4S

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

Nanopi R4S

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

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

OpenWrt

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

https://openwrt.org/toh/hwdata/friendlyarm/friendlyarm_nanopi_r4s

しかし残念ながら、NanoPi R4S向けにはstable releaseされておらず開発版のsnapshotを使う必要がある。
追記 2022/9/6 22.03がリリースされ、NanoPi R4S向けのイメージがstable releaseとして出ました。

初期設定

OS書き込み

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

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

$ ssh [email protected]

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 [email protected]

これで

$ ssh [email protected]

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

ネットワークの初期設定

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トンネルに関するパッケージは公式にはないため、

https://github.com/HiraokaHyperTools/openwrt-ipip6

こちらを使用させていただいた。

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

# 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 <[email protected]>
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に持っていき、インストールする。

root@OpenWrt:~# opkg install ./ipip6_0.1_all.ipk

ここで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と入れる。

https://atmarkit.itmedia.co.jp/fnetwork/netcom/netcom06/option.html

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/releases/22.03.0/targets/rockchip/armv8/openwrt-22.03.0-rockchip-armv8-friendlyarm_nanopi-r4s-squashfs-sysupgrade.img.gz
root@OpenWrt:~# sysupgrade -v ./openwrt-22.03.0-rockchip-armv8-friendlyarm_nanopi-r4s-squashfs-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 qrencode wireguard-tools luci-proto-wireguard luci-app-wireguard luci-i18n-wireguard-ja
root@OpenWrt:~# opkg install openvpn-openssl kmod-ovpn-dco openvpn-easy-rsa luci-app-openvpn luci-i18n-openvpn-ja
root@OpenWrt:~# opkg install ddns-scripts-cloudflare luci-app-ddns luci-i18n-ddns-ja
root@OpenWrt:~# opkg install acme acme-dnsapi luci-app-acme luci-i18n-acme-ja

root@OpenWrt:~# reboot

速度測定

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

十分に速度が出ている。

Ubuntu20.04でv6プラス固定IPルータをつくる

Edgerouterではなぜかhwnatを有効化するとipipトンネルがおかしくなるみたいでhardware offloadを無効化していたのだが、やはりCPU性能がボトルネックになっていたのでノートパソコン(XPS13)でルータを作ってみた。

前回の記事での「RA Prefixの取得」を行って、

$ sudo apt install radvdump
  • 隣ルータのリンクローカルアドレス : fe80::xxxx:xxxx:xxxx:xxxx
  • IPv6 Prefix : 240b:xxxx:xxxx:xxxx::/64

を取得しているものとする。

環境

Ubuntu 20.04 Desktop XPS13-9360

  • eth0: ONUに直結
  • eth1: LAN側 (10.10.0.1/24)

Ubuntu Serverではないため、Network Managerが入っているがこれは以下で設定するnetplanと競合してしまったりするためアンインストールしておく。

$ sudo apt purge network-manager

(ここで再起動しておいたほうがいいかも)

Netplanを使用したIPアドレスとIPIPトンネリング

eth0に取得したIPv6 Prefix (240b:xxxx:xxxx:xxxx) とISPから通知されたインターフェイスID (yyyy:yyyy:yyyy:yyyy) を連結させたものをセットする。
IPv6のデフォルトゲートウェイを隣ルータのリンクローカルアドレス (fe80::xxxx:xxxx:xxxx:xxxx) とする。

IPIPトンネルにはISPから通知された固定IP情報に記載されている[固定IPアドレス]と[BRアドレス]を使用する。
IPv4はこのトンネルを使用するようにする。

/etc/netplan/01-netcfg.yamlを以下の内容で作成。

(このディレクトリにある他の設定ファイルは拡張子を変えるとかして無効化しておく)

network:
  version: 2
  ethernets:
    eth0:
      accept-ra: false
      dhcp4: false
      dhcp6: false
      addresses:
        - 240b:xxxx:xxxx:xxxx:yyyy:yyyy:yyyy:yyyy/64
      routes:
        - to: ::/0
          via: fe80::xxxx:xxxx:xxxx:xxxx
    eth1:
      accept-ra: false
      addresses:
        - 10.10.0.1/24
        - 240b:xxxx:xxxx:xxxx::1/64
      nameservers:
        addresses:
          - 8.8.8.8
          - 2001:4860:4860::8888
  tunnels:
    ip6tnl1:
      mode: ipip6
      addresses:
        - [固定IPアドレス]
      remote: [BRアドレス]
      local: 240b:xxxx:xxxx:xxxx:yyyy:yyyy:yyyy:yyyy
      routes:
        - to: 0.0.0.0/0
          scope: link

Forwardingの設定

IPパケットの転送を有効化する。

/etc/sysctl.confを編集。以下のコメントを外す。

# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1
       ↓
net.ipv4.ip_forward=1
# Uncomment the next line to enable packet forwarding for IPv6
#  Enabling this option disables Stateless Address Autoconfiguration
#  based on Router Advertisements for this host
#net.ipv6.conf.all.forwarding=1
       ↓
net.ipv6.conf.all.forwarding=1
$ sudo sysctl -p 

ufwの設定

/etc/default/ufwを編集。DEFAULT_FORWARD_POLICYACCEPTにする。

# Set the default forward policy to ACCEPT, DROP or REJECT.  Please note that
# if you change this you will most likely want to adjust your rules
DEFAULT_FORWARD_POLICY="DROP"
       ↓
DEFAULT_FORWARD_POLICY="ACCEPT"

/etc/ufw/before.rulesを編集。最初の部分に以下を追加。

#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
#   ufw-before-input
#   ufw-before-output
#   ufw-before-forward
#

# ここから
# Masquarade
*nat
:POSTROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.10.0.0/24 -j MASQUERADE
COMMIT
# don't delete the 'COMMIT' line or these rules won't be processed
# ここまで追加

/etc/ufw/after.rules/etc/ufw/after6.rulesを同じように編集。最初の部分に以下を追加。

#
# rules.input-after
#
# Rules that should be run after the ufw command line added rules. Custom
# rules should be added to one of these chains:
#   ufw-after-input
#   ufw-after-output
#   ufw-after-forward
#

# ここから
*mangle
:POSTROUTING ACCEPT [0:0]
:PREROUTING ACCEPT [0:0]
-A FORWARD -o ip6tnl1 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1412
COMMIT
# don't delete the 'COMMIT' line or these rules won't be processed
# ここまで追加

ufwを有効化する

$ sudo ufw enable

LANからLocalへのアクセスを許可する

$ sudo ufw allow from 10.10.0.0/24

DHCPサーバ・RAの設定

IPv4アドレスはDHCPサーバで配布して、IPv6アドレスはNDProxy+RAによる告知を行う。

isc-dhcp-serverの設定

$ sudo apt install isc-dhcp-server

/etc/default/isc-dhcp-serverを編集。DHCPv4サーバがlistenするインターフェイスを指定。

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#    Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACESv4=""
INTERFACESv6=""
       ↓
INTERFACESv4="eth1"
#INTERFACESv6=""

/lib/systemd/system/isc-dhcp-server.serviceを編集。PIDファイルのパスを/var/run/dhcpd.pidへ変更。

    exec dhcpd -user dhcpd -group dhcpd -f -4 -pf /run/dhcp-server/dhcpd.pid -cf $CONFIG_FILE $INTERFACESv4'
       ↓
    exec dhcpd -user dhcpd -group dhcpd -f -4 -pf /var/run/dhcpd.pid -cf $CONFIG_FILE $INTERFACESv4'
$ sudo systemctl daemon-reload

最初からある設定ファイルの名前を変えておく。

$ sudo mv /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.sample

/etc/dhcp/dhcpd.confを以下の内容で作成。

# default
default-lease-time 600;
max-lease-time 7200;
ddns-update-style none;

authoritative;

subnet 10.10.0.0 netmask 255.255.255.0 {
  range 10.10.0.30 10.10.0.199;
  option routers 10.10.0.1;
  option domain-name-servers 1.1.1.1, 8.8.8.8;
  default-lease-time 3600;
  max-lease-time 7200;
}

radvdの設定

/etc/radvd.confを以下の内容で作成。

interface eth1   
{   
    AdvCurHopLimit 64;
    AdvLinkMTU 1500;
    AdvManagedFlag off;
    AdvOtherConfigFlag off;
    AdvReachableTime 0;
    AdvRetransTimer 0;
    AdvSendAdvert on;
    MaxRtrAdvInterval 600;
    prefix 240b:xxxx:xxxx:xxxx::/64 
    {
        AdvAutonomous on;
        AdvOnLink on;
        AdvValidLifetime 2592000;
    };
    RDNSS 2606:4700:4700::1111 2001:4860:4860::8888
    {
    };
};    
$ sudo apt install radvd

ndppdの設定

/etc/ndppd.confを以下の内容で作成。

proxy eth0 {
  router no
  timeout 500
  autowire yes
  keepalive yes
  retries 3
  ttl 30000
  240b:xxxx:xxxx:xxxx::/64 {
    iface eth1
  }
}
$ sudo apt install ndppd
$ sudo systemctl enable ndppd.service

ここで再起動する

速度計測

十分に速くなった!