EdgeRouter 4: tailscaleの導入
VPNにwireguardを使用しているが、管理面の煩雑さや固定IPアドレスが必要なためハブアンドスポークの構成になってしまっていることに課題が残っている。勿論、DDNSを使えばメッシュ型のネットワークに出来るがDDNSの運用に手間が掛かることやWireguardのConfigが長大になってしまう問題が発生してしまう。
今回はtailscaleを導入することでネットワークをVPN接続のネットワークをメッシュ型に移行したいと思う。念のため現行のwireguardによるハブアンドスポークの構成はサブ経路として残しておくが、表の経路としてはtailscaleで構成するメッシュネットワークを使用する形にしたい。
問題はEdge Routerでtailscaleが動くかであるが、mipsでコンパイルされたbinaryが用意されており、こちらが使えるらしい。また、Edge Router自身がdebianベース?らしくtailscaleが配布しているインストールスクリプト(apt)でのインストールも問題なく行える。今回は次環境のEdgeRouter4にtailscaleを導入する。
Linux 4.9.79-UBNT #1 SMP Fri Jul 18 11:06:53 UTC 2025 mips64
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
VERSION_CODENAME=stretch
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"2025年にEdgeRouterのOSリリースがあり、ver=3.0.0 へアップグレード済みである。(作っている形跡はあったが今更リリースしてくれるとは思わなかった・・・)
※3.0.0からはwireguardが標準サポートされており、wireguardを個別にインストールする必要が無くなった
冒頭記載の通り、tailscaleが配布しているスクリプトでインストールが行えるが、今回は次のサイトを参考にセットアップを行う。(Firmwareアップグレード時にどうなるかは試せていないので未知数)
GitHub – jamesog/tailscale-edgeos: Running Tailscale on Ubiquiti EdgeOS
1.aptリポジトリの設定
gitの手順に沿ってリポジトリを登録する。
configure
set system package repository tailscale url '[signed-by=/usr/share/keyrings/tailscale-stretch-stable.gpg] https://pkgs.tailscale.com/stable/debian'
set system package repository tailscale distribution stretch
set system package repository tailscale components main
commit comment "Add Tailscale repository"
save
exit2.talescaleのインストール
こちらもgitの手順に沿って進める。スクリプトがbind mountやらsymlinkやらを作成しており、EdgeRouterのfirmware update時にtailscaleの設定が初期化されないような構成に準備してくれている。
sudo bash
mkdir -p /config/scripts/firstboot.d
curl -o /config/scripts/firstboot.d/tailscale.sh https://raw.githubusercontent.com/jamesog/tailscale-edgeos/main/firstboot.d/tailscale.sh
chmod 755 /config/scripts/firstboot.d/tailscale.sh
/config/scripts/firstboot.d/tailscale.sh
/config/scripts/post-config.d/tailscale.sh
3.tailscaleの起動
tailscaleの起動コマンドについては自身の環境に合わせて少しカスタマイズする。gitでは先にauthkeyを発行する手順となっているが、authkey無しで進めると認証用のURLが発行されるので、こちらを用いて認証する形にする。※–snat-subnet-routesについては6.に記載
# tailscale up --advertise-routes "192.168.32.0/20" --accept-routes --snat-subnet-routes=false
To authenticate, visit:
認証用のURL
Success.EdgeRouterが接続しているプライベートネットワークのサブネットをadvertise-routesで広報することで、他のネットワークから接続が出来るようにする。複数サブネットを広報したい場合は--advertise-routes "192.168.1.0/24,192.168.2.0/24"のように”,”区切りでサブネットCIDRを設定する。
※tailscale起動後に変更する場合はtailscale set --advertise-routesで変更可能
また、他のネットワークから広報された経路を取得するために--accept-routesを設定する。これが無いとtailscale上に広報されているネットワーク情報を取り込んでくれない。
※offにしたい場合は--accept-routes=false
4.tailscaleのコントローラ設定
advertise-routesで広報したネットワーク情報を有効にするにはコントローラの方で許可設定が必要になる。広報内容の確認と承認、ついでに認証の永続化をWEB-UIから行う。


広報内容の確認と承認は「Edit route settings…」から行い、認証の永続化は「Disable Key expiry」から行う。
5.Routingの確認
--accept-routesで取り込んだルーティングが確認できず、でも通信はできたりして若干混乱したが、tailscaleの方でルーティングテーブルを追加作成しているため、show ip routeではルーティングを確認することが出来ない。ip rule showで確認すると「52」というルーティングテーブルが追加され、mainよりも優先されるようになっている。
# ip rule show
0: from all lookup local
5210: from all fwmark 0x80000/0xff0000 lookup main
5230: from all fwmark 0x80000/0xff0000 lookup default
5250: from all fwmark 0x80000/0xff0000 unreachable
5270: from all lookup 52
32766: from all lookup main
32767: from all lookup default# show ip route table 52
100.100.100.100 dev tailscale0
100.83.114.53 dev tailscale0 <---他のtailscaleのクライアント
100.101.32.154 dev tailscale0 <---他のtailscaleのクライアント
192.168.32.0/20 dev tailscale0 <---tailscaleから広報されているルーティング
192.168.48.0/20 dev tailscale0 <---tailscaleから広報されているルーティング$ show ip route 192.168.32.1
Routing entry for 192.168.32.0/24
Known via "bgp",
※show ip routeはEdgeRouter側のコマンドが呼ばれているが、mainテーブルのみで判定されている
$ ip route get 192.168.32.1
192.168.32.1 dev tailscale0 table 52 src 100.76.234.56
※こちらのコマンドだとtailscaleで追加されたルートテーブルも込みで判定されていて、こちらの方が実際の通信経路になる私の環境の場合、tailscaleからの広報が無くなると、mainのルートテーブルに設定している経路が有効化されるのでルートテーブル52の存在を忘れなければ、この構成の方が都合が良い。(tailscaleのI/F上で動的ルーティングを設定するのが面倒そうなので・・・)
--accept-routesを使わないで、EdgeRouterの方でルーティング設定する方法は未検証。
次のような設定?(おそらく、100.x.y.zのルーティングはtable 52で解決しちゃうのでこれのstaticは不要な気がする)
# set protocols static interface-route 192.168.32.0/20 next-hop-interface tailscale0
※未検証今の私の環境だとBGPで/24単位を配布しているため、/20ではなく/24単位のstaticをたくさん書かないといけない。fail-over動作させたい場合は動的ルーティングの設定系が必要だが、tailscale0のI/Fがpoint to multi-pointのnon-broadcastなtunnel I/Fなので結構面倒な気がする。non-broadcastなOSPFあたりの設定かp2pのGREトンネルとかを構成して無理やりnexthopをconnected nwで見えるように変えちゃうか。(簡単に繋がらなかったら多分すごく面倒なやつなので多分検証しない)
メモ:linux (ubuntu)で tailscale upだけを行った状況が次。やはり、100.x.y.z宛てのroutingは自動的に設定される模様。
# tailscale up
To authenticate, visit:
Success.
# ip route list table 52
100.xx.xx.xx dev tailscale0
100.yy.yy.yy dev tailscale0
100.100.100.100 dev tailscale0
100.zz.zz.zz dev tailscale0
# ip rule show
0: from all lookup local
5210: from all fwmark 0x80000/0xff0000 lookup main
5230: from all fwmark 0x80000/0xff0000 lookup default
5250: from all fwmark 0x80000/0xff0000 unreachable
5270: from all lookup 52
32766: from all lookup main
32767: from all lookup default6. SNATの停止
いくつかの通信で想定通り動かない事象が発生した。通信を確認するとtailscaleでのNATが原因と思われる。例えば次のような通信の場合、2の通信に対してのみSNATで192.168.2.1などのIPアドレスにSNAT (source nat)されると認識していた。
1. | 192.168.1.100 | ---> |tailscale_RT| ---> |tailscale_RT| ---> |192.168.2.100|
2. | 100.x.y.z (tailscale)| ---> |tailscale_RT| ---> |192.168.2.100|実際のエラーログを見ると、1の通信についてもSNATが行われているようである。これだと通信元のIPアドレスをチェックしている一部の通信でエラーが出てしまう。
tailscaleでSNATを行う方法はDisable SNATに記載がある。
tailscale up --snat-subnet-routes=falsetailscaleを起動中の場合は次のコマンドになる。
tailscale set --snat-subnet-routes=falseこの設定を行った場合は100.x.y.zからの通信が来るケースがあるので、SNATをしたり他のネットワーク機器にルーティングを設定したり、アプリの許可IPアドレス範囲に追加したりなどを検討する必要がある。