Vultr VPSと自宅サーバの間にL2ネットワークを作り、グローバルの固定IPv6アドレスを自宅マシンに割り当てた
動機: グローバルの固定IPv6アドレスを自宅マシンで使いたい
VultrでVPSをデプロイすると、インターネットreachableなグローバルの固定IPv6プレフィックス/64が1つVPSに割り当てられます。これをVPSだけに使わせるのはもったいないので、VPSからL2トンネルを張って下流の自宅マシンにも同じ固定IPv6プレフィックスを割り当てられるようにしました。
結果として、VPS 1契約分のコストで、グローバルの固定IPv6アドレスを下流の任意の自宅マシンに割り当てできるようになりました。以下、本記事ではその構成と設定方法を記述します。
前提: VultrにおけるIPv6アドレス割り当ての仕組み
SLAAC(ステートレス・アドレス自動設定)が採用されている
VultrでデプロイしたVPSには標準でインターネット向けIF(enp1s0)が備わっていて、そのIFの上流(VPSのdefault GW)からRAが広報されてきます。そのRAには、VPSごとにユニークな固定IPv6プレフィックス/64が設定されています。
VPSはそのRAを受信することで、IPv6ホスト部をMACアドレスから生成したIPv6アドレスをIF(enp1s0)に自動設定し、さらにインターネットと疎通できるようにするためのIPv6ルーティングも自動設定します。いわゆるSLAAC(ステートレス・アドレス自動設定)です。
試しにVPS上でipコマンドを打てば、VPSが自動設定したIPv6アドレスやdefault GWへのIPv6ルーティングなどを確認できます。
例えば、以下のように。
・2001:db8:7654:3210::/64 RAで広報されたVPSの固定IPv6プレフィックス/64
・fe80::1234:5678:9abc:def0 RAの送信元IPv6 link-localアドレス。VPSのdefault GW
$ ip a show dev enp1s0
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet6 2001:db8:7654:3210:xxxx:xxxx:xxxx:xxxx/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 2591679sec preferred_lft 604479sec
inet6 fe80::xxxx:xxxx:xxxx:xxxx/64 scope link
valid_lft forever preferred_lft forever
$ ip -6 route
2001:db8:7654:3210::/64 dev enp1s0 proto ra metric 100 expires 2591711sec mtu 1500 hoplimit 64 pref medium
fe80::/64 dev enp1s0 proto kernel metric 256 pref medium
default via fe80::1234:5678:9abc:def0 dev enp1s0 proto ra metric 100 expires 1511sec mtu 1500 hoplimit 64 pref medium
IPv6アドレスがVPS自身のIFのものかどうかは上流でチェックされない
Vultrでデプロイしたばかりの素のVPS上では、RAを受信してIPv6アドレスが自動設定されるIFはenp1s0のみです。つまりenp1s0だけがインターネットreachableな状態となっています。
ここで特筆すべき点は、VPS自身のIF(enp1s0)でRAを受信したかどうかは上流(VPSのdefault GW)でチェックされないということです。例えば、VPS上でenp1s0とは異なるMACアドレスのIFをユーザ定義してそのIFでRAを受信させると、そのユーザ定義のIFにもIPv6アドレスを自動設定でき、かつ、そのユーザ定義のIFでもインターネットreachableな状態となります。
上流(VPSのdefault GW)はあくまでステートレスであり、IPv6プレフィックスまでしか把握していないため、実際にIPv6で通信する際には下流に対してNeighbor Discovery Protocolで通信先IPv6アドレスのMACアドレスを探しにくる挙動が見られます。
このようなSLAACの仕組みを踏まえると、RAを広報するレイヤ2ネットワークを自分で構築してそこに任意のマシンを接続させれば、任意のマシンのIFにIPv6アドレスを自動設定でき、任意のマシンのIFをインターネットreachableな状態にできることになります。
以下、長くなりますが、そのための手順を順に記述していきます。
VPSと自宅サーバの間にレイヤ2ネットワークを作る手順
事前に用意するもの
-
Vultr VPS (Ubuntu 24.04) 1台
VPSデプロイ時の指定事項:
・Oerating System=Ubuntu 24.04 x64
・Public IPv4=Enabled
・Public IPv6=Enabled
・Limited User Login=Enabled
-
適当な自宅サーバ (Ubuntu 24.04) 1台
指定事項:
・Ubuntu 24.04インストール済であること
・物理IFを2つ備えており、
1番目の物理IFでIPv4でインターネットにアクセスできること (apt install等できること)
2番目の物理IFにIPv4/v6アドレスを設定していないこと
手順の概要
NOTE: 手順を進める中で下記のapt install
を行います。
-
VPSと自宅サーバにIncusを導入する
VPSと自宅サーバになるべく変更を加えない方針でまずIncusを導入する。
apt install incus
-
Incusホストを設定する
Incusゲストを動作させるためIncusホストを設定する。下準備。 -
Incusゲストを生成する
下準備を整えたら、
・VPS上でIncusゲスト 2台 (ubunt-ndppdとubuntu-l2vpn-s)を生成する。
・自宅サーバ上でIncusゲスト 1台 (ubuntu-l2vpn-c)を生成する。 -
Incusゲスト ubuntu-ndppdを設定する
Incusゲスト上でradvdとndppdを導入して設定する。
・radvd: 下流にRAを広報する。
・ndppd: 上流と下流の間でNeighbor Discovery Protocolをプロキシする。
apt install radvd ndppd
-
Incusゲスト ubuntu-l2vpn-s/-cを設定する
Incusゲスト上でwireguardを導入して設定する。
・wireguard: Incusゲスト間でVPNを張って直接通信を可能とする。
さらに、VPN上でL2TPのトンネルを張ってL2ネットワークを完成させる。
・L2TP: Linuxカーネルモジュールでapt install不要で使用可。
apt install wireguard
ネットワーク構成
・上流(default GW)がRAを広報しますが、それと同等のRAをradvdから下流へ広報させます。
・上流と下流の間でNeighbor Discovery Protocolをプロキシするndppdを立てます。
・下流にL2TPトンネル over WireGuardを張り、自宅L2スイッチまで地続きのレイヤ2にします。
インタフェース一覧:
本手順で以下のインタフェースを作成します。(事前作成済のIFを除く)
- 事前作成済のIF
・VPSenp1s0
・自宅サーバenp1s0
,enp2s0
- Incus導入時に作成するIF
・VPSincusbr0
- Incusホスト設定時に作成するIF
・VPSbr-internal0
・自宅サーバbr-internal0
- Incusゲスト生成時に作成するIF
・ubuntu-ndppdeth0 (nictype:macvlan)
,eth1 (nictype:bridged)
・ubuntu-l2vpn-seth0 (network:incusbr0)
,eth1 (nictype:bridged)
・ubuntu-l2vpn-ceth0 (network:incusbr0)
,eth1 (nictype:bridged)
- Incusゲスト ubuntu-ndppd設定時に作成するIF
・none - Incusゲスト ubuntu-l2vpn-s/-c設定時に作成するIF
wireguard用
・ubuntu-l2vpn-swg0
・ubuntu-l2vpn-cwg0
L2TP用
・ubuntu-l2vpn-sbr-l2tp0
,l2tp-eth0
・ubuntu-l2vpn-cbr-l2tp0
,l2tp-eth0
IPアドレス一覧:
本手順で以下のIPアドレスを設定します。太字IPはグローバルIP。
- Vultr VPSデプロイ時に割当済みのIP
・VPSのGlobal IPv4アドレス: 203.0.113.103
・VPSのGlobal IPv6プレフィックス: 2001:db8:7654:3210::/64 - Incus導入時に割当されるIP
・VPSのincusbr0 Private IPv4アドレス: 10.91.163.1 - 本手順で指定するユーザ指定のIP/port
・自宅マシンのSLAAC IPv6アドレス: 2001:db8:7654:3210:1111:2222:3333:4444
・通信プロトコル (下表参照)
Protocol | Role | EndPoint | 本手順での例示 | |
---|---|---|---|---|
1 | wireguard/udp | サーバ | ubuntu-l2vpn-s(eth0) | 10.91.163.3:53000 |
クライアント | ubuntu-l2vpn-c(eth0) | Don't care | ||
2 | ポート開放/udp | 転送元(Global) | VPS(enp1s0) | 203.0.113.103:53000 |
転送先(Private) | ubuntu-l2vpn-s(eth0) | 10.91.163.3:53000 | ||
3 | l2tp/udp | サーバ | ubuntu-l2vpn-s(wg0) | 10.0.0.1:1701 |
クライアント | ubuntu-l2vpn-s(wg0) | 10.0.0.2:1701 |
手順1. VPSと自宅サーバにIncusを導入する
PVSと自宅サーバそれぞれでIncusを導入します。
なお、incus導入後にip aコマンドを打つと、incusbr0が見えます。
Ref1: https://linuxcontainers.org/incus/docs/main/tutorial/first_steps/
sudo apt update
sudo apt install incus
sudo adduser linuxuser incus-admin
newgrp incus-admin
incus admin init --minimal
ip a
incusbr0を介した通信を許容するようにファイアウォール(ufw)を設定します。
Ref2: https://linuxcontainers.org/incus/docs/main/howto/network_bridge_firewalld/
sudo ufw status
sudo ufw allow in on incusbr0
sudo ufw route allow in on incusbr0
sudo ufw route allow out on incusbr0
sudo ufw status
手順2. Incusホストを設定する
VPS設定その1: Incusプロファイル用意
defaultのプロファイルを流用してIncusゲスト(ubuntu-ndppd)用のプロファイルを用意します。
ここで用意したプロファイルは、後でIncusゲスト生成時に指定します。
incus profile copy default custom-ndppd
incus profile show custom-ndppd
incus profile edit custom-ndppd
edit前:
・流用元のdefaultのプロファイル
$ incus profile show custom-ndppd
config: {}
description: Default Incus profile
devices:
eth0:
name: eth0
network: incusbr0
type: nic
root:
path: /
pool: default
type: disk
name: custom-ndppd
used_by: []
edit後:
・description(修正): 適当な文字列
・eth0(修正): ホストのenp1s0を親とするmacvlan IF
・eth1(追加): ホストのbr-internal0に接続するBridged IF
$ incus profile show custom-ndppd
config: {}
description: Custom Incus profile for ndppd
devices:
eth0:
name: eth0
nictype: macvlan
parent: enp1s0
type: nic
eth1:
name: eth1
nictype: bridged
parent: br-internal0
type: nic
root:
path: /
pool: default
type: disk
name: custom-ndppd
used_by: []
defaultのプロファイルを流用してIncusゲスト(ubuntu-l2vpn-s)用のプロファイルを用意します。
ここで用意したプロファイルは、後でIncusゲスト生成時に利用します。
incus profile copy default custom-l2vpn-s
incus profile show custom-l2vpn-s
incus profile edit custom-l2vpn-s
edit前:
・流用元のdefaultのプロファイル
$ incus profile show custom-l2vpn-s
config: {}
description: Default Incus profile
devices:
eth0:
name: eth0
network: incusbr0
type: nic
root:
path: /
pool: default
type: disk
name: custom-l2vpn-s
used_by: []
edit後:
・description(修正): 適当な文字列
・eth1(追加): ホストのbr-internal0に接続するBridged IF
$ incus profile show custom-l2vpn-s
config: {}
description: Custom Incus profile for l2vpn-s
devices:
eth0:
name: eth0
network: incusbr0
type: nic
eth1:
name: eth1
nictype: bridged
parent: br-internal0
type: nic
root:
path: /
pool: default
type: disk
name: custom-l2vpn-s
used_by: []
VPS設定その2: l2tp用service設定
VPSのブート起動時にl2tp用のカーネルモジュール(l2tp_eth)の組み込みとブリッジIF(br-internal0)の作成を実行するoneshot serviceを定義します。
sudo bash -c 'cat > /etc/systemd/system/bridge-l2vpn-s.service' <<'EOS'
[Unit]
Description=Makes interfaces at boot
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/modprobe l2tp_eth
ExecStart=/usr/sbin/ip link add br-internal0 type bridge
ExecStart=/usr/sbin/ip link set dev br-internal0 up
TimeoutStartSec=0
RemainAfterExit=yes
[Install]
WantedBy=default.target
EOS
定義したserviceをstart・enableします。
また、lsmodでl2tp_ethが組み込まれたことと、ip aでbr-internal0が見えることを確認します。なお、bridge link showでbr-internal0をmasterとするIFの確認ができますがこの時点では何も表示されません。
sudo systemctl daemon-reload
sudo systemctl start bridge-l2vpn-s.service
sudo systemctl enable bridge-l2vpn-s.service
lsmod | grep l2tp
ip a
bridge link show | grep br-internal0
自宅サーバ設定その1: Incusプロファイル用意
defaultのプロファイルを流用してIncusゲスト(ubuntu-l2vpn-c)用のプロファイルを用意します。
ここで用意したプロファイルは、後でIncusゲスト生成時に指定します。
incus profile copy default custom-l2vpn-c
incus profile show custom-l2vpn-c
incus profile edit custom-l2vpn-c
edit前:
・流用元のdefaultのプロファイル
$ incus profile show custom-l2vpn-c
config: {}
description: Default Incus profile
devices:
eth0:
name: eth0
network: incusbr0
type: nic
root:
path: /
pool: default
type: disk
name: custom-l2vpn-c
used_by: []
edit後:
・description(修正): 適当な文字列
・eth1(追加): ホストのbr-internal0に接続するBridged IF
$ incus profile show custom-l2vpn-c
config: {}
description: Custom Incus profile for l2vpn-c
devices:
eth0:
name: eth0
network: incusbr0
type: nic
eth1:
name: eth1
nictype: bridged
parent: br-internal0
type: nic
root:
path: /
pool: default
type: disk
name: custom-l2vpn-c
used_by: []
自宅サーバ設定その2: l2tp用service設定
自宅サーバのブート起動時にl2tp用のカーネルモジュール(l2tp_eth)の組み込みとブリッジIF(br-internal0)の作成、自宅サーバの自宅L2スイッチ向け物理IF(enp2s0)をブリッジIFに差し込むことを実行するoneshot serviceを定義します。
sudo bash -c 'cat > /etc/systemd/system/bridge-l2vpn-c.service' <<'EOS'
[Unit]
Description=Makes interfaces at boot
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/modprobe l2tp_eth
ExecStart=/usr/sbin/ip link add br-internal0 type bridge
ExecStart=/usr/sbin/ip link set dev br-internal0 up
ExecStart=/usr/sbin/ip link set dev enp2s0 master br-internal0
ExecStart=/usr/sbin/ip link set dev enp2s0 up
TimeoutStartSec=0
RemainAfterExit=yes
[Install]
WantedBy=default.target
EOS
定義したserviceをstart・enableします。
また、lsmodでl2tp_ethが組み込まれたことと、ip aでbr-internal0が見えることを確認します。なお、bridge link showでbr-internal0をmasterとするIFの確認ができ、この時点ではenp2s0が表示されます。
sudo systemctl daemon-reload
sudo systemctl start bridge-l2vpn-c.service
sudo systemctl enable bridge-l2vpn-c.service
lsmod | grep l2tp
ip a
bridge link show | grep br-internal0
自宅サーバ設定その3: l2tp用netplan設定
netplanで自宅スイッチ向けIF(enp2s0)のIPアドレス自動設定を無効化します。
自宅サーバがUbuntu Desktopの場合 - NetworkManagerを指定
sudo bash -c 'cat > /etc/netplan/96-manualipv6.yaml' <<'EOS'
network:
version: 2
renderer: NetworkManager
ethernets:
enp2s0:
dhcp4: false
dhcp6: false
accept-ra: false
link-local: []
EOS
自宅サーバがUbuntu Serverの場合 - networkdを指定
sudo bash -c 'cat > /etc/netplan/96-manualipv6.yaml' <<'EOS'
network:
version: 2
renderer: networkd
ethernets:
enp2s0:
dhcp4: false
dhcp6: false
accept-ra: false
link-local: []
EOS
sudo chmod 600 /etc/netplan/96-manualipv6.yaml
sudo netplan try
手順3. Incusゲストを生成する
VPSサーバで、準備済みのプロファイルを用いてIncusゲストを生成・起動します。incus listコマンドにより、生成したIncusゲストがRUNNINGステートであることを確認します。
incus list
incus launch -p custom-ndppd images:ubuntu/noble ubuntu-ndppd
incus list
incus launch -p custom-l2vpn-s images:ubuntu/noble ubuntu-l2vpn-s
incus list
bridge link showでbr-internal0をmasterとするIF(veth)が2個表示されることを確認します。
NOTE: 表示されるvethはIncusゲストのeth1に相当。
・ubuntu-ndppdのeth1 (nictype:bridged)
・ubuntu-l2vpn-sのeth1 (nictype:bridged)
bridge link show | grep br-internal0
xx: veth41afc649@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br-internal0 state forwarding priority 32 cost 2
xx: veth41226d17@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br-internal0 state forwarding priority 32 cost 2
自宅サーバで、準備済みのプロファイルを用いてIncusゲストを生成・起動します。incus listコマンドにより、生成したIncusゲストがRUNNINGステートであることを確認します。
incus list
incus launch -p custom-l2vpn-c images:ubuntu/noble ubuntu-l2vpn-c
incus list
bridge link showでbr-internal0をmasterとするenp2s0およびvethが表示されることを確認します。
NOTE: enp2s0のstateは、L2スイッチに接続していないとdisabled。接続しているとforwarding。
NOTE: 表示されるvethはIncusゲストのeth1に相当。
・ubuntu-l2vpn-cのeth1 (nictype:bridged)
bridge link show | grep br-internal0
xx: enp2s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 master br-internal0 state disabled priority 32 cost 100
xx: veth931add8c@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br-internal0 state forwarding priority 32 cost 2
手順4. Incusゲスト ubuntu-ndppdを設定する
VPSサーバで、ubuntu-ndppdに入ります。
root@ubuntu-ndppdのコマンドプロンプトが表示されます。
incus exec ubuntu-ndppd -- bash
root@ubuntu-ndppd:~#
IPv6 fowrwarding設定
eth0とeth1で受信した自分宛てではないIPv6パケットを転送できるようにするため(ルータ動作できるようにするため)、/etc/sysctl.confのnet.ipv6.conf.all.forwarding=1のコメントアウトを外します。
・修正前: #net.ipv6.conf.all.forwarding=1
・修正後: net.ipv6.conf.all.forwarding=1
修正を反映させるためsysctl -p
を実行します。
vi /etc/sysctl.conf
sysctl -p
radvd service設定
radvdをインストールします。
apt install radvd
radvdの設定ファイル/etc/radvd.confを作成します。
bash -c 'cat > /etc/radvd.conf' <<'EOS'
interface eth1
{
AdvSendAdvert on;
prefix 2001:db8:7654:3210::/64
{
AdvOnLink on;
AdvAutonomous on;
};
};
EOS
radvdの設定ファイルを反映させるためrestartします。
NOTE: 既にenableされており、enableは不要。
systemctl daemon-reload
systemctl restart radvd
systemctl status radvd
(status表示例)
# systemctl status radvd
● radvd.service - Router advertisement daemon for IPv6
Loaded: loaded (/usr/lib/systemd/system/radvd.service; enabled; preset: enabled)
(...)
Feb 11 07:31:28 ubuntu-ndppd systemd[1]: Starting radvd.service - Router advertisement daemon for IPv6...
Feb 11 07:31:28 ubuntu-ndppd radvd[549]: config file, /etc/radvd.conf, syntax ok
Feb 11 07:31:28 ubuntu-ndppd radvd[551]: version 2.19 started
Feb 11 07:31:28 ubuntu-ndppd systemd[1]: Started radvd.service - Router advertisement daemon for IPv6.
ndppd service設定
ndppdをインストールします。
apt install ndppd
ndppdの設定ファイル/etc/ndppd.confを作成します。
bash -c 'cat > /etc/ndppd.conf' <<'EOS'
proxy eth0 {
router no
autowire yes
rule ::/0 {
iface eth1
}
}
proxy eth1 {
rule ::/0 {
iface eth0
}
}
EOS
ndppdの設定ファイルを反映させるためrestartします。
NOTE: 既にenableされており、enableは不要。
systemctl daemon-reload
systemctl restart ndppd
systemctl status ndppd
下流向けのIPv6静的route設定
下流向けに、自宅マシン(IPv6ノード)ごとに1つのIPv6静的routeを設定します。
一時的にroute追加する場合:
NOTE: 複数の自宅マシンを追加する場合はroute add
を複数実行。
ip -6 route add 2001:db8:7654:3210:1111:2222:3333:4444/128 dev eth1
ip -6 route
一時的に追加したrouteを削除する場合:
ip -6 route del 2001:db8:7654:3210:1111:2222:3333:4444/128 dev eth1
ip -6 route
恒久的にroute追加する場合:
NOTE: 複数の自宅マシンを追加する場合は-to:
行を複数追加。
bash -c 'cat > /etc/netplan/95-manualconf.yaml' <<'EOS'
network:
version: 2
renderer: networkd
ethernets:
eth1:
routes:
- to: 2001:db8:7654:3210:1111:2222:3333:4444/128
EOS
chmod 600 /etc/netplan/95-manualconf.yaml
netplan try
ip -6 route
恒久的に追加したrouteを削除する場合:
rm /etc/netplan/95-manualconf.yaml
netplan try
ip -6 route
Incusゲストから抜け、Incusホストに戻ります。
exit
手順5. Incusゲスト ubuntu-l2vpn-s/-cを設定する
wireguardサーバ用のポート開放設定
VPS上で、wireguardサーバ側となるubuntu-l2vpn-sをいったん停止します。
incus stop ubuntu-l2vpn-s
incus list
ipコマンドでenp1s0のGlobal IPv4アドレスを確認します。(例: 203.0.113.103)
ip -4 a show dev enp1s0
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq state UP group default qlen 1000
inet 203.0.113.103/xx metric 100 brd xxx.xxx.xxx.xxx scope global dynamic enp1s0
valid_lft 75440sec preferred_lft 75440sec
ipコマンドでincusbr0のPrivate IPv4アドレスを確認します。(例: 10.91.163.1)
ip -4 a show dev incusbr0
6: incusbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
inet 10.91.163.1/24 scope global incusbr0
valid_lft forever preferred_lft forever
デフォルトではincusbr0に接続する各IncusゲストのIFのIPv4アドレスはDHCPで動的IPになっていますが、これを静的IPに設定変更します。(例: 静的IP 10.91.163.3に設定)
また、その静的IPアドレスの特定ポート(例: 53000)にインターネットからアクセスできるようにするためのポート開放(ポートフォワーディング)を設定します。
incus config device override ubuntu-l2vpn-s eth0 ipv4.address=10.91.163.3
incus config device add ubuntu-l2vpn-s port53000 proxy listen=udp:203.0.113.103:53000 connect=udp:10.91.163.3:53000 nat=true
ubuntu-l2vpn-sに適用されているconfigを確認します。プロファイルをオーバライドしたeth0デバイス設定、および、プロファイルには無かったport53000という名のproxyタイプのデバイス設定がdevicesパートに表示されること確認します。
incus config show ubuntu-l2vpn-s
(...)
devices:
eth0:
ipv4.address: 10.91.163.3
name: eth0
network: incusbr0
type: nic
port53000:
connect: udp:10.91.163.3:53000
listen: udp:203.0.113.103:53000
nat: "true"
type: proxy
(...)
停止させていたubuntu-l2vpn-sを起動します。(configが適用されます。)
incus start ubuntu-l2vpn-s
incus list
wireguard設定
Ref3: https://pc.watch.impress.co.jp/docs/column/ubuntu/1606110.html
Ref4: https://hachune.net/blog/2022/05/20/l2tp-wireguard.html
Ref5: https://www.man7.org/linux/man-pages/man8/ip-l2tp.8.html
VPSで、ubuntu-l2vpn-sに入ります。
root@ubuntu-l2vpn-sのコマンドプロンプトが表示されます。
incus exec ubuntu-l2vpn-s -- bash
root@ubuntu-l2vpn-s:~#
wireguardをインストールします。
apt install wireguard
wireguardサーバ側の秘密鍵を生成してserver.keyファイルに保存します。
wireguardサーバ側の公開鍵を生成してserver.pubファイルに保存します。
wg genkey | tee /etc/wireguard/server.key
cat /etc/wireguard/server.key | wg pubkey | tee /etc/wireguard/server.pub
chmod 600 /etc/wireguard/server.{key,pub}
続けて、自宅サーバで、ubuntu-l2vpn-cに入ります。
root@ubuntu-l2vpn-cのコマンドプロンプトが表示されます。
incus exec ubuntu-l2vpn-c -- bash
root@ubuntu-l2vpn-c:~#
wireguardをインストールします。
apt install wireguard
wireguardクライアント側の秘密鍵を生成してclient.keyファイルに保存します。
wireguardクライアント側の公開鍵を生成してclient.pubファイルに保存します。
wg genkey | tee /etc/wireguard/client.key
cat /etc/wireguard/client.key | wg pubkey | tee /etc/wireguard/client.pub
chmod 600 /etc/wireguard/client.{key,pub}
wireguardサーバ側の設定ファイルを作成します。
・PrivateKey: 自分(サーバ側)の秘密鍵を指定
・Address: 自分(サーバ側)のwg0インタフェースに割り当てるIPアドレスを指定
・ListenPort: wireguardクライアントからの接続を待ち受けるサーバ側のudpポート番号を指定
・PublicKey: 相手(クライアント側)の公開鍵を指定
・AllowedIPs: wg0インタフェースへrouteするroute先のIPまたはサブネットを指定
bash -c 'cat > /etc/wireguard/wg0.conf' <<'_EOS_'
[Interface]
PrivateKey = sssssssssssssssssssssssssssssssssssssssssss=
Address = 10.0.0.1
ListenPort = 53000
[Peer]
PublicKey = ccccccccccccccccccccccccccccccccccccccccccc=
AllowedIPs = 10.0.0.2/32
_EOS_
wireguardクライアント側の設定ファイルを作成します。
・PrivateKey: 自分(クライアント側)の秘密鍵を指定
・Address: 自分(クライアント側)のwg0インタフェースに割り当てるIPアドレスを指定
・PublicKey: 相手(サーバ側)の公開鍵を指定
・EndPoint: wireguardサーバのIPアドレスとudpポート番号を指定
NOTE: EndPointにはポート開放したVPSのGlobal IPアドレスを指定することに注意
・AllowedIPs: wg0インタフェースへrouteするroute先のIPまたはサブネットを指定
bash -c 'cat > /etc/wireguard/wg0.conf' <<'_EOS_'
[Interface]
PrivateKey = ccccccccccccccccccccccccccccccccccccccccccc=
Address = 10.0.0.2
[Peer]
PublicKey = sssssssssssssssssssssssssssssssssssssssssss=
EndPoint = 203.0.113.103:53000
AllowedIPs = 10.0.0.0/24
_EOS_
wg0指定でwireguardサーバを起動します。ip aコマンドでwg0が表示されることを確認します。
NOTE: サーバ側は常時起動のためenableにします。
systemctl enable --now wg-quick@wg0
systemctl status wg-quick@wg0
ip a
(status表示例)
# systemctl status wg-quick@wg0
● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
Loaded: loaded (/usr/lib/systemd/system/wg-quick@.service; enabled; preset: enabled)
(...)
Feb 11 13:03:33 ubuntu-l2vpn-s systemd[1]: Starting wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0...
Feb 11 13:03:33 ubuntu-l2vpn-s wg-quick[672]: [#] ip link add wg0 type wireguard
Feb 11 13:03:33 ubuntu-l2vpn-s wg-quick[672]: [#] wg setconf wg0 /dev/fd/63
Feb 11 13:03:33 ubuntu-l2vpn-s wg-quick[672]: [#] ip -4 address add 10.0.0.1 dev wg0
Feb 11 13:03:33 ubuntu-l2vpn-s wg-quick[672]: [#] ip link set mtu 1420 up dev wg0
Feb 11 13:03:33 ubuntu-l2vpn-s wg-quick[672]: [#] ip -4 route add 10.0.0.2/32 dev wg0
Feb 11 13:03:33 ubuntu-l2vpn-s systemd[1]: Finished wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0.
wireguardクライアントを起動し、ip aコマンドでwg0が表示されることを確認します。
wireguardサーバにpingが通ることを確認します。
wg-quick up wg0
ip a
ping 10.0.0.1
pingが通ったらwireguardクライアントをいったん停止します。
wg-quick down wg0
l2tp設定
wireguardサーバ側のl2tp設定を行うシェルスクリプトを作成します。
bash -c 'cat > ./l2vpn-s.sh' <<'EOS'
#!/bin/sh
# L2TP
ip l2tp add tunnel \
tunnel_id 3939 \
peer_tunnel_id 3940 \
encap udp \
local 10.0.0.1 \
remote 10.0.0.2 \
udp_sport 1701 \
udp_dport 1701
ip l2tp add session \
tunnel_id 3939 \
session_id 3941 \
peer_session_id 3942
ip link set dev l2tpeth0 up mtu 1500
# Bridge
ip link add br-l2tp0 type bridge
ip link set dev br-l2tp0 up
ip link set dev l2tpeth0 master br-l2tp0
ip link set dev eth1 master br-l2tp0
ip link set dev eth1 up
EOS
chmod 755 ./l2vpn-s.sh
wireguardクライアント側のl2tp設定を行うシェルスクリプトを作成します。
NOTE: wireguardクライアントの起動もシェルスクリプトの中で実行します。
bash -c 'cat > ./l2vpn-c.sh' <<'EOS'
#!/bin/sh
# WireGuard
wg-quick up wg0
# L2TP
ip l2tp add tunnel \
tunnel_id 3940 \
peer_tunnel_id 3939 \
encap udp \
local 10.0.0.2 \
remote 10.0.0.1 \
udp_sport 1701 \
udp_dport 1701
ip l2tp add session \
tunnel_id 3940 \
session_id 3942 \
peer_session_id 3941
ip link set dev l2tpeth0 up mtu 1500
# Bridge
ip link add br-l2tp0 type bridge
ip link set dev br-l2tp0 up
ip link set dev l2tpeth0 master br-l2tp0
ip link set dev eth1 master br-l2tp0
ip link set dev eth1 up
EOS
chmod 755 ./l2vpn-c.sh
サーバ側のシェルスクリプトを実行します。
./l2vpn-s.sh
クライアント側のシェルスクリプトを実行します。
./l2vpn-c.sh
自宅L2スイッチ先に適当な自宅マシン(IPv6ノード)を用意し、そこからインターネットへpingが通ることを確認します。(例: Google DNSへping)
ping -6 2001:4860:4860::8888
Incusゲストから抜け、Incusホストに戻ります。以上で手順完了です。
./exit
./exit
付録: 運用手順
VPSをrebootした後の復旧手順
reboot前にRUNNINGステートだったIncusゲストは、reboot後にRUNNINGステートに戻ります。ただし再開しているためシェルスクリプトを再度実行する必要があります。
incus exec ubuntu-l2vpn-s -- ./l2vpn-s.sh
自宅サーバをrebootした後の復旧手順
reboot前にRUNNINGステートだったIncusゲストは、reboot後にRUNNINGステートに戻ります。ただし再開しているためシェルスクリプトを再度実行する必要があります。
incus exec ubuntu-l2vpn-c -- ./l2vpn-c.sh
WireGuard/L2TPを一時的に切断/復旧する手順
自宅サーバ側のubuntu-l2vpn-cを停止することで切断となります。
incus stop ubuntu-l2vpn-c
接続を復旧させる場合は、ubuntu-l2vpn-cを開始し、シェルスクリプトを再度実行します。
incus start ubuntu-l2vpn-c
incus exec ubuntu-l2vpn-c -- ./l2vpn-c.sh
下流の自宅マシン(IPv6ノード)を追加する手順
Incusゲストubuntu-ndppdのnetplan設定ファイルに- to:
行を追加してnetplanコマンドで反映させます。
例) 2001:db8:7654:3210:5555:6666:7777:8888/128を行追加
vi /etc/netplan/95-manualconf.yaml
(...)
ethernets:
eth1:
routes:
- to: 2001:db8:7654:3210:1111:2222:3333:4444/128
- to: 2001:db8:7654:3210:5555:6666:7777:8888/128
netplan try
ip -6 route
以上
Discussion