Hands-on lab

Network attack and defence, on your own machines.

How the network layer is probed and abused, and how a Linux firewall, VPN and monitoring answer back, with Docker and home-lab exercises, official documentation and a clear expected result for each.

Antes de começarBefore you start

Esta nota é um laboratório: cada seção ensina uma ferramenta e termina num exercício com um resultado esperado explícito, para você saber se funcionou. A ideia é 80/20: as ferramentas que cobrem a maior parte do que um desenvolvedor precisa de redes e segurança no dia a dia, sem tentar ser um curso de pentest.This note is a lab: each section teaches one tool and ends with an exercise that states an explicit expected result, so you know whether it worked. The idea is 80/20: the tools that cover most of what a developer needs from networking and security day to day, without trying to be a pentest course.

Regra de ouro: só escaneie, capture tráfego ou teste firewalls em máquinas e redes suas (sua própria VM, seu laboratório Docker, sua VPN) ou com autorização explícita por escrito. Fazer isso contra redes de terceiros sem permissão pode ser crime em praticamente todo lugar. Toda ferramenta aqui é a mesma usada por times de segurança defensivos: para entender e proteger o que é seu.Golden rule: only scan, capture traffic or test firewalls on machines and networks that are yours (your own VM, your Docker lab, your VPN) or with explicit written authorization. Doing this against someone else's network without permission can be a crime almost everywhere. Every tool here is the same one defensive security teams use: to understand and protect what is yours.
Onde esta nota se encaixa: é a etapa 0 da trilha de cibersegurança para quem programa (fundamentos de rede e sistema). As ferramentas daqui servem aos dois lados: o nmap e o Wireshark do atacante são o inventário e a investigação do defensor. Os próximos passos são a nota de aplicações web seguras e a nota de ataque e defesa web e de servidor.Where this note fits: it is stage 0 of the cybersecurity path for developers (network and system fundamentals). The tools here serve both sides: the attacker's nmap and Wireshark are the defender's inventory and investigation. The next steps are the secure web apps note and the web and host attack and defence note.

O que você precisaWhat you need

  • Uma máquina Linux: uma VM (VirtualBox/UTM/Multipass), WSL2 no Windows, ou um servidor de estudo na nuvem (veja a nota de AWS).A Linux machine: a VM (VirtualBox/UTM/Multipass), WSL2 on Windows, or a cloud study server (see the AWS note).
  • Docker, para a seção de laboratório local (opcional nas outras seções).Docker, for the local-lab section (optional in the other sections).
  • Um segundo dispositivo na mesma rede (celular, outro notebook) ajuda a ver o tráfego "de fora" em alguns exercícios, mas não é obrigatório.A second device on the same network (phone, another laptop) helps see traffic "from outside" in some exercises, but is not required.

Mapa da notaMap of this note

SessõesSessions nmap SSH WireGuard Wireshark Firewall Recon Docker
A ordem sugerida: cada seção usa uma ideia da anterior.The suggested order: each section uses an idea from the previous one.

Sessões: TCP com estado, UDP sem estadoSessions: stateful TCP, stateless UDP

Uma sessão é o estado que duas pontas guardam sobre uma conversa em andamento: quem é o outro lado, o que já foi enviado, o que falta confirmar. TCP é stateful (com estado): abre uma conexão, numera os bytes, reenvia o que se perde. UDP é stateless (sem estado): cada pacote (datagrama) é independente, sem conexão nem garantia de entrega.A session is the state both ends keep about an ongoing conversation: who the other side is, what has been sent, what is still unacknowledged. TCP is stateful: it opens a connection, numbers the bytes, and resends what gets lost. UDP is stateless: each packet (datagram) is independent, with no connection and no delivery guarantee.

clienteclient servidorserver handshake de 3 vias (abre a sessão)3-way handshake (opens the session) SYN SYN-ACK ACK dados, com número de sequênciadata, with a sequence number ACK: "recebi até aqui"ACK: "got this far" Se um ACK não chega, o remetente reenvia: é isso que torna o TCP confiável e "com estado".If an ACK does not arrive, the sender resends: that is what makes TCP reliable and "stateful".
TCP: a sessão existe nos dois lados desde o handshake até o FIN (encerramento).TCP: the session exists on both ends from the handshake until the FIN (close).
clienteclient servidor DNSDNS server servidor NTPNTP server datagrama 1 (consulta)datagram 1 (query) datagrama 2 (resposta)datagram 2 (response) datagrama 3 (hora?)datagram 3 (time?) cada datagrama é independente: sem conexão, sem reenvio automáticoeach datagram is independent: no connection, no automatic resend
UDP: sem sessão. Quem precisa de confiabilidade (como DNS às vezes) cuida disso na camada de cima.UDP: no session. Whoever needs reliability (like DNS sometimes) handles it a layer up.

Por que isso importa na práticaWhy this matters in practice

ConceitoConceptO que significaWhat it means
Firewall statefulStateful firewalllembra as conexões TCP que você abriu e libera as respostas sozinho (ct state established no nftables)remembers the TCP connections you opened and lets the replies through on its own (ct state established in nftables)
NAT e conntrackNAT and conntrackseu roteador doméstico guarda uma tabela de sessões para saber a quem devolver cada respostayour home router keeps a session table to know whom to return each reply to
Por que UDP "vaza" menos pelo NATWhy UDP "leaks" less through NATsem sessão formal, o NAT usa um timeout curto; é por isso que WireGuard (UDP) manda pacotes de keepalivewith no formal session, NAT uses a short timeout; that is why WireGuard (UDP) sends keepalive packets
Balanceador de carga "sticky""Sticky" load balancerprecisa lembrar a sessão para mandar sempre o mesmo cliente ao mesmo servidorneeds to remember the session to always send the same client to the same server

Exercício: ver as duas coisas ao vivoExercise: see both live

ss -tn state established        # conexões TCP com sessão aberta agora (seu navegador, SSH...)
ss -un                          # "conexões" UDP: na verdade sockets locais, sem sessão de verdade
dig example.com                 # uma consulta DNS: um datagrama de ida, um de volta

Resultado esperado: ss -tn mostra pares Local Address:Port / Peer Address:Port com estado ESTAB — isso é uma sessão TCP de verdade. ss -un mostra só sockets locais, sem "estado" de conexão, porque UDP não tem sessão no protocolo.Expected result: ss -tn shows Local Address:Port / Peer Address:Port pairs with state ESTAB — that is a real TCP session. ss -un shows only local sockets, with no connection "state", because UDP has no session in the protocol.

nmap: o que existe na redenmap: what exists on the network

nmap (Network Mapper) responde a pergunta mais básica de rede: o que existe, e o que está aberto? Ele manda pacotes de teste para um alvo e lê as respostas para descobrir hosts vivos, portas abertas e, às vezes, até a versão do serviço rodando nelas. É a primeira ferramenta que qualquer time de segurança roda contra os próprios sistemas, para ver o que um atacante veria de fora.nmap (Network Mapper) answers the most basic network question: what exists, and what is open? It sends test packets to a target and reads the replies to find live hosts, open ports and sometimes even the service version running on them. It is the first tool any security team runs against its own systems, to see what an attacker would see from outside.

Rode o nmap só contra IPs seus (sua VM, seu contêiner, um servidor de estudo seu) ou contra scanme.nmap.org, que o próprio projeto Nmap mantém de propósito para testes. Escanear redes alheias sem permissão é ilegal em quase todo lugar.Only run nmap against your own IPs (your VM, your container, a study server of yours) or against scanme.nmap.org, which the Nmap project itself keeps around on purpose for testing. Scanning other people's networks without permission is illegal almost everywhere.

InstalarInstall

sudo apt install nmap     # Debian/Ubuntu
sudo dnf install nmap     # Fedora
brew install nmap         # macOS

Anatomia de um scan de portasAnatomy of a port scan

nmap :22 aberta:22 open ← SYN-ACK: aberta← SYN-ACK: open :80 aberta:80 open ← SYN-ACK: aberta← SYN-ACK: open :443 fechada:443 closed ← RST: fechada← RST: closed :8080 filtrada:8080 filtered sem resposta: filtradano reply: filtered SYN (o firewall descarta o pacote)(a firewall drops the packet)
Um SYN scan (-sS) manda um SYN para cada porta e classifica pela resposta, sem completar a conexão.A SYN scan (-sS) sends a SYN to each port and classifies it by the reply, without completing the connection.

Exercício 1: escaneie a sua própria máquinaExercise 1: scan your own machine

nmap localhost                       # scan básico das 1000 portas mais comuns
nmap -p- localhost                   # TODAS as 65535 portas (mais lento)
nmap -sV localhost                   # tenta identificar a VERSÃO de cada serviço
nmap -O localhost                    # tenta adivinhar o sistema operacional (precisa de sudo)
sudo nmap -sS -p 1-1000 localhost    # SYN scan "silencioso", não completa a conexão

Resultado esperado: uma lista como 22/tcp open ssh, 631/tcp open ipp (se você tem impressão compartilhada), ou "0 portas abertas" numa máquina bem fechada. Compare com ss -tulpn (nota de Linux): toda porta que o nmap mostra como aberta deve aparecer também ali, do lado do servidor.Expected result: a list like 22/tcp open ssh, 631/tcp open ipp (if you have printer sharing), or "0 open ports" on a well-closed machine. Compare it with ss -tulpn (Linux note): every port nmap shows as open should also show up there, from the server side.

Exercício 2: escaneie um contêiner DockerExercise 2: scan a Docker container

docker run -d --name web -p 8080:80 nginx
nmap -p 8080 localhost               # a porta publicada
nmap localhost                       # as outras portas do HOST continuam aparecendo, a 80 do container não

Resultado esperado: só a porta 8080 aparece aberta (a publicada com -p); a 80 "de dentro" do contêiner não aparece, porque o nmap, rodando no host, só enxerga a interface do host, não a rede interna do Docker. A seção sobre Docker mais abaixo explica por quê.Expected result: only port 8080 shows as open (the one published with -p); the container's internal 80 does not show up, because nmap, running on the host, only sees the host's interface, not Docker's internal network. The Docker section below explains why.

Opções do dia a diaEveryday options

OpçãoOptionFazDoes
-sSSYN scan: rápido, não completa a conexão (precisa de sudo)SYN scan: fast, does not complete the connection (needs sudo)
-sTconnect scan: completa a conexão TCP normal (não precisa de sudo)connect scan: completes a normal TCP connection (no sudo needed)
-sUescaneia portas UDP (mais lento e menos confiável que TCP)scans UDP ports (slower and less reliable than TCP)
-p 1-1000 · -p- · -p 22,80,443faixa, tudo, ou portas específicasa range, everything, or specific ports
-sVdetecta a versão do serviço (“nginx 1.25”)detects the service version (“nginx 1.25”)
-Atudo junto: versão, SO, script básico, traceroute (mais barulhento e lento)everything together: version, OS, basic scripts, traceroute (noisier and slower)
-T4mais rápido (até -T5); o padrão é conservadorfaster (up to -T5); the default is conservative
-oN arquivo.txtsalva a saída legível em arquivosaves readable output to a file
192.168.1.0/24escaneia uma faixa inteira (só na sua LAN!)scans a whole range (only on your own LAN!)
Nmap tem uma engine de scripts (NSE, --script) usada para checagens específicas, como testar se um servidor tem uma configuração TLS fraca. É poderosa e também de uso exclusivo em sistemas seus ou autorizados.Nmap has a scripting engine (NSE, --script) used for specific checks, like testing whether a server has weak TLS configuration. It is powerful, and likewise for use only on your own or authorized systems.

SSH como ferramenta de redeSSH as a network tool

A nota de Linux já cobre chaves e sshd_config. Aqui o foco é usar o SSH como ferramenta de rede: um túnel cifrado que você pode usar para alcançar serviços que, de outro jeito, não exporia.The Linux note already covers keys and sshd_config. Here the focus is using SSH as a network tool: an encrypted tunnel you can use to reach services that would otherwise not be exposed.

seu notebookyour laptop servidor (SSH)server (SSH) banco :5432database :5432 só localhostlocalhost only túnel :5432tunnel :5432 local ssh -L 5432:localhost:5432 ana@servidorssh -L 5432:localhost:5432 ana@server agora localhost:5432 no seu notebook é o banco do servidornow localhost:5432 on your laptop is the server’s database
Encaminhamento local (-L): o que você manda para uma porta sua sai do outro lado do túnel.Local forwarding (-L): what you send to a port of yours comes out the other end of the tunnel.

Exercício: um túnel de verdadeExercise: a real tunnel

# no "servidor" (pode ser uma segunda VM, ou um contêiner com sshd):
docker run -d --name srv -p 2222:22 -p 127.0.0.1:8081:80 linuxserver/openssh-server \
  -e PASSWORD_ACCESS=true -e USER_PASSWORD=estudo -e USER_NAME=ana
docker exec srv apk add --no-cache python3 2>/dev/null || true
docker exec -d srv python3 -m http.server 80

# no seu notebook: abra o túnel
ssh -p 2222 -L 9000:localhost:8081 ana@localhost   # senha: estudo

# numa SEGUNDA aba, com o túnel ainda aberto:
curl http://localhost:9000

Resultado esperado: o curl retorna a página servida por python3 -m http.server dentro do contêiner, mesmo que a porta 80 dele só esteja ligada ao localhost interno — porque o túnel SSH carrega o tráfego da sua porta 9000 até lá. Feche o SSH (Ctrl+C) e repita o curl: agora falha, porque o túnel não existe mais.Expected result: curl returns the page served by python3 -m http.server inside the container, even though its port 80 is only bound to its internal localhost — because the SSH tunnel carries the traffic from your port 9000 there. Close SSH (Ctrl+C) and repeat the curl: it now fails, because the tunnel no longer exists.

As três formas de encaminhamentoThe three kinds of forwarding

ComandoCommandDireçãoDirectionUse quandoUse when
ssh -L porta_local:destino:porta ana@srvvocê → servidor → destinoyou → server → destinationalcançar um banco/painel que só existe na rede do servidorreaching a database/panel that only exists on the server’s network
ssh -R porta_remota:localhost:porta ana@srvservidor → vocêserver → youexpor algo seu (um app local) através de um servidor com IP públicoexposing something of yours (a local app) through a server with a public IP
ssh -D 1080 ana@srvproxy SOCKS: qualquer app → servidor → internetSOCKS proxy: any app → server → internetnavegar como se estivesse saindo pela rede do servidorbrowsing as if leaving from the server’s network

VPN e WireGuard: hospede a suaVPN and WireGuard: host your own

Uma VPN (Virtual Private Network) estende uma rede privada pela internet: o tráfego entra cifrado num ponto e sai do outro lado como se estivesse dentro da rede remota. WireGuard é a forma moderna de fazer isso: um protocolo enxuto (poucos milhares de linhas, contra centenas de milhares do OpenVPN/IPsec), baseado em criptografia de chave pública, que vira uma interface de rede comum (wg0). É simples o bastante para você hospedar a sua própria VPN em minutos.A VPN (Virtual Private Network) extends a private network across the internet: traffic goes in encrypted at one point and comes out the other side as if it were inside the remote network. WireGuard is the modern way to do this: a lean protocol (a few thousand lines, versus hundreds of thousands for OpenVPN/IPsec), based on public-key cryptography, that shows up as an ordinary network interface (wg0). It is simple enough that you can host your own VPN in minutes.

seu notebookyour laptop wg0: 10.8.0.2 seu servidoryour server wg0: 10.8.0.1 internet (tudo aqui é cifrado)internet (everything here is encrypted) UDP :51820 · pacotes cifrados e autenticadosUDP :51820 · encrypted, authenticated packets Cada lado tem uma chave privada (que nunca sai da máquina)Each side has a private key (that never leaves the machine) e conhece a chave PÚBLICA do outro — como SSH, mas para toda a conexão.and knows the other’s PUBLIC key — like SSH, but for the whole connection.
Os dois lados viram uma pequena rede própria, 10.8.0.0/24, por cima da internet normal.Both sides become a small network of their own, 10.8.0.0/24, on top of the ordinary internet.

Exercício: hospede a sua própria VPNExercise: host your own VPN

No seu servidor (uma VM de estudo na nuvem, ou uma VM local — veja a nota de AWS para subir uma de graça/baixo custo):On your server (a cloud study VM, or a local VM — see the AWS note to spin one up cheaply):

# SERVIDOR
sudo apt install wireguard
umask 077   # garante que as chaves nasçam só legíveis pelo dono
wg genkey | tee server.key | wg pubkey > server.pub
cat server.key   # guarde: vai no [Interface] do servidor
cat server.pub   # guarde: vai no [Peer] do notebook

sudo sysctl -w net.ipv4.ip_forward=1    # deixa o servidor RETRANSMITIR pacotes

Arquivo de configuração do servidor:The server’s configuration file:

# /etc/wireguard/wg0.conf  (servidor)
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <conteúdo de server.key>

[Peer]                      # um bloco [Peer] para cada cliente
PublicKey = <conteúdo de laptop.pub>
AllowedIPs = 10.8.0.2/32    # só este IP da VPN vem desse peer
sudo wg-quick up wg0                    # sobe a interface
sudo systemctl enable wg-quick@wg0      # liga no boot
sudo wg show                            # confirma: peer, handshake, transferência

No seu notebook (o cliente):On your laptop (the client):

# NOTEBOOK
wg genkey | tee laptop.key | wg pubkey > laptop.pub
# copie laptop.pub para o bloco [Peer] do servidor (acima) e reinicie: sudo wg-quick down wg0 && sudo wg-quick up wg0
# /etc/wireguard/wg0.conf  (notebook)
[Interface]
Address = 10.8.0.2/24
PrivateKey = <conteúdo de laptop.key>

[Peer]
PublicKey = <conteúdo de server.pub>
Endpoint = SEU_IP_PUBLICO:51820
AllowedIPs = 10.8.0.0/24    # só a rede da VPN passa pelo túnel (não TUDO)
PersistentKeepalive = 25    # mantém o NAT "vivo" (lembra: UDP não tem sessão!)
sudo wg-quick up wg0
ping 10.8.0.1                 # chega ao servidor pela VPN?
sudo wg show                  # "latest handshake" recente = funcionando

Resultado esperado: ping 10.8.0.1 responde, e sudo wg show mostra um latest handshake de segundos atrás nos dois lados. Se não houver handshake, confira: porta 51820/UDP liberada no firewall e no grupo de segurança da nuvem, ip_forward ligado no servidor, e se as chaves públicas foram trocadas corretamente (a pública do notebook no servidor, e vice-versa).Expected result: ping 10.8.0.1 replies, and sudo wg show shows a latest handshake from seconds ago on both sides. If there is no handshake, check: port 51820/UDP open in the firewall and the cloud security group, ip_forward on at the server, and whether the public keys were exchanged correctly (the laptop’s public key on the server, and vice versa).

Com AllowedIPs = 0.0.0.0/0 no cliente, TODO o seu tráfego de internet passa pelo servidor (uma VPN "completa", útil em Wi-Fi não confiável). Com uma faixa menor (como 10.8.0.0/24), só o tráfego para a rede da VPN passa por ela — o resto sai direto. Essa escolha é só o AllowedIPs.With AllowedIPs = 0.0.0.0/0 on the client, ALL of your internet traffic goes through the server (a "full" VPN, useful on untrusted Wi-Fi). With a smaller range (like 10.8.0.0/24), only traffic to the VPN network goes through it — everything else goes out directly. That choice is just AllowedIPs.

Para que serve de verdade: usar fora de casa, em Wi-Fi públicoWhat it is really for: using it away from home, on public Wi-Fi

Um Wi-Fi de aeroporto, cafeteria ou hotel é uma rede que você não controla: qualquer outro cliente nela pode tentar capturar seu tráfego (o mesmo tcpdump/Wireshark da seção anterior, só que operado por outra pessoa) ou criar um ponto de acesso falso com o mesmo nome ("evil twin"). Ligar a VPN antes de usar essa rede resolve isso: todo o seu tráfego sai cifrado do seu aparelho até o SEU servidor, então quem está no Wi-Fi local só vê bytes WireGuard sem sentido, exatamente como a captura da porta 443 na seção de Wireshark.Airport, coffee-shop or hotel Wi-Fi is a network you do not control: any other client on it can try to capture your traffic (the same tcpdump/Wireshark from the previous section, just run by someone else) or stand up a fake access point with the same name (an "evil twin"). Turning the VPN on before using that network fixes this: all your traffic leaves your device encrypted all the way to YOUR server, so whoever is on the local Wi-Fi only sees meaningless WireGuard bytes, exactly like the port-443 capture in the Wireshark section.

Configurar o celular (com QR code)Setting up your phone (with a QR code)

# no SERVIDOR: gere a config completa de um novo peer "celular" e mostre como QR code
sudo apt install qrencode
wg genkey | tee celular.key | wg pubkey > celular.pub

cat > celular.conf <<EOF
[Interface]
Address = 10.8.0.3/24
PrivateKey = $(cat celular.key)
DNS = 10.8.0.1                       # veja "sem vazar DNS" abaixo

[Peer]
PublicKey = $(cat server.pub)
Endpoint = SEU_IP_PUBLICO:51820
AllowedIPs = 0.0.0.0/0, ::/0          # TUNEL COMPLETO: todo o tráfego do celular
PersistentKeepalive = 25
EOF

qrencode -t ansiutf8 < celular.conf    # mostra o QR no próprio terminal
# adicione o peer no servidor (bloco [Peer] com celular.pub e AllowedIPs = 10.8.0.3/32) e recarregue o wg0

Abra o app oficial WireGuard (Android/iOS), toque em "+", escaneie o QR do terminal, e pronto: um toque liga e desliga a VPN. Para o notebook, use AllowedIPs = 0.0.0.0/0 do mesmo jeito no lugar de 10.8.0.0/24 (o exemplo principal desta seção usava a faixa menor de propósito, para separar "túnel completo" de "só a rede da VPN").Open the official WireGuard app (Android/iOS), tap "+", scan the QR code from the terminal, and that's it: one tap turns the VPN on and off. For a laptop, use AllowedIPs = 0.0.0.0/0 the same way in place of 10.8.0.0/24 (this section's main example used the smaller range on purpose, to keep "full tunnel" separate from "just the VPN network").

Sem vazar DNSWithout leaking DNS

Se o AllowedIPs manda todo o TRÁFEGO pela VPN mas o aparelho continua perguntando o DNS do Wi-Fi local "qual o IP de banco.com?", o dono daquele Wi-Fi ainda vê quais sites você visita — isso é um vazamento de DNS. A linha DNS = 10.8.0.1 na config do cliente resolve isso, desde que o servidor tenha um resolvedor DNS escutando na VPN.If AllowedIPs sends all TRAFFIC through the VPN but the device still asks the local Wi-Fi "what is banco.com's IP?", whoever owns that Wi-Fi can still see which sites you visit — that is a DNS leak. The DNS = 10.8.0.1 line in the client config fixes this, as long as the server has a DNS resolver listening on the VPN.

# no SERVIDOR: um resolvedor simples, só para a rede da VPN
sudo apt install unbound
echo 'interface: 10.8.0.1' | sudo tee -a /etc/unbound/unbound.conf.d/wg.conf
echo 'access-control: 10.8.0.0/24 allow' | sudo tee -a /etc/unbound/unbound.conf.d/wg.conf
sudo systemctl restart unbound

# teste de vazamento, dos dois lados
dig @10.8.0.1 example.com            # pelo resolvedor da VPN: deve responder
cat /etc/resolv.conf                 # no cliente, depois de subir o túnel: deve apontar para 10.8.0.1

Resultado esperado: com a VPN ligada, abra dnsleaktest.com num navegador: os servidores de DNS listados devem ser os do SEU servidor (ou do provedor que ele usa), nunca os do Wi-Fi em que você está.Expected result: with the VPN on, open dnsleaktest.com in a browser: the DNS servers listed should be YOUR server's (or whatever provider it uses), never the Wi-Fi's you are on.

Kill switch: não deixar vazar se a VPN cairKill switch: don't leak if the VPN drops

Com túnel completo, se o WireGuard cair por um instante (trocou de rede, o app travou), o sistema operacional pode voltar a mandar tráfego direto pela rede local sem avisar. Um kill switch é uma regra de firewall que só libera saída pela interface wg0 (e descarta o resto), então, se o túnel cai, a internet para de funcionar em vez de vazar.With a full tunnel, if WireGuard drops for a moment (you switched networks, the app froze), the operating system may fall back to sending traffic directly over the local network without warning. A kill switch is a firewall rule that only allows outbound traffic through the wg0 interface (and drops the rest), so if the tunnel drops, the internet stops working instead of leaking.

# /etc/wireguard/wg0.conf (notebook) — bloco [Interface], regras extras
[Interface]
Address = 10.8.0.2/24
PrivateKey = <conteúdo de laptop.key>
DNS = 10.8.0.1
PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PostDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
Esse PostUp/PostDown é a receita oficial do próprio projeto WireGuard para kill switch no Linux. Nos apps oficiais de celular (Android/iOS), procure a opção "Always-on VPN" / "Bloquear conexões sem VPN" nas configurações do sistema — ela faz o mesmo sem editar config nenhuma.This PostUp/PostDown is the WireGuard project's own recipe for a Linux kill switch. In the official phone apps (Android/iOS), look for "Always-on VPN" / "Block connections without VPN" in the system settings — it does the same thing with no config editing.

WireGuard gerenciadoManaged WireGuard

Quando configurar à mão em vários dispositivos cansa, wg-easy (um contêiner com painel web) e Tailscale/Netbird (redes "mesh" sobre WireGuard, com login por conta) resolvem a parte chata de distribuir chaves. Internamente, todos usam o mesmo protocolo que você acabou de configurar à mão.When configuring by hand on several devices gets old, wg-easy (a container with a web panel) and Tailscale/Netbird (WireGuard-based "mesh" networks with account login) solve the tedious part of distributing keys. Internally, all of them use the same protocol you just configured by hand.

Wireshark e tcpdump: ver os pacotesWireshark and tcpdump: seeing the packets

tcpdump captura pacotes no terminal; Wireshark faz o mesmo com uma interface gráfica para ler e filtrar o que foi capturado. Os dois leem a mesma coisa: os bytes que realmente passam pela sua placa de rede, camada por camada.tcpdump captures packets in the terminal; Wireshark does the same with a graphical interface to read and filter what was captured. Both read the same thing: the bytes that actually travel through your network card, layer by layer.

InstalarInstall

sudo apt install tcpdump wireshark termshark   # termshark = Wireshark no terminal
sudo usermod -aG wireshark $USER               # captura sem sudo (requer novo login)

Exercício 1: ver um handshake TCPExercise 1: see a TCP handshake

sudo tcpdump -i any -n port 80 -c 20 &          # captura em segundo plano
curl -s http://example.com -o /dev/null
wait

Resultado esperado: três linhas com flags [S], [S.], [.] (o SYN, SYN-ACK, ACK da seção de sessões), depois pacotes [P.] com dados, e no fim [F.] de cada lado fechando a conexão. É o diagrama da seção "Sessões", agora em bytes de verdade.Expected result: three lines with flags [S], [S.], [.] (the SYN, SYN-ACK, ACK from the sessions section), then [P.] data packets, and at the end [F.] from each side closing the connection. It is the "Sessions" diagram, now in real bytes.

Exercício 2: texto puro vs. cifradoExercise 2: plain text vs. encrypted

sudo tcpdump -i any -n -A port 80 -c 30 &
curl -s http://neverssl.com -o /dev/null
wait
# compare:
sudo tcpdump -i any -n -A port 443 -c 30 &
curl -s https://example.com -o /dev/null
wait
captura da porta 80 (HTTP)port 80 capture (HTTP) GET / HTTP/1.1 Host: neverssl.com ← tudo legível← all readable captura da porta 443 (HTTPS)port 443 capture (HTTPS) \x17\x03\x03\x00\x45\xa2\xf1... (bytes sem sentido)(meaningless bytes) ← cifrado pelo TLS← encrypted by TLS
Resultado esperado: a captura da porta 80 mostra a requisição HTTP em texto puro, inclusive o Host; a da 443 mostra só ruído — é o TLS funcionando. Isso é literalmente por que HTTPS existe.Expected result: the port-80 capture shows the HTTP request in plain text, including the Host; the 443 one shows only noise — that is TLS working. This is literally why HTTPS exists.

Filtros essenciaisEssential filters

Filtro (Wireshark)Filter (Wireshark)MostraShows
tcp.port == 443tráfego HTTPSHTTPS traffic
httprequisições e respostas HTTP decodificadasdecoded HTTP requests and responses
dnsconsultas e respostas de DNSDNS queries and responses
ip.addr == 10.8.0.1tudo de/para um IPeverything to/from one IP
tcp.flags.syn == 1 && tcp.flags.ack == 0só os SYN iniciais (útil para achar varreduras de porta)only the initial SYNs (useful for spotting port scans)
tcpdump -i any -n port 53                               # equivalente em tcpdump
tcpdump -i any -n "tcp[13] & 2 != 0 and tcp[13] & 16 = 0"  # só SYN (sem ACK) — filtro cru de bits
sudo tcpdump -i any -w captura.pcap                      # salva para abrir no Wireshark depois

Firewall: medir a defesa com o nmapFirewall: measuring the defence with nmap

A nota de Linux explica a teoria do firewall. Aqui o exercício é fechar o laço: configurar uma regra e provar com o nmap que ela funciona, de fora para dentro.The Linux note explains the firewall theory. Here the exercise is to close the loop: set a rule and prove with nmap that it works, from the outside in.

Exercício: negar por padrão e medir com nmapExercise: deny by default and measure with nmap

# ANTES: confirme o que está aberto hoje
sudo ss -tulpn
nmap -p- localhost

# aplique uma política restritiva (ufw; veja a nota de Linux para nftables puro)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp          # não se tranque fora se isto for remoto!
sudo ufw enable

# DEPOIS: meça de novo
nmap -p- localhost
antesbefore 22 ssh 80 http 3000 app-dev 5432 postgres depoisafter 22 ssh 80 filtrada80 filtered 3000 filtrada3000 filtered 5432 filtrada5432 filtered
O nmap antes mostra tudo que estava escutando sem querer; depois, só o que você liberou de propósito.nmap before shows everything that was listening unintentionally; after, only what you opened on purpose.

Resultado esperado: o segundo nmap -p- mostra só a porta 22 (ou as que você liberou de propósito); as outras aparecem como filtered em vez de open. Se alguma porta que você queria aberta sumiu, falta uma regra ufw allow para ela.Expected result: the second nmap -p- shows only port 22 (or whichever you opened on purpose); the others show as filtered instead of open. If a port you wanted open disappeared, it is missing a ufw allow rule.

Teste primeiro numa VM ou contêiner descartável. Se estiver numa máquina remota, confirme que a porta do SSH está liberada antes de ativar o ufw, ou abra uma segunda sessão para testar sem se trancar fora.Test on a throwaway VM or container first. If you are on a remote machine, confirm the SSH port is allowed before enabling ufw, or open a second session to test without locking yourself out.

ARP spoofing: se passar pelo roteador da sua própria redeARP spoofing: posing as your own network's router

ARP (Address Resolution Protocol) traduz um IP para o endereço MAC da placa de rede, numa LAN, mas não tem nenhuma autenticação: qualquer host pode anunciar "este IP é meu MAC" e os outros aceitam sem verificar. ARP spoofing (ou ARP poisoning) explora exatamente isso para se colocar no meio do tráfego de outra máquina — um ataque man-in-the-middle clássico, só dentro da sua própria LAN.ARP (Address Resolution Protocol) translates an IP into a network card's MAC address on a LAN, but has no authentication at all: any host can announce "this IP is mine" and others accept it without checking. ARP spoofing (or ARP poisoning) exploits exactly that to insert itself into another machine's traffic — a classic man-in-the-middle attack, just inside your own LAN.

vítimavictim atacanteattacker roteador realreal router "o IP do roteador é o MEU MAC""the router's IP is MY MAC" O atacante manda ARP replies forjados para os dois lados; cada um passa a mandarThe attacker sends forged ARP replies to both sides; each one now sends its o tráfego do outro para o atacante, que o repassa (e pode ler ou alterar).traffic for the other to the attacker, who forwards it on (and can read or alter it). tráfego da vítima para a internet agora passa pelo atacante primeirothe victim's traffic to the internet now passes through the attacker first
Nenhum pacote "quebra" nada: ARP simplesmente confia em quem fala por último.No packet "breaks" anything: ARP simply trusts whoever speaks last.
Faça este exercício só na sua própria rede doméstica ou numa rede Docker isolada, com dispositivos seus. Interceptar tráfego de terceiros, mesmo "só para ver", é crime na maioria dos países.Only do this exercise on your own home network or an isolated Docker network, with devices of your own. Intercepting someone else's traffic, even "just to see", is a crime in most countries.

Exercício: ver a tabela ARP mudarExercise: watch the ARP table change

# numa VM "vítima", confira a tabela ARP normal
ip neigh show                     # mostra IP, MAC, interface de cada vizinho conhecido

# numa segunda VM "atacante", na MESMA rede, instale o arpspoof (pacote dsniff)
sudo apt install dsniff
sudo arpspoof -i eth0 -t IP_DA_VITIMA IP_DO_ROTEADOR   # anuncia: "eu sou o roteador"

# de volta na vítima, enquanto o comando acima roda:
ip neigh show                     # o MAC associado ao IP do roteador mudou?

Resultado esperado: o MAC associado ao IP do roteador na tabela ARP da vítima passa a ser o MAC da máquina atacante, sem nenhum alerta visível — é exatamente por isso que o ataque funciona tão bem. Combine com o Wireshark da seção anterior (filtro arp) para ver os ARP replies forjados chegando repetidamente.Expected result: the MAC associated with the router's IP in the victim's ARP table becomes the attacker machine's MAC, with no visible warning — this is exactly why the attack works so well. Pair it with the Wireshark from the previous section (arp filter) to see the forged ARP replies arriving repeatedly.

Defesa: detectar e, onde possível, travarDefence: detect, and lock down where you can

ControleControlComo funcionaHow it works
arpwatchdaemon que observa a rede e avisa (por e-mail/log) quando um IP troca de MAC — detecta o spoofing em segundosa daemon that watches the network and alerts (email/log) when an IP changes MAC — detects spoofing within seconds
ARP estático para hosts críticosStatic ARP for critical hostsip neigh add IP lladdr MAC nud permanent dev eth0 fixa o MAC do roteador/gateway, ignorando qualquer ARP reply forjado
Dynamic ARP Inspection (DAI)Dynamic ARP Inspection (DAI)recurso de switches gerenciados (Cisco, muitos domésticos "prosumer"): só aceita ARP replies que casam com o DHCP conhecidoa managed-switch feature (Cisco, many "prosumer" home switches): only accepts ARP replies that match known DHCP leases
VPN de ponta a ponta (WireGuard, acima)End-to-end VPN (WireGuard, above)não impede o spoofing, mas o tráfego dentro do túnel já está cifrado — o atacante no meio só vê ruídodoes not stop the spoofing, but traffic inside the tunnel is already encrypted — the attacker in the middle only sees noise
sudo apt install arpwatch
sudo systemctl enable --now arpwatch
# gere o spoof de novo (exercício acima) e observe:
sudo journalctl -u arpwatch -f    # ou /var/log/syslog, dependendo da distro

Resultado esperado: o arpwatch registra uma linha changed ethernet address para o IP do roteador, com o MAC antigo e o novo — o mesmo evento que, numa rede de verdade, dispararia um alerta para o time de segurança.Expected result: arpwatch logs a changed ethernet address line for the router's IP, with the old and new MAC — the same event that, on a real network, would fire an alert to the security team.

O kit de reconhecimento, com limitesThe recon kit, with limits

Um time de segurança (e um atacante) usa um kit pequeno e bem conhecido. Conhecer os nomes e para que servem já tira o mistério; usá-los de verdade exige sempre o mesmo limite: sistemas seus ou autorização explícita por escrito (um contrato de pentest, uma competição de CTF, um laboratório próprio).A security team (and an attacker) uses a small, well-known kit. Knowing the names and what they are for already removes the mystery; actually using them always requires the same boundary: your own systems or explicit written authorization (a pentest contract, a CTF competition, your own lab).

FerramentaToolPara quêWhat it is forJá viu nesta nota?Seen in this note?
nmapdescobrir hosts e portasdiscovering hosts and portssimyes
Wireshark / tcpdumpler o tráfegoreading trafficsimyes
netcat (nc)canivete de rede: testar portas, mandar/ouvir bytes crusnetwork Swiss Army knife: testing ports, sending/listening raw bytesnota de LinuxLinux note
Scanners de vulnerabilidade (Nessus, OpenVAS)Vulnerability scanners (Nessus, OpenVAS)comparam serviços e versões com um banco de falhas conhecidascompare services and versions against a database of known flawsnão (fora do 80/20)no (outside the 80/20)
Proxies de aplicação web (Burp Suite, OWASP ZAP)Web app proxies (Burp Suite, OWASP ZAP)interceptam e editam requisições HTTP para testar uma aplicaçãointercept and edit HTTP requests to test an applicationnãono
Testadores de senha (Hydra, John the Ripper)Password testers (Hydra, John the Ripper)tentam credenciais ou quebram hashes para medir a força de senhastry credentials or crack hashes to measure password strengthnãono
Frameworks de exploração (Metasploit)Exploitation frameworks (Metasploit)automatizam o uso de falhas conhecidas contra um alvo autorizadoautomate using known flaws against an authorized targetnãono
Esse kit é literalmente o currículo de certificações defensivas como CompTIA Security+ e do caminho de pentest como o eJPT/OSCP — e também o que times de "blue team" usam ao contrário, para caçar essas mesmas ferramentas sendo usadas contra eles nos logs. Se quiser praticar de verdade, plataformas como TryHackMe e Hack The Box dão alvos de propósito, de forma legal.This kit is literally the curriculum of defensive certifications like CompTIA Security+ and of the pentest path like eJPT/OSCP — and also what "blue team" defenders use in reverse, hunting for these same tools being used against them in the logs. If you want to practice for real, platforms like TryHackMe and Hack The Box give you purpose-built, legal targets.

O único exercício seguro de "ataque": força bruta contra o seu próprio SSHThe one safe "attack" exercise: brute force against your own SSH

# no seu laboratório: veja as tentativas de login falharem, do lado do SERVIDOR
sudo journalctl -u ssh -f &
# de outro terminal, erre a senha de propósito algumas vezes
ssh ana@localhost   # digite qualquer coisa errada, 3x

# instale e observe o fail2ban reagir
sudo apt install fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Resultado esperado: o journal mostra Failed password para cada tentativa; depois de configurar o fail2ban (padrão: 5 tentativas), o IP some de fail2ban-client status sshd e entra na lista de banidos — tente de novo e a conexão nem completa o handshake TCP.Expected result: the journal shows Failed password for each attempt; after setting up fail2ban (default: 5 attempts), the IP shows up in fail2ban-client status sshd's ban list — try again and the connection does not even complete the TCP handshake.

Docker para o laboratório localDocker for the local lab

Para praticar com duas ou mais "máquinas" sem comprar duas máquinas, o jeito mais rápido é o Docker. Mas a rede de um contêiner não é a rede de uma máquina real, e isso confunde muita gente quando o laboratório não se comporta como esperado. Esta seção explica as duas, nessa ordem.To practice with two or more "machines" without buying two machines, the fastest way is Docker. But a container's network is not a real machine's network, and that confuses a lot of people when the lab does not behave as expected. This section explains both, in that order.

Sem Docker: como é numa máquina de verdadeWithout Docker: how it is on a real machine

sua máquinayour machine processosprocesses placa de rede (NIC)network card (NIC) switch físicophysical switch roteador / internetrouter / internet Um IP real por NIC. O firewall do Linux (netfilter) decide o que entra e sai nessa única interface.One real IP per NIC. Linux's firewall (netfilter) decides what comes in and out through that one interface. Outra máquina na rede fala com você por um switch e um cabo/Wi-Fi físicos — há hardware real no meio.Another machine on the network talks to you through a physical switch and cable/Wi-Fi — there is real hardware in between.
A rede "de verdade": uma interface, um firewall, hardware real entre as máquinas.The "real" network: one interface, one firewall, real hardware between machines.

Com Docker: uma rede inteira simulada dentro da sua máquinaWith Docker: a whole network simulated inside your machine

sua máquina (host)your machine (host) eth0 IP realreal IP docker0 (bridge) 172.17.0.1 -p 8080:80 NAT contêiner Acontainer A 172.17.0.2 contêiner Bcontainer B 172.17.0.3 docker0 é um switch de software; cada contêiner ganha um par "veth" (um cabo de rede virtual).docker0 is a software switch; each container gets a "veth" pair (a virtual network cable).
Namespaces de rede dão a cada contêiner sua própria pilha de rede (interfaces, rotas, regras); o docker0 os liga como um switch e faz NAT para o mundo de fora.Network namespaces give each container its own network stack (interfaces, routes, rules); docker0 links them like a switch and NATs them out to the world.
TermoTermO que éWhat it is
Namespace de redeNetwork namespaceuma pilha de rede isolada por processo/contêiner: suas próprias interfaces, rotas e regras de firewallan isolated network stack per process/container: its own interfaces, routes and firewall rules
veth pairveth pairum "cabo" de rede virtual com duas pontas: uma dentro do contêiner, outra ligada ao bridgea virtual network "cable" with two ends: one inside the container, one plugged into the bridge
Bridge (docker0)Bridge (docker0)um switch de software que liga os contêineres entre si e ao hosta software switch that links containers to each other and to the host
-p 8080:80-p 8080:80uma regra de NAT: tráfego na porta 8080 do HOST é redirecionado para a 80 do contêinera NAT rule: traffic on the HOST's port 8080 is redirected to the container's port 80
DNS embutidoEmbedded DNSo Docker roda um DNS interno (127.0.0.11) para contêineres se acharem pelo nome do serviçoDocker runs an internal DNS server (127.0.0.11) so containers find each other by service name
A diferença que mais confunde: dois contêineres na mesma rede Docker se enxergam direto, sem passar pelo firewall do host — o netfilter do host só vê o tráfego que cruza para fora do bridge. Isso também já apareceu na nota de Linux: regras do Docker ficam numa cadeia própria (DOCKER-USER) e podem abrir uma porta ao mundo mesmo com o ufw negando. Nunca assuma que um firewall de host protege contêineres sem conferir.The most confusing difference: two containers on the same Docker network see each other directly, without going through the host firewall — the host's netfilter only sees traffic that crosses out of the bridge. This also showed up in the Linux note: Docker's rules live in their own chain (DOCKER-USER) and can open a port to the world even with ufw denying it. Never assume a host firewall protects containers without checking.

Laboratório: duas "máquinas" em contêineresLab: two "machines" in containers

mkdir lab-rede && cd lab-rede
cat > docker-compose.yml <<'EOF'
services:
  alvo:
    image: nginx
    networks: [lab]
  ferramentas:
    image: instrumentisto/nmap     # já vem com nmap, tcpdump, curl
    networks: [lab]
    command: sleep infinity
networks:
  lab:
    driver: bridge
EOF
docker compose up -d
docker compose exec ferramentas nmap alvo          # escaneia pelo NOME (o DNS embutido resolve)
docker compose exec ferramentas sh -c "nc -zv alvo 80 && echo OK"

Resultado esperado: nmap alvo resolve o nome pelo DNS interno do Docker e mostra 80/tcp open, mesmo sem nenhum -p no docker-compose.yml — porque, dentro da rede lab, os contêineres se enxergam direto, sem precisar publicar porta nenhuma. Compare com o exercício de nmap da seção anterior, feito do HOST contra a porta publicada: são dois cenários diferentes, e é exatamente essa diferença que costuma confundir.Expected result: nmap alvo resolves the name through Docker's internal DNS and shows 80/tcp open, even with no -p at all in docker-compose.yml — because, inside the lab network, the containers see each other directly, with no port to publish. Compare this with the nmap exercise from the previous section, done from the HOST against the published port: these are two different scenarios, and that difference is exactly what usually trips people up.

Onde a simulação paraWhere the simulation stops

No contêinerIn the containerNuma máquina/nuvem realOn a real machine/cloud
Um "cabo" virtual (veth) sem latência realA virtual "cable" (veth) with no real latencycabo, Wi-Fi ou fibra de verdade, com latência, perda de pacote e limite de banda reaisa real cable, Wi-Fi or fibre, with real latency, packet loss and bandwidth limits
Um switch de software (docker0) sem ARP de verdadeA software switch (docker0) with no real ARPum switch físico (ou uma VPC na nuvem) com tabelas ARP, VLANs, possivelmente outros inquilinosa physical switch (or a cloud VPC) with ARP tables, VLANs, possibly other tenants
Firewall do host pode nem ver o tráfego entre contêineresHost firewall may not even see inter-container trafficgrupos de segurança/NACLs da nuvem, e o firewall do SO, realmente filtram cada pacotecloud security groups/NACLs, and the OS firewall, really filter every packet
IP muda a cada docker compose upIP changes on every docker compose upIP costuma ser estável (ou um Elastic IP/DNS gerenciado)IP is usually stable (or a managed Elastic IP/DNS)

Use contêineres para aprender comandos e ler saídas sem custo. Para medir o que um atacante real veria — latência, firewall de verdade, uma rota pela internet — volte para uma VM real ou de nuvem (nota de AWS) de vez em quando.Use containers to learn commands and read output at no cost. To measure what a real attacker would see — latency, a real firewall, a route across the actual internet — go back to a real or cloud VM (AWS note) every so often.

Cola e revisãoCheat sheet and review

ColaCheat sheet

Quero…I want…ComandoCommand
ver conexões TCP abertassee open TCP connectionsss -tn state established
escanear minha própria máquinascan my own machinenmap -sV -p- localhost
abrir um túnel SSH para um serviço remotoopen an SSH tunnel to a remote servicessh -L porta_local:localhost:porta ana@servidor
subir minha VPNbring my VPN upsudo wg-quick up wg0 · sudo wg show
capturar um handshake TCPcapture a TCP handshakesudo tcpdump -i any -n port 80 -c 20
provar que o firewall funcionaprove the firewall worksnmap -p- localhost antes e depois do ufw enable
ver o Docker simular uma redesee Docker simulate a networkdocker network inspect bridge
ver a tabela ARP e fixar uma entradasee the ARP table and pin an entryip neigh show · ip neigh add IP lladdr MAC nud permanent dev eth0
detectar ARP spoofingdetect ARP spoofingsudo systemctl enable --now arpwatch

Perguntas de revisãoReview questions

PerguntaQuestionRespostaAnswer
Por que o TCP é "com estado" e o UDP não?Why is TCP "stateful" and UDP is not?TCP abre uma conexão com handshake e numera/reenvia bytes; UDP manda datagramas independentes, sem conexão.TCP opens a connection with a handshake and numbers/resends bytes; UDP sends independent datagrams, with no connection.
O que significa uma porta aparecer "filtered" no nmap?What does a port showing "filtered" in nmap mean?O pacote de teste não teve resposta nenhuma — geralmente um firewall descartando, em vez de recusar.The test packet got no reply at all — usually a firewall dropping it instead of refusing it.
Qual a diferença entre ssh -L e ssh -R?What is the difference between ssh -L and ssh -R?-L leva uma porta sua até o lado de lá; -R leva uma porta de lá até o seu lado.-L carries a port of yours to the far side; -R carries a port from the far side to you.
Por que o WireGuard manda pacotes de keepalive?Why does WireGuard send keepalive packets?Porque é UDP, sem sessão; sem keepalive, o NAT no meio do caminho esquece a tradução depois de um tempo.Because it is UDP, with no session; without keepalives, NAT along the way forgets the translation after a while.
Como o Wireshark prova que o HTTPS funciona?How does Wireshark prove HTTPS works?Uma captura da porta 443 mostra só bytes sem sentido, enquanto a da porta 80 mostra a requisição em texto puro.A port-443 capture shows only meaningless bytes, while the port-80 one shows the request in plain text.
Dois contêineres no mesmo docker-compose.yml precisam de -p para se enxergar?Do two containers in the same docker-compose.yml need -p to see each other?Não: na mesma rede Docker eles se enxergam direto pelo nome do serviço; -p é só para expor ao HOST.No: on the same Docker network they see each other directly by service name; -p is only to expose to the HOST.
Que ferramentas requerem autorização explícita antes de usar?Which tools require explicit authorization before use?Praticamente todas desta nota contra sistemas que não são seus: nmap, testadores de senha, frameworks de exploração.Practically all of this note's tools, against systems that are not yours: nmap, password testers, exploitation frameworks.
Por que o ARP spoofing funciona sem explorar nenhum bug?Why does ARP spoofing work without exploiting any bug?O protocolo ARP não tem autenticação: ele confia no último ARP reply recebido para cada IP.The ARP protocol has no authentication: it trusts the last ARP reply received for each IP.

Fontes recomendadasRecommended sources

Os livros abaixo aprofundam cada ferramenta desta nota.The books below go deeper into each tool in this note.