切腹倶楽部
日々是切腹
素WireGuardでVPNのセットアップ
重い腰を上げてやりましたとさ。
なぜに素WireGuardなのか
- Tailscaleはお行儀が悪くてログインすら外部IdP依存なのがしんどい
- NetBirdも微妙にアレだった
- ログイン情報は自前で持ってるくせに2FAは外部IdP依存なのがびみょい
- AndroidクライアントがカーネルWireGuardを使わないのもなんかアレ(これはTailscaleも同じ?)
- Headscaleは試してないけど,どうせならTailscale系をやめたかった
やったこと
外部から到達可能なVPSを拠点にして疑似サーバ・クライアント方式で接続する方針でやった。
サーバ側は,ArchWikiを手掛りにしてsystemd.netdev(5)とsystemd.network(5)を読みつつ,既に使用していたsystemd-networkdを用いて設定した。
クライアント側は各々の流儀に従って設定した。
VPNのアドレスには10.0.0.0/24を用いた。
自分の環境ではまだ衝突していない。
特記事項
ここが本題。
- サーバ・クライアント方式でやるなら
net.ipv4.ip_forward=1を設定しろとArchWikiに書いてあったので,サーバの/etc/systemd/network/wg0.networkの[Network]にIPv4Forwarding=yesを書いた - NAT内のサーバ(VPN接続においてはクライアントだが)は
PersistentKeepaliveを設定しないと疎通できなかった- 値は
wg(8)で紹介されている25を設定した。これで困っていない
- 値は
- サーバがdockerと同居しているとVPN内のパケットの転送がうまくいかないことがあった
- dockerがパケット制御のためにiptablesを弄くり回してくれていた
- 今の時代にiptablesを学ぶのもなんだかなぁだったので,
/etc/docker/daemon.jsonを{"firewall-backend":"nftables"}として,nftables.serviceでwg0のパケット転送を許可する感じにした - Linuxネットワークのいい勉強になった
付録
/etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
set blacklist {
type ipv4_addr
elements = {
114.514.1919.810
}
}
chain input {
ip saddr @blacklist drop
type filter hook input priority filter; policy accept;
}
chain forward {
type filter hook forward priority filter; policy accept;
iifname "wg0" oifname "wg0" accept
}
chain output {
type filter hook output priority filter; policy accept;
}
}