Hands-on lab
Security, hands on.
A practical 80/20 of networking and security tools: run them on your own machines, read the output, and know exactly what success looks like.
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.
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õ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.
Por que isso importa na práticaWhy this matters in practice
| ConceitoConcept | O que significaWhat it means |
|---|---|
| Firewall statefulStateful firewall | lembra 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 conntrack | seu 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 NAT | sem 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 balancer | precisa 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.
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
-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çãoOption | FazDoes |
|---|---|
-sS | SYN scan: rápido, não completa a conexão (precisa de sudo)SYN scan: fast, does not complete the connection (needs sudo) |
-sT | connect scan: completa a conexão TCP normal (não precisa de sudo)connect scan: completes a normal TCP connection (no sudo needed) |
-sU | escaneia 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,443 | faixa, tudo, ou portas específicasa range, everything, or specific ports |
-sV | detecta a versão do serviço (“nginx 1.25”)detects the service version (“nginx 1.25”) |
-A | tudo junto: versão, SO, script básico, traceroute (mais barulhento e lento)everything together: version, OS, basic scripts, traceroute (noisier and slower) |
-T4 | mais rápido (até -T5); o padrão é conservadorfaster (up to -T5); the default is conservative |
-oN arquivo.txt | salva a saída legível em arquivosaves readable output to a file |
192.168.1.0/24 | escaneia uma faixa inteira (só na sua LAN!)scans a whole range (only on your own LAN!) |
--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.
-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
| ComandoCommand | DireçãoDirection | Use quandoUse when |
|---|---|---|
ssh -L porta_local:destino:porta ana@srv | você → servidor → destinoyou → server → destination | alcanç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@srv | servidor → vocêserver → you | expor 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@srv | proxy SOCKS: qualquer app → servidor → internetSOCKS proxy: any app → server → internet | navegar 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.
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).
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.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
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 == 443 | tráfego HTTPSHTTPS traffic |
http | requisições e respostas HTTP decodificadasdecoded HTTP requests and responses |
dns | consultas e respostas de DNSDNS queries and responses |
ip.addr == 10.8.0.1 | tudo de/para um IPeverything to/from one IP |
tcp.flags.syn == 1 && tcp.flags.ack == 0 | só 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
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.
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.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).
| FerramentaTool | Para quêWhat it is for | Já viu nesta nota?Seen in this note? |
|---|---|---|
nmap | descobrir hosts e portasdiscovering hosts and ports | simyes |
Wireshark / tcpdump | ler o tráfegoreading traffic | simyes |
netcat (nc) | canivete de rede: testar portas, mandar/ouvir bytes crusnetwork Swiss Army knife: testing ports, sending/listening raw bytes | nota 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 flaws | nã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 application | nã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 strength | nã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 target | nãono |
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
Com Docker: uma rede inteira simulada dentro da sua máquinaWith Docker: a whole network simulated inside your machine
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.| TermoTerm | O que éWhat it is |
|---|---|
| Namespace de redeNetwork namespace | uma 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 pair | um "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:80 | uma 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 DNS | o 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 |
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 container | Numa máquina/nuvem realOn a real machine/cloud |
|---|---|
| Um "cabo" virtual (veth) sem latência realA virtual "cable" (veth) with no real latency | cabo, 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 ARP | um 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 traffic | grupos 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 up | IP 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 connections | ss -tn state established |
| escanear minha própria máquinascan my own machine | nmap -sV -p- localhost |
| abrir um túnel SSH para um serviço remotoopen an SSH tunnel to a remote service | ssh -L porta_local:localhost:porta ana@servidor |
| subir minha VPNbring my VPN up | sudo wg-quick up wg0 · sudo wg show |
| capturar um handshake TCPcapture a TCP handshake | sudo tcpdump -i any -n port 80 -c 20 |
| provar que o firewall funcionaprove the firewall works | nmap -p- localhost antes e depois do ufw enable |
| ver o Docker simular uma redesee Docker simulate a network | docker network inspect bridge |
Perguntas de revisãoReview questions
| PerguntaQuestion | RespostaAnswer |
|---|---|
| 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. |
Fontes recomendadasRecommended sources
Os livros abaixo aprofundam cada ferramenta desta nota.The books below go deeper into each tool in this note.
- Gordon "Fyodor" Lyon. Nmap Network Scanning. Nmap Project (free online book).
- Jason A. Donenfeld. WireGuard: Next Generation Kernel Network Tunnel (whitepaper).
- Chris Sanders. Practical Packet Analysis, 3rd edition. No Starch Press, 2017.
- Charles M. Kozierok. The TCP/IP Guide. No Starch Press.
- Richard Bejtlich. The Practice of Network Security Monitoring. No Starch Press, 2013.
- Docker documentation. Networking overview.
- Michael Kerrisk. The Linux Programming Interface, ch. 56-61 (sockets). No Starch Press, 2010.
- CompTIA Security+ exam objectives (for the defensive side of this toolkit).