Communitygithub.com

ホームラボ WireGuard VPN

WireGuard VPNサーバーのセットアップ、ピア設定、鍵生成、スプリットトンネリングとフルトンネルルーティングの選択、およびモバイル・ラップトップクライアントからのホームネットワークへのリモートアクセスを実現します。ホームネットワークへのリモートアクセスにWireGuardを設定する際や、スプリットトンネルとフルトンネルのどちらを選ぶかを決める際に使用します。

ホームラボ WireGuard VPN とは?

このスキルは、ホームラボ環境向けにWireGuard VPNをセットアップするための包括的なガイドです。OpenVPNよりもシンプルな設定で、高速で現代的VPNプロトコルであるWireGuardを、Raspberry Pi、Linuxホスト、pfSense、ルーターなどにインストールし、設定する手順を提供します。サーバーとクライアントの鍵ペア生成、ピア設定ファイル作成、スプリットトンネリング(ホームネットワークトラフィックのみルーティング)とフルトンネル(全トラフィックをルーティング)の違いと選択基準について詳細に解説します。さらに、DDNS(ダイナミックDNS)の設定方法や、接続が確立しない場合のトラブルシューティング手順、非推奨パターン(アンチパターン)とベストプラクティスも網羅しており、開発者やシステム管理者が安全かつ効率的にWireGuardを導入・運用できるよう支援します。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/homelab-wireguard-vpn

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

ホームラボ WireGuard VPN は何をしますか?

WireGuardは、高速で現代的なVPNプロトコルです。ホームネットワークへのリモートアクセスに最適な選択肢であり、OpenVPNよりも設定が簡単で、ほとんどの代替手段よりも高速です。

すべての設定例は一般的な構成を示しています。各コマンド(特にiptables転送ルールと鍵ファイルのパーミッション)をシステムに適用する前に確認し、メンテナンス時間帯に変更を行ってください。

使用するタイミング

  • Raspberry Pi、Linuxホスト、pfSense、またはルーター上でWireGuardサーバーをセットアップする場合
  • WireGuardの鍵ペアを生成し、ピア設定ファイルを作成する場合
  • スマートフォンやラップトップからホームネットワークにリモートアクセスできるように設定する場合
  • スプリットトンネリング(ホームトラフィックのみルーティング)とフルトンネル(全トラフィックをルーティング)の違いを説明する場合
  • WireGuardの接続が確立しない問題をトラブルシューティングする場合
  • 複数クライアント向けにピア設定の生成を自動化する場合

WireGuardの仕組み

スマートフォン (WireGuard クライアント)
    │
    │  暗号化UDPトンネル (ポート51820)
    │
ホームルーター (WireGuard サーバー — パブリックIPまたはDDNSが必要)
    │
    ホームネットワーク (192.168.1.0/24, NAS, Pi など)

すべてのデバイスは鍵ペア(公開鍵+秘密鍵)を持ちます。
サーバーは各クライアントの公開鍵を把握します。
クライアントはサーバーの公開鍵とエンドポイント(IP:ポート)を把握します。
トラフィックは、中央サーバーや認証局なしでエンドツーエンドで暗号化されます。

サーバー設定 (Linux)

# WireGuardのインストール
sudo apt update && sudo apt install wireguard -y

# サーバー鍵ペアの生成 — 最初から秘密パーミッションでファイルを作成
sudo mkdir -p /etc/wireguard
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server_private.key'
sudo sh -c 'wg pubkey < /etc/wireguard/server_private.key > /etc/wireguard/server_public.key'

# サーバー設定の書き出し — 実際の秘密鍵の値に置き換えてください
# 秘密鍵をバージョン管理や共有してはいけません
sudo tee /etc/wireguard/wg0.conf << 'EOF'
[Interface]
Address = 10.8.0.1/24              # VPNサブネット — サーバーは .1 を取得
ListenPort = 51820
PrivateKey = <paste_server_private_key_here>

# スコープ制限された転送ルール:VPNトラフィックの出入力を許可し、包括的なFORWARD ACCEPTは行わない
PostUp   = iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
PostUp   = iptables -A FORWARD -i eth0 -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostUp   = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -o eth0 -j ACCEPT
PostDown = iptables -D FORWARD -i eth0 -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# スマートフォン — 実際のスマートフォンの公開鍵に置き換えてください
PublicKey = <phone_public_key>
AllowedIPs = 10.8.0.2/32

[Peer]
# ラップトップ — 実際のラップトップの公開鍵に置き換えてください
PublicKey = <laptop_public_key>
AllowedIPs = 10.8.0.3/32
EOF
sudo chmod 600 /etc/wireguard/wg0.conf

# eth0 を実際のアウトバウンドインターフェース名に置き換えてください
# 確認コマンド: ip route show default

# IP転送の有効化(サーバーを介したトラフィックルーティングに必要)
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system

# WireGuardの起動と自動起動の有効化
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0

クライアント設定

# クライアントデバイスごとに一意の鍵ペアを生成
# クライアント上で実行するか、サーバー上で生成して秘密鍵を安全に転送 — 平文では絶対に転送しない
umask 077
wg genkey | tee phone_private.key | wg pubkey > phone_public.key

# クライアント設定ファイル (phone_wg0.conf):
[Interface]
PrivateKey = <phone_private_key>
Address = 10.8.0.2/32
DNS = 192.168.1.2                  # オプション: トンネル経由でPi-holeをDNSとして使用

[Peer]
PublicKey = <server_public_key>
Endpoint = your-home-ip.ddns.net:51820  # パブリックIPまたはDDNSホスト名
AllowedIPs = 192.168.1.0/24            # スプリットトンネル: ホームネットワークトラフィックのみ
# AllowedIPs = 0.0.0.0/0, ::/0        # フルトンネル: すべてのトラフィックをVPN経由

PersistentKeepalive = 25              # NATホールを維持(モバイルクライアントに必須)

スプリットトンネル vs フルトンネル

# スプリットトンネル: AllowedIPs = 192.168.1.0/24
  ホームネットワーク宛てのトラフィックのみがVPNを通過します。
  YouTubeやSpotifyなどのインターネットトラフィックは直接送信されます — モバイルでのパフォーマンスが向上します。
  最適な用途: 「NASとPiにどこからでもアクセスしたいだけ」

# フルトンネル: AllowedIPs = 0.0.0.0/0, ::/0
  すべてのトラフィックがホームインターネット接続を経由します。
  用途: ホームDNS/Pi-hole広告ブロックの利用。
  欠点: ホームのアップロード速度がボトルネックになり、どこでも遅くなります。

# マルチサブネットスプリットトンネル(最も一般的なホームラボのユースケース):
  AllowedIPs = 192.168.10.0/24, 192.168.20.0/24, 192.168.30.0/24, 10.8.0.0/24
  すべてのVLANトラフィックをトンネル経由でルーティングし、インターネットは直接接続します。

鍵生成とピア管理

import subprocess

def generate_keypair() -> tuple[str, str]:
    """WireGuard鍵ペアを生成します。 (秘密鍵, 公開鍵) を返します。"""
    private = subprocess.check_output(["wg", "genkey"]).decode().strip()
    public = subprocess.run(
        ["wg", "pubkey"], input=private.encode(), capture_output=True
    ).stdout.decode().strip()
    return private, public

def generate_preshared_key() -> str:
    return subprocess.check_output(["wg", "genpsk"]).decode().strip()

def build_client_config(
    client_private_key: str,
    client_vpn_ip: str,       # 例: "10.8.0.3"
    server_public_key: str,
    server_endpoint: str,     # 例: "home.example.com:51820"
    allowed_ips: str = "192.168.1.0/24",
    dns: str = "",
) -> str:
    dns_line = f"DNS = {dns}\n" if dns else ""
    return f"""[Interface]
PrivateKey = {client_private_key}
Address = {client_vpn_ip}/32
{dns_line}
[Peer]
PublicKey = {server_public_key}
Endpoint = {server_endpoint}
AllowedIPs = {allowed_ips}
PersistentKeepalive = 25
"""

def build_server_peer_block(
    client_public_key: str,
    client_vpn_ip: str,
    comment: str = "",
) -> str:
    comment_line = f"# {comment}\n" if comment else ""
    return f"""
{comment_line}[Peer]
PublicKey = {client_public_key}
AllowedIPs = {client_vpn_ip}/32
"""

秘密鍵はソース管理外に保管してください。このスクリプトを使用する場合は、鍵素材をモード600のファイルに書き込み、決してログ出力や表示をしないでください。

pfSense / OPNsense WireGuard

# pfSense: VPN → WireGuard → トンネル追加
  インターフェースキー: 生成(鍵ペアを自動生成)
  リッスンポート: 51820
  インターフェースアドレス: 10.8.0.1/24

# ピア追加(クライアントごとに1つ):
  公開鍵: <クライアントの公開鍵>
  許可IP: 10.8.0.2/32

# WireGuardインターフェースの割り当て:
  インターフェース → 割り当て → 追加 (wg0を選択)
  インターフェースを有効化、IPは不要(トンネル設定で設定済み)

# ファイアウォールルール:
  WAN → UDPポート51820のインバウンドを許可(クライアントがサーバーに到達できるように)
  WireGuardインターフェース → アクセス可能にしたいLANネットワークへのトラフィックを許可

DDNS(ダイナミックDNS)のホームサーバー設定

ほとんどのホームインターネット接続は動的IPです。DDNSを使用して、IP変更後もVPNエンドポイントに到達可能にします。

# オプション1: Cloudflare DDNS — クレデンシャルはシークレットファイルに保存し、インラインには記述しない
# docker-composeのエントリ(envファイル使用):
  ddns-updater:
    image: qmcgaw/ddns-updater
    env_file: ./ddns.env   # zone_id と token はここに保存し、composeファイルには記述しない
    restart: unless-stopped

# ddns.env (chmod 600、gitにはコミットしない):
# SETTINGS_CLOUDFLARE_ZONE_ID=your_zone_id
# SETTINGS_CLOUDFLARE_TOKEN=your_api_token

# オプション2: DuckDNS(無料、シンプル)
  duckdns.org にサインアップ → トークンとサブドメインを取得 (myhome.duckdns.org)
  トークンを /etc/ddns.env (モード600) に保存し、root所有の小さなスクリプトを使用:

  # /usr/local/bin/update-duckdns
  #!/bin/sh
  set -eu
  . /etc/ddns.env
  curl --fail --silent --show-error --max-time 10 \
    --get "https://www.duckdns.org/update" \
    --data-urlencode "domains=myhome" \
    --data-urlencode "token=${DUCKDNS_TOKEN}" \
    --data-urlencode "ip="

  # cronジョブ:
  */5 * * * * /usr/local/bin/update-duckdns >/dev/null 2>&1

トラブルシューティング

# WireGuardのステータスと最終ハンドシェイクを確認
sudo wg show

# 「latest handshake」が表示されない、または非常に古い場合、トンネルは接続されていません。
# 確認事項:
# 1. ルーター/ファイアウォールでUDPポート51820が開放されていますか?
sudo ufw status  # またはpfSense/UniFiのファイアウォールルールを確認

# 2. クライアント設定のサーバー公開鍵は正しいですか?
sudo wg show wg0 public-key   # クライアント設定のものと比較

# 3. サーバーでIP転送が有効になっていますか?
cat /proc/sys/net/ipv4/ip_forward  # 1 であるべき

# 4. クライアントのAllowedIPs は、到達しようとしているIPをカバーしていますか?
# AllowedIPs = 192.168.1.0/24 で 192.168.3.5 に到達しようとしている場合、ルーティングされません。

# カーネルログでWireGuardエラーを確認
dmesg | grep wireguard

# WireGuardの再起動
sudo wg-quick down wg0 && sudo wg-quick up wg0

アンチパターン

# 悪い例: 秘密鍵をバージョン管理に保存したり、共有したりする
# 秘密鍵はパスワードと同等です — gitにコミットしてはいけません

# 悪い例: モバイルで AllowedIPs = 0.0.0.0/0 を使用し、影響を考慮しない
# フルトンネルはすべてのモバイルトラフィックをホームのアップロード経由でルーティングします — 通常は遅い

# 悪い例: モバイルクライアントでPersistentKeepaliveを設定しない
# NATの背後にあるモバイルクライアントは、これがないとアイドルトンネルが切断されます

# 悪い例: ファイアウォールでポート51820を開放したが、サーバーでIP転送を忘れる
# トンネルは接続されるがトラフィックはルーティングされない — デバッグが混乱します

# 悪い例: 複数のクライアントデバイスで鍵ペアを共有する
# 各デバイスは独自の一意の鍵ペアを持つ必要があります — 共有鍵はセキュリティモデルを破壊します

# 悪い例: 包括的な「FORWARD ACCEPT」iptablesルールを使用する
# 転送ルールはwg0インターフェースと方向にのみスコープ制限する

ベストプラクティス

  • クライアントデバイスごとに一意の鍵ペアを生成 — 鍵を再利用しない
  • モバイルではスプリットトンネリング(AllowedIPs = <ホームサブネット>)を使用
  • すべてのモバイルクライアントで PersistentKeepalive = 25 を設定
  • ISPが動的IPを割り当てる場合はDDNSを使用し、クレデンシャルはインラインではなく env ファイルに保存
  • 包括的なFORWARD ACCEPTではなく、スコープ制限されたiptables転送ルール(wg0のインバウンドのみ)を使用
  • クライアント設定にPi-holeのIPを DNS = として追加し、VPN経由で広告ブロックを取得
  • サーバー鍵ペアを定期的にローテーションし、すべてのクライアント設定を更新

関連スキル

  • homelab-network-setup
  • homelab-vlan-segmentation
  • homelab-pihole-dns

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

関連スキル