Communitygithub.com

홈랩 WireGuard VPN

WireGuard VPN 서버 설정, 피어 구성, 키 생성, 분할 터널링 vs 전체 터널 라우팅, 모바일 및 노트북 클라이언트에서 홈 네트워크로의 원격 액세스를 지원합니다. 홈 네트워크에 원격으로 접속하기 위해 WireGuard를 설정하거나 분할/전체 터널 라우팅을 결정할 때 사용하세요.

홈랩 WireGuard VPN란 무엇인가요?

이 스킬은 홈랩 환경에서 **WireGuard VPN**을 설정하고 관리하는 방법을 종합적으로 제공합니다. WireGuard는 OpenVPN보다 설정이 간단하고 대부분의 대안보다 빠른 현대적인 VPN 프로토콜로, 이 스킬은 라즈베리 파이, Linux 호스트, pfSense, OPNsense 등 다양한 플랫폼에서의 서버 설정부터 클라이언트 구성, 키 생성 및 피어 관리, 분할 터널링과 전체 터널링 간의 선택, DDNS 설정, 문제 해결까지 모든 과정을 다룹니다. 각 구성 예시는 실제 명령어와 설정 파일을 포함하며, 특히 iptables 포워딩 규칙과 키 파일 권한에 대한 주의 사항을 강조합니다. Python 스크립트를 통한 키 생성 자동화, pfSense/OPNsense에서의 WireGUARD 설정, 그리고 분할 터널링(홈 트래픽만 VPN을 통해 라우팅)과 전체 터널링(모든 트래픽을 VPN을 통해 라우팅)의 장단점과 사용 사례를 명확히 설명합니다. 또한 비공개 키를 버전 관리에 저장하지 않는 것, 모바일 클라이언트에 PersistentKeepalive를 설정하는 것, 범위가 지정된 iptables 포워딩 규칙을 사용하는 것 등의 모범 사례와 안티 패턴을 제시하여 안전하고 효율적인 VPN 운영을 지원합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/homelab-wireguard-vpn

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

홈랩 WireGuard VPN은(는) 무엇을 하나요?

WireGuard는 빠르고 현대적인 VPN 프로토콜입니다. 홈 네트워크에 원격으로 접속하기에 적합한 선택으로, OpenVPN보다 설정이 간단하고 대부분의 대안보다 빠릅니다.

모든 구성 예시는 일반적인 설정을 보여줍니다. 특히 iptables 포워딩 규칙과 키 파일 권한을 시스템에 적용하기 전에 각 명령어를 검토하고, 유지 관리 시간에 변경 사항을 적용하세요.

사용 시기

  • 라즈베리 파이, 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 → Add Tunnel
  Interface Keys: Generate (키 쌍 자동 생성)
  Listen Port: 51820
  Interface Address: 10.8.0.1/24

# Add Peer (클라이언트당 하나):
  Public Key: <클라이언트 공개 키>
  Allowed IPs: 10.8.0.2/32

# WireGuard 인터페이스 할당:
  Interfaces → Assignments → Add (wg0 선택)
  인터페이스 활성화, IP 불필요 (터널 구성에서 설정)

# 방화벽 규칙:
  WAN → UDP 포트 51820 인바운드 허용 (클라이언트가 서버에 연결 가능)
  WireGuard 인터페이스 → 액세스하려는 LAN 네트워크로의 트래픽 허용

홈 서버용 DDNS (Dynamic DNS)

대부분의 홈 인터넷 연결은 동적 IP를 사용합니다. DDNS를 사용하면 IP 변경 후에도 VPN 엔드포인트에 접속할 수 있습니다.

# 옵션 1: Cloudflare DDNS — 자격 증명을 시크릿 파일에 저장, 인라인 금지
# env 파일을 사용하는 docker-compose 항목:
  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 (mode 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 파일에 저장
  • 범위가 지정된 iptables 포워딩 규칙(wg0 인바운드만) 사용, 포괄적인 FORWARD ACCEPT 금지
  • 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/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

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.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

관련 스킬