implant wireguard
Instala e opera a VPN WireGuard do servidor (v2.48.0+): sobe a interface,
cadastra e remove devices (peers), libera a porta UDP no firewall do host e
mostra o estado. O servidor é o hub da VPN; cada device (celular,
notebook) é um peer com um IP /32 dentro da rede da VPN.
A fonte da verdade é o próprio /etc/wireguard/<iface>.conf do servidor.
Todo comando que muda o conf faz backup antes, grava de forma atômica (modo
600) e restaura o backup se a aplicação falhar.
Uso
implant wireguard <subcomando> [OPTIONS]Todos os subcomandos aceitam --iface <IFACE> (padrão wg0), o --dry-run
global e -o json|yaml.
Subcomandos
`status`
Somente leitura. Mostra se o wireguard-tools e o módulo do kernel estão
presentes, se a interface está no ar, se a unit wg-quick@<iface> está
habilitada/ativa, se o conf existe, a rede, a porta, o endpoint, o estado do
firewall e a lista de devices com o último handshake.
sudo implant wireguard status
sudo implant wireguard status -o json`init`
Instala o wireguard-tools (e o iproute2) se faltar, cria o conf, habilita
e sobe wg-quick@<iface> e libera a porta UDP no firewall do host.
| Flag | Descrição |
|---|---|
--subnet <CIDR> |
Rede da VPN, ex.: 10.8.0.0/24. O servidor fica com o .1. Obrigatória sem --adopt |
--port <PORT> |
Porta UDP (padrão 51820). Não combina com --adopt (vale a porta do conf) |
--endpoint <HOST[:PORTA]> |
Endereço público que vai no .conf dos devices. Padrão: IP público detectado |
--adopt |
Passa a gerenciar um conf existente sem reescrevê-lo |
--force |
Recria o conf do zero (ver aviso abaixo) |
--iface <IFACE> |
Interface (padrão wg0) |
Comportamento:
- Idempotente: rodar de novo com os mesmos parâmetros não muda nada
(
outcome: unchanged). - Trocar só o endpoint (
--endpointdiferente, resto igual) atualiza o endpoint guardado sem reiniciar a VPN e sem--force(outcome: updated). Devices já cadastrados continuam com o.confantigo; o novo endpoint vale para os próximospeer add. - Parâmetros diferentes de um conf existente (outra rede, outra porta) são
recusados — a menos de
--force.
--forceé destrutivo. Gera uma nova chave do servidor e remove todos os devices: todo.confdistribuído para de funcionar. O conf anterior fica em backup. Não é preciso--forcepara trocar o endpoint.
Adotar um conf existente (`--adopt`)
Para um servidor que já tem WireGuard configurado à mão:
sudo implant wireguard init --adopt
sudo implant wireguard init --adopt --endpoint vpn.example.com- Rede e porta vêm do conf; nada é reescrito. Comentários, chaves
desconhecidas (
PostUp,Table, …) e a ordem das linhas são preservados. - Com
--endpoint, só o endpoint é gravado no conf. - Conf com
SaveConfig = trueé recusado: owg-quickreescreveria o arquivo ao parar a interface e apagaria os comentários. Desligue antes de adotar. - O nome de um device é o comentário
# <nome>logo abaixo do[Peer].
A porta sobrevive ao reboot (v2.54.0+)
init (e --adopt) grava um drop-in do systemd para wg-quick@<iface> que
chama implant wireguard firewall open --iface <iface> toda vez que a
interface sobe. Em host com iptables em DROP e sem persistência de regras,
a liberação feita em runtime sumia no boot e a VPN ficava no ar sem receber
conexão.
`peer add `
Cadastra um device e imprime o .conf dele e um QR code para importar no app
do WireGuard.
| Flag | Descrição |
|---|---|
<NAME> |
Nome do device: a-z, 0-9 e -, até 32 caracteres. Nome repetido é recusado |
--ip <IP> |
IP do device na VPN: auto (padrão, próximo livre) ou um IPv4 da rede |
--public-key <KEY> |
Chave pública gerada fora. Sem ela, o implant gera o par de chaves |
--dns <IP> |
DNS que vai no .conf do device |
--endpoint <HOST[:PORTA]> |
Sobrepõe o endpoint guardado pelo init só neste device |
--qr <svg|ansi|none> |
Formato do QR. Padrão: ansi no terminal, svg com -o json |
--iface <IFACE> |
Interface (padrão wg0) |
O device é aplicado na interface em execução sem derrubar as sessões dos outros devices.
A chave privada aparece uma única vez. Quando o implant gera o par, a chave privada do device existe só na saída deste comando: não é gravada em disco, em log nem em relatório. Não há como baixar o
.confde novo nem "regerar" a chave. Perdeu o.conf? Remova o device e cadastre outro:sudo implant wireguard peer remove notebook sudo implant wireguard peer add notebook
Com --public-key, o implant só registra a chave pública: a saída não tem
chave privada e o .conf fica a cargo de quem gerou o par.
O .conf gerado é split tunnel: o AllowedIPs do device é a rede da VPN
mais o IP público do servidor (/32), com PersistentKeepalive = 25. Os
apps de Android, iOS, Windows e macOS funcionam assim. Em notebook Linux com
wg-quick, ter o IP do endpoint dentro do AllowedIPs cria loop de
roteamento: remova o IP público do servidor do AllowedIPs nesse caso.
`peer remove `
Remove um device, pelo nome ou pela chave pública. A conexão do device cai na hora.
`peer list`
Lista os devices com IP e último handshake. Peers que existem só na
interface em execução (fora do conf) aparecem marcados como "só runtime" e
não são tocados pelo peer add.
`firewall open` / `firewall status` (v2.54.0+)
firewall open— libera a porta UDP da VPN (oListenPortdo conf; padrão51820) no firewall do host. Idempotente; é o que o drop-in do systemd chama no boot. Sai com código 0 mesmo quando não há firewall local gerenciado.firewall status— mostra se a porta está liberada, sem mudar nada.
Firewalls reconhecidos: ufw, firewalld e iptables com policy DROP. Sem
nenhum deles bloqueando, o resultado é "sem firewall local" — libere a porta
UDP no firewall do provedor de nuvem, se houver. No ufw, a regra criada é
marcada com o comentário wireguard-<iface>; regras antigas sem a marca
(versões anteriores à 2.53.0) são trocadas pela marcada.
`disable`
Para e desabilita wg-quick@<iface> e fecha a porta que o implant liberou.
O conf é mantido (chave do servidor e devices continuam lá). Para religar
com o mesmo conf:
sudo implant wireguard init --adoptVárias redes por servidor (v2.57.0+)
O servidor pode ter mais de uma rede WireGuard (wg0, wg1…, cada uma com
seu conf em /etc/wireguard/<iface>.conf). Todo subcomando aceita --iface
(padrão wg0).
sudo implant wireguard init --iface wg1 --subnet 10.100.8.0/24 --port 51821
implant -o json wireguard networks # todas as redes do host (somente leitura)
implant -o json wireguard status --iface wg1
sudo implant wireguard disable --iface wg1 # para a rede; conf e isenção ficam
sudo implant wireguard remove --iface wg1 # remove a rede inteira
sudo implant --dry-run wireguard remove --iface wg1 # só o plano`networks`
Lista as redes de /etc/wireguard/*.conf mais as interfaces
WireGuard no ar sem conf. Cada item tem o formato do status --iface X e mais:
conf_existseinterface_upno topo (iguais aos dedetection);managed_by, lido do cabeçalho do conf:implant(cabeçalho# Gerenciado pelo implant …, gravado peloinit), o nome da ferramenta quando o cabeçalho é# Gerado por `<ferramenta> …`, oudesconhecido(inclusive conf adotado com--adopt, que não é reescrito);role:hub(temListenPorteAddresscom prefixo menor que /32) ouclient(Address/32 e um[Peer]comEndpoint). No cliente,subneté oAddresscomo está elisten_portpode sernull;peersno formato dopeer list(namevem do comentário logo abaixo do[Peer]);firewall(só com a interface no ar) erate_limit_whitelist.
Conf ilegível não derruba a lista: o item sai com error. Servidor sem
WireGuard: networks: [], exit 0. Nenhuma saída traz chave privada.
`remove --iface X [--force]`
Remove a rede inteira, nesta ordem:
systemctl disable --now wg-quick@X;- fecha a porta no firewall (só as regras com o marcador
wireguard-X); - tira a porta da isenção do rate-limit;
- apaga o drop-in
/etc/systemd/system/wg-quick@X.service.d/implant-firewall.confe rodasystemctl daemon-reload; - guarda o conf em
/etc/wireguard/X.conf.removed-<AAAAMMDDTHHMMSSZ>(modo- e só então tira o original. O conf nunca é apagado sem backup.
Rede que não existe (sem conf e sem interface) dá outcome: "absent" e exit 0
— e ainda tira uma isenção órfã do rate-limit, se houver. Sem --force, o
remove recusa (exit diferente de 0) a wg0, que é a rede padrão do
servidor, e qualquer rede que não seja managed_by: implant. Interface só de
runtime que continua no ar depois do disable não é do wg-quick: o comando
falha com a mensagem e ela deve ser derrubada por quem a criou. Com
--dry-run, nada muda e o json traz o plano em planned.
{"iface": "wg1", "outcome": "removed", "managed_by": "implant", "listen_port": 51821,
"firewall": "closed", "firewall_detail": {"kind": "iptables", "opened": false},
"rate_limit_whitelist": "removed", "backup": "/etc/wireguard/wg1.conf.removed-20261012T120000Z"}rate_limit_whitelist no remove: removed, absent (rate-limit gerenciado,
porta não estava isenta) ou not_managed (sem rate-limit gerenciado).
Porta da rede isenta do rate-limit
O init (inclusive --adopt) isenta
a ListenPort da rede no rate-limit, presa à rede pelo marcador
wireguard-<iface> — o mesmo do firewall: é um RETURN no topo da cadeia
IMPLANT_RATELIMIT (v4 e v6), guardado no state do rate-limit
(whitelist_ports) e refeito por apply, reconcile, add e remove. Só o
rate-limit deixa de valer para a porta; blocklist e geo-block continuam. Se o
ListenPort muda, a porta antiga da mesma rede sai. O disable mantém a
isenção; o remove a tira. Opt-in respeitado: sem rate-limit aplicado nada é
feito. Com o rate-limit suspenso (emergency-mode), só o state muda e o
reconcile a recoloca. init, status e networks relatam
rate_limit_whitelist: {"listed": true|false, "kind": "iptables"} ou null
sem rate-limit gerenciado; um erro vem em error, sem falhar o init.
Detecção do firewall
A detecção é a mesma em init, status, disable e
remove: ufw ativo, firewalld rodando, ou iptables quando o INPUT bloqueia
(policy DROP/REJECT ou DROP final) ou quando já há regra wireguard-<iface>
para fechar. INPUT aberto e sem regra nossa: kind: "none" em todos.
Flags globais relevantes
| Flag | Descrição |
|---|---|
--dry-run |
Mostra o plano (lista "Faria:") sem alterar nada. Em JSON, vai no campo planned |
-o, --output json|yaml |
Saída estruturada (envelope) |
-v, --verbose |
Mais detalhes |
Exemplos
# Criar a VPN na rede 10.8.0.0/24, porta padrão
sudo implant wireguard init --subnet 10.8.0.0/24 --endpoint vpn.example.com
# Simular antes
sudo implant wireguard init --subnet 10.8.0.0/24 --dry-run
# Cadastrar o celular (QR no terminal)
sudo implant wireguard peer add celular
# Cadastrar com IP fixo e DNS, sem QR
sudo implant wireguard peer add notebook --ip 10.8.0.10 --dns 10.8.0.1 --qr none
# Listar e remover
sudo implant wireguard peer list
sudo implant wireguard peer remove celular
# Conferir / reabrir a porta no firewall
sudo implant wireguard firewall status
sudo implant wireguard firewall open
# Parar a VPN mantendo o conf
sudo implant wireguard disableSaída JSON
Comandos do envelope: wireguard.status, wireguard.init,
wireguard.peer.add, wireguard.peer.remove, wireguard.peer.list,
wireguard.firewall.open, wireguard.firewall.status, wireguard.disable.
peer add separa o que é sensível no bloco secret (ausente com
--public-key):
{
"peer": { "name": "celular", "public_key": "…", "ip": "10.8.0.2/32" },
"server": { "public_key": "…", "endpoint": "203.0.113.10:51820", "subnet": "10.8.0.0/24", "iface": "wg0" },
"secret": { "private_key": "…", "config": "[Interface]\n…", "qr_svg": "<svg …>" }
}init, disable e firewall * trazem firewall (opened, closed,
not_managed, planned ou unknown) e firewall_detail (kind,
opened e, quando houver, error/migrated). firewall: unknown significa
que o comando do firewall falhou e o estado da regra não é conhecido — um
aviso também sai no stderr.
Notas
- A chave privada do servidor fica só no conf (modo 600) e nunca sai do servidor.
- Backups do conf:
/etc/wireguard/<iface>.conf.bak-<timestamp>, modo 600, os 5 mais recentes. - Com um console de gerenciamento remoto, a mesma operação é disparada
pela CLI em
-o json; o console recebe osecretuma vez, para mostrar o QR ao operador, e não deve guardá-lo.
Veja também
- firewall — wrapper UFW
- harden-network — o hardening detecta a interface
WireGuard e ajusta
ip_forward/rp_filter