Communitygithub.com

homelab-wireguard-vpn

Configuração de servidor WireGuard VPN, configuração de peers, geração de chaves, roteamento split tunnel vs full tunnel e acesso remoto à rede doméstica a partir de dispositivos móveis e laptops. Use ao configurar WireGuard para acesso remoto à rede doméstica ou ao decidir entre split e full tunnel.

O que é homelab-wireguard-vpn?

Esta skill cobre a instalação e configuração completa de um servidor WireGuard VPN em um ambiente homelab. Ela fornece orientação passo a passo para gerar pares de chaves, configurar peers (clientes) como telefones e laptops, e decidir entre roteamento split tunnel (apenas tráfego da rede doméstica) e full tunnel (todo o tráfego). É útil para quem precisa de acesso remoto seguro a serviços como NAS, servidores Pi-hole ou outros dispositivos na rede local. A skill inclui exemplos práticos de configuração para Linux (incluindo iptables e sysctl), pfSense/OPNsense, geração automatizada de chaves com Python, solução de problemas comuns (como verificar handshakes e regras de firewall), integração com DDNS (Cloudflare e DuckDNS) e práticas recomendadas de segurança, como nunca armazenar chaves privadas em controle de versão e usar regras de forwarding scoped. Ela é compatível com servidores Linux, pfSense e roteadores, e clientes móveis e laptops.

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

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Homelab WireGuard VPN

WireGuard é um protocolo VPN moderno e rápido. É a escolha certa para acesso remoto a uma rede doméstica — mais simples de configurar que OpenVPN e mais rápido que a maioria das alternativas.

Todos os exemplos de configuração mostram setups comuns. Revise cada comando — especialmente as regras de encaminhamento iptables e permissões de arquivos de chave — antes de aplicá-los ao seu sistema, e faça alterações em uma janela de manutenção.

Quando Usar

  • Configurando servidor WireGuard em um Raspberry Pi, host Linux, pfSense ou roteador
  • Gerando pares de chaves WireGuard e escrevendo arquivos de configuração de peers
  • Configurando acesso remoto a partir de um telefone ou laptop para uma rede doméstica
  • Explicando split tunneling (rotear apenas tráfego doméstico) vs full tunnel (rotear todo o tráfego)
  • Solucionando conexões WireGuard que não sobem
  • Automatizando geração de configuração de peers para múltiplos clientes

Como o WireGuard Funciona

Seu telefone (cliente WireGuard)
    │
    │  Túnel UDP criptografado (porta 51820)
    │
Seu roteador doméstico (servidor WireGuard — precisa de IP público ou DDNS)
    │
    Sua rede doméstica (192.168.1.0/24, NAS, Pi, etc.)

Cada dispositivo tem um par de chaves (chave pública + privada).
O servidor conhece a chave pública de cada cliente.
O cliente conhece a chave pública do servidor + endpoint (IP:porta).
O tráfego é criptografado ponto a ponto sem servidor central ou autoridade certificadora.

Configuração do Servidor (Linux)

# Instalar WireGuard
sudo apt update && sudo apt install wireguard -y

# Gerar par de chaves do servidor — criar arquivos com permissões privadas desde o início
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'

# Escrever configuração do servidor — substituir pelo valor real da chave privada
# Não armazenar chaves privadas em controle de versão ou compartilhá-las
sudo tee /etc/wireguard/wg0.conf << 'EOF'
[Interface]
Address = 10.8.0.1/24              # Sub-rede VPN — servidor recebe .1
ListenPort = 51820
PrivateKey = <cole_a_chave_privada_do_servidor_aqui>

# Regras de encaminhamento scoped: permitir tráfego VPN entrada/saída, não um FORWARD ACCEPT genérico
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]
# Telefone — substituir pela chave pública real do telefone
PublicKey = <chave_publica_do_telefone>
AllowedIPs = 10.8.0.2/32

[Peer]
# Laptop — substituir pela chave pública real do laptop
PublicKey = <chave_publica_do_laptop>
AllowedIPs = 10.8.0.3/32
EOF
sudo chmod 600 /etc/wireguard/wg0.conf

# Substituir eth0 pelo nome real da sua interface de saída
# Verificar com: ip route show default

# Habilitar encaminhamento IP (necessário para rotear tráfego através do servidor)
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system

# Iniciar WireGuard e habilitar na inicialização
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0

Configuração do Cliente

# Gerar um par de chaves único para cada dispositivo cliente
# Executar no cliente, ou no servidor e transferir a chave privada de forma segura — nunca em texto puro
umask 077
wg genkey | tee phone_private.key | wg pubkey > phone_public.key

# Arquivo de configuração do cliente (phone_wg0.conf):
[Interface]
PrivateKey = <chave_privada_do_telefone>
Address = 10.8.0.2/32
DNS = 192.168.1.2                  # Opcional: usar Pi-hole para DNS através do túnel

[Peer]
PublicKey = <chave_publica_do_servidor>
Endpoint = your-home-ip.ddns.net:51820  # Seu IP público ou hostname DDNS
AllowedIPs = 192.168.1.0/24            # Split tunnel: apenas tráfego da rede doméstica
# AllowedIPs = 0.0.0.0/0, ::/0        # Full tunnel: todo o tráfego através da VPN

PersistentKeepalive = 25              # Manter buraco NAT aberto (necessário para clientes móveis)

Split Tunnel vs Full Tunnel

# Split tunnel: AllowedIPs = 192.168.1.0/24
  Apenas o tráfego destinado à sua rede doméstica passa pela VPN.
  O tráfego da Internet (YouTube, Spotify) vai diretamente — melhor performance em dispositivos móveis.
  Melhor para: "Só quero acessar meu NAS e Pi de qualquer lugar."

# Full tunnel: AllowedIPs = 0.0.0.0/0, ::/0
  TODO o tráfego passa pela sua conexão de Internet doméstica.
  Útil para: aproveitar bloqueio de anúncios do Pi-hole/DNS doméstico.
  Desvantagem: sua velocidade de upload doméstica se torna o gargalo em todos os lugares.

# Split tunnel multi-sub-rede (caso de uso mais comum em homelab):
  AllowedIPs = 192.168.10.0/24, 192.168.20.0/24, 192.168.30.0/24, 10.8.0.0/24
  Roteia todas as suas VLANs através do túnel; Internet permanece direta.

Geração de Chaves e Gerenciamento de Peers

import subprocess

def generate_keypair() -> tuple[str, str]:
    """Gera um par de chaves WireGuard. Retorna (chave_privada, chave_publica)."""
    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,       # ex: "10.8.0.3"
    server_public_key: str,
    server_endpoint: str,     # ex: "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
"""

Mantenha chaves privadas fora do controle de versão. Se usar este script, escreva o material de chave em arquivos com modo 600 e nunca o registre em log ou imprima.

WireGuard no pfSense / OPNsense

# pfSense: VPN → WireGuard → Adicionar Túnel
  Interface Keys: Gerar (cria par de chaves automaticamente)
  Listen Port: 51820
  Interface Address: 10.8.0.1/24

# Adicionar Peer (um por cliente):
  Public Key: <chave pública do cliente>
  Allowed IPs: 10.8.0.2/32

# Atribuir a interface WireGuard:
  Interfaces → Assignments → Adicionar (selecionar wg0)
  Habilitar interface, sem IP necessário (definido na configuração do túnel)

# Regras de firewall:
  WAN → Permitir UDP porta 51820 entrada (para clientes alcançarem o servidor)
  Interface WireGuard → Permitir tráfego para redes LAN que deseja acessíveis

DDNS (DNS Dinâmico) para Servidores Domésticos

A maioria das conexões de Internet domésticas tem IP dinâmico. Use DDNS para que seu endpoint VPN permaneça acessível após uma mudança de IP.

# Opção 1: Cloudflare DDNS — armazenar credenciais em um arquivo de segredos, não inline
# Entrada docker-compose usando um arquivo env:
  ddns-updater:
    image: qmcgaw/ddns-updater
    env_file: ./ddns.env   # armazenar zone_id e token aqui, não no compose
    restart: unless-stopped

# ddns.env (chmod 600, não commitado no git):
# SETTINGS_CLOUDFLARE_ZONE_ID=your_zone_id
# SETTINGS_CLOUDFLARE_TOKEN=your_api_token

# Opção 2: DuckDNS (gratuito, simples)
  Cadastre-se em duckdns.org → obtenha um token e subdomínio (myhome.duckdns.org)
  Armazene token em /etc/ddns.env (modo 600), depois use um pequeno script de propriedade do 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 job:
  */5 * * * * /usr/local/bin/update-duckdns >/dev/null 2>&1

Solução de Problemas

# Verificar status do WireGuard e último handshake
sudo wg show

# Se "latest handshake" for nunca ou muito antigo, o túnel não está conectado.
# Verificar:
# 1. A porta UDP 51820 está aberta no roteador/firewall?
sudo ufw status  # ou verificar regras de firewall pfSense/UniFi

# 2. A chave pública do servidor está correta na configuração do cliente?
sudo wg show wg0 public-key   # Comparar com o que está na configuração do cliente

# 3. O encaminhamento IP está habilitado no servidor?
cat /proc/sys/net/ipv4/ip_forward  # Deve ser 1

# 4. O AllowedIPs do cliente cobre o IP que você está tentando alcançar?
# Se AllowedIPs = 192.168.1.0/24 e você está tentando alcançar 192.168.3.5, não vai rotear.

# Verificar logs do kernel para erros do WireGuard
dmesg | grep wireguard

# Reiniciar WireGuard
sudo wg-quick down wg0 && sudo wg-quick up wg0

Anti-Padrões

# RUIM: Armazenar chaves privadas em controle de versão ou compartilhá-las
# Chaves privadas são equivalentes a senhas — nunca as faça commit no git

# RUIM: Usar AllowedIPs = 0.0.0.0/0 em dispositivos móveis sem considerar o impacto
# Full tunnel roteia todo o tráfego móvel através do seu upload doméstico — geralmente lento

# RUIM: Não definir PersistentKeepalive em clientes móveis
# Clientes móveis atrás de NAT derrubam túneis ociosos sem isso

# RUIM: Abrir porta 51820 no firewall mas esquecer o encaminhamento IP no servidor
# Túnel conecta mas nenhum tráfego roteia — confuso de depurar

# RUIM: Compartilhar um par de chaves entre múltiplos dispositivos cliente
# Cada dispositivo deve ter seu próprio par de chaves único — chaves compartilhadas quebram o modelo de segurança

# RUIM: Usar uma regra iptables "FORWARD ACCEPT" genérica
# Escopo as regras de encaminhamento para a interface wg0 e direção apenas

Práticas Recomendadas

  • Gere um par de chaves único por dispositivo cliente — nunca reutilize chaves
  • Use split tunneling (AllowedIPs = <sub-redes domésticas>) para dispositivos móveis
  • Defina PersistentKeepalive = 25 em todos os clientes móveis
  • Use DDNS se seu ISP atribuir IP dinâmico; armazene credenciais em arquivos env, não inline
  • Use regras de encaminhamento iptables scoped (entrada apenas em wg0) em vez de um FORWARD ACCEPT genérico
  • Adicione o IP do Pi-hole como DNS = nas configurações do cliente para obter bloqueio de anúncios pela VPN
  • Rode o par de chaves do servidor periodicamente e atualize todas as configurações do cliente

Skills Relacionadas

  • 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.

Habilidades Relacionadas