これで作られるもの
WireGuardを実行する1つのインスタンス。各クライアントにプライベートIPv4アドレス、独自の/48からルーティングされたIPv6アドレス、そしてトンネル内に存在するリゾルバを割り当てます。DNSクエリが他のトラフィックとは異なる経路を取ることがないようにです。ファイアウォールは双方向でデフォルトドロップです。転送はトンネルインターフェースに対してのみ有効で、かつアウトバウンドのみです。
AMS-01のR-4でDebian 13でテスト済み。WireGuardはシングルフローでカーネルサイドなので、複数ギガビットを押し出すまでは、コアを増やしても意味がありません。もっと重要なのはサイトです。実際にいる場所に最も近いものを選んでください。ここで追加するミリ秒は、すべてのパケットに追加されるからです。
始める前に
- デプロイ済みのインスタンスとSSHでのrootアクセス。
- パネルでIPv6 /48アドオンを有効にしていること。付属の/64は単一クライアントで動作しますが、単一の/64からクライアントごとのサブネットを出すには近隣探索のプロキシが必要で、それは設定ではなく趣味です。
- インスタンスを指すホスト名。以下ではすべて
vpn.example.comを使用します。 - ここにあるすべての
2001:db8:アドレスはドキュメント用スペースです。プレフィックスをインスタンスページに表示されているものに置き換えてください。
1. パッケージとカーネル設定
apt update && apt full-upgrade -y
apt install -y wireguard-tools nftables unbound qrencode
ip -br linkその最後のコマンドは、外向きインターフェース名を表示します。当社のKVMイメージではens3です。異なる場合は、以下すべてで置き換えてください。次にカーネル:
cat > /etc/sysctl.d/99-wireguard.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.ens3.accept_ra = 2
net.ipv4.conf.all.rp_filter = 1
EOF
sysctl --systemaccept_ra = 2の行は忘れがちです。IPv6転送を有効にすると、カーネルはルーター広告の受け入れを停止し、デフォルトルートは10分以内に消え、マシンはv4で応答しながらv6で暗闇になります。2に設定すると、転送ホストで広告の受け入れを維持します。
2. 鍵
install -d -m 700 /etc/wireguard
umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub
wg genkey | tee /etc/wireguard/laptop.key | wg pubkey > /etc/wireguard/laptop.pub
wg genpsk > /etc/wireguard/laptop.psk事前共有鍵はこの構成ではオプションではありません。コストはゼロで、各設定で1行です。今日単に安全なトンネルと、現在トラフィックを記録して後で解読する敵に対しても安全であり続けるトンネルの違いです。
3. サーバーインターフェース
/etc/wireguard/wg0.confを書き、マークされた場所に鍵の内容を貼り付けます:
[Interface]
Address = 10.7.0.1/24, 2001:db8:1a2b:7::1/64
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>
MTU = 1420
[Peer]
# laptop
PublicKey = <contents of /etc/wireguard/laptop.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
AllowedIPs = 10.7.0.2/32, 2001:db8:1a2b:7::2/128サーバー側ではAllowedIPsはルーティングテーブルであり、許可リストではありません。各ピアに、それが所有するアドレスだけを正確に与え、それ以上広くしないでください。そうしないと、2つのクライアントが同じルートを争い、負けた方は単にパケットを受信しなくなります。
chmod 600 /etc/wireguard/wg0.conf4. トンネル内のリゾルバ
クライアントをパブリックリゾルバに向けると、意味がかなり失われます。Unboundはすでにインストールされています。/etc/unbound/unbound.conf.d/tunnel.confを与えてください:
server:
interface: 10.7.0.1
interface: 2001:db8:1a2b:7::1
access-control: 10.7.0.0/24 allow
access-control: 2001:db8:1a2b:7::/64 allow
do-ip6: yes
prefetch: yes
hide-identity: yes
hide-version: yes
qname-minimisation: yesUnboundはトンネルが存在する前に起動に失敗します。これらのアドレスがまだ上がっていないためです。うまく順序付けて対抗するのではなく、適切にシーケンスします:
systemctl edit unbound[Unit]
[email protected]
[email protected]5. ファイアウォール
/etc/nftables.conf全体を置き換えます:
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iif lo accept
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
tcp dport 22 accept
udp dport 51820 accept
iifname "wg0" udp dport 53 accept
iifname "wg0" tcp dport 53 accept
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname "wg0" oifname "ens3" accept
iifname "wg0" oifname "wg0" drop
}
chain output {
type filter hook output priority filter; policy accept;
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.7.0.0/24 oifname "ens3" masquerade
}
}何が欠けているかに注意してください:IPv6用のNATテーブルはありません。クライアントは/48から自分のアドレスでegressします。これがそもそも/48を取得する理由のすべてです。iifname "wg0" oifname "wg0" dropの行はピア同士の到達を防ぎます。これは、意図的にメッシュを構築しているのでない限り望ましいです。
systemctl enable --now nftables
nft list ruleset | head -206. 起動
systemctl enable --now wg-quick@wg0
systemctl restart unbound
wg show wg07. クライアント
[Interface]
PrivateKey = <contents of /etc/wireguard/laptop.key>
Address = 10.7.0.2/24, 2001:db8:1a2b:7::2/64
DNS = 10.7.0.1
MTU = 1420
[Peer]
PublicKey = <contents of /etc/wireguard/server.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25電話の場合は、サーバー上でQRコードに変換してターミナルを撮影します:
qrencode -t ansiutf8 < /root/laptop.confDebianまたはUbuntuクライアントでは、DNS =の行にopenresolvのインストールが必要です。そうしないとwg-quickは警告を出力し、古いリゾルバを静かに残します。これは、完全に機能し、すべてのルックアップをリークするトンネルの最も一般的な原因です。
検証
4つのチェックを順に行います。失敗したものは、どのステップに戻るべきかを示します。
# on the server, after connecting the client
wg show wg0 latest-handshakes
wg show wg0 transfer過去2分以内のハンドシェイクタイムスタンプと、双方向の非ゼロカウンタは、暗号化とルーティングの両方が正常であることを意味します。
# on the client
ping -c3 10.7.0.1
ping -c3 2001:db8:1a2b:7::1
dig @10.7.0.1 paragonvps.com AAAA +short3番目のコマンドは、トンネルリゾルバが応答していることを証明します。タイムアウトした場合は、wg0が存在する前にunboundが起動しました。再起動してください。
最後のチェックは、トラフィックが意図した場所から出ることを証明する唯一のチェックであり、2台目のマシンが必要です。フリート内の他のインスタンスならどこでも、どの都市でも構いません:
# on the second instance
nc -lv 9101
# on the client, tunnel up
curl -m5 -4 http://second.example.com:9101/
curl -m5 -6 http://second.example.com:9101/リスナーは各接続の送信元アドレスを出力します。v4の試行は、マスカレードされたためWireGuardサーバーから到着するはずです。v6の試行は、クライアント自身のトンネルアドレスから/48内で、変更されずに到着するはずです。これが「routed」の意味であり、「proxied」ではないのです。
問題が発生した場合
| 症状 | 原因 | 修正 |
|---|---|---|
| ハンドシェイク成功、データが通らない | 転送オフ、またはフォワードチェーンがドロップ | sysctl net.ipv4.ip_forward、次にフォワードチェーンを再読 |
| 小さなリクエストはok、大きなダウンロードがハング | MTUとパス探索 | 両方の設定をMTU = 1380に下げて再試行 |
| 起動後約10分でIPv6が死ぬ | 転送がルーター広告を殺した | 外向きインターフェースでaccept_ra = 2 |
| DNSがトンネル外で解決 | クライアントがDNS =を無視 | クライアントにopenresolvをインストール |
| 再起動後にすべて消える | ユニットが有効になっていない | systemctl enable wg-quick@wg0 nftables unbound |
ここから先の賢明な次のステップは、別のリージョンに2番目のエンドポイントを置き、それらのいずれかが応答を停止したときに通知する監視スタックを構築することです。両方ともガイドの他の場所でカバーされています。ネットワークページは、エッジがトラフィックを処理する方法を説明しています。