Redes e web
TCP/IP e portas: como os serviços escutam na sua máquina
Porta é uma entrada numerada na sua máquina. Entenda como TCP e UDP usam portas e teste um servidor local em 127.0.0.1.
Leia uma troca HTTP real linha por linha: métodos, URLs, cabeçalhos, classes de status e cookies, testados com curl em um servidor local.
HTTP é o protocolo que navegadores, apps e APIs usam para trocar mensagens. A RFC 9110 define o que essas mensagens significam: métodos, códigos de status, campos de cabeçalho e assim por diante. A RFC 9112 define como uma mensagem HTTP/1.1 se parece em texto puro sobre uma conexão TCP. A visão geral da MDN é uma introdução mais curta, voltada ao navegador, e funciona bem ao lado das RFCs.
O padrão é simples. Um cliente envia uma requisição, e um servidor devolve uma resposta. Quem sempre começa a troca é o cliente. HTTP puro não criptografa nada e não lembra quem você é entre uma requisição e outra. A criptografia vem do TLS, que o próximo artigo explica. A memória entre requisições vem de cookies e tokens, que veremos mais adiante.
Quase todo comportamento web que você vai estudar passa pelo HTTP. Um formulário envia um valor no corpo, uma API confia em um cabeçalho, um redirecionamento leva o usuário para outro lugar e um cache guarda a cópia errada de uma página. Quando você usar depois um proxy como o OWASP ZAP para inspecionar tráfego, ele vai mostrar exatamente essas mensagens. Se você não consegue ler uma requisição crua, a saída do proxy vira ruído.
Uma requisição HTTP/1.1 é texto puro nesta forma:
GET / HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: curl/8.12.1
Accept: */*A primeira linha é a linha de requisição: o método, o alvo da requisição e a versão do protocolo. Cada linha seguinte é um campo de cabeçalho, escrito como nome: valor. Uma linha em branco encerra a seção de cabeçalhos. Se a mensagem tiver corpo, ele vem depois dessa linha em branco. No fio, cada linha termina com CRLF (um retorno de carro seguido de uma quebra de linha), que o editor esconde de você.
Uma resposta segue o mesmo layout, com uma linha de status no topo: versão, código de status e frase de motivo.
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 15
<h1>hello</h1>O método diz o que o cliente quer que seja feito. A RFC 9110 define GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS e TRACE. O PATCH vem da RFC 5789.
Duas propriedades importam quando você lê tráfego:
Essas propriedades são promessas sobre significado. Quem decide o que realmente acontece é o servidor. Um handler de GET que apaga um registro quebra esse contrato, e um revisor de segurança vai procurar exatamente esse erro.
Pegue a URL http://127.0.0.1:8000/missing?lang=en#top e separe as partes:
http, que diz ao cliente qual protocolo usar.127.0.0.1:8000, o host e a porta opcional./missing.lang=en, depois do ?.top, depois do #.O cliente não envia o esquema nem o fragmento ao servidor. A linha de requisição leva o caminho e a query. A autoridade vai no cabeçalho Host. O HTTP/1.1 exige Host porque muitos sites podem compartilhar um mesmo IP, e o servidor usa esse cabeçalho para decidir qual site deve responder.
Nomes de cabeçalho não diferenciam maiúsculas de minúsculas, então Content-Type e content-type são o mesmo campo (RFC 9110, seção 5.1). Os valores são outra história: muitos diferenciam maiúsculas, então não presuma que não diferenciam.
Cabeçalhos de requisição que você vai ver com mais frequência:
Host: obrigatório em toda requisição HTTP/1.1. A RFC 9112, seção 3.2, diz que o servidor deve responder 400 quando ele faltar.User-Agent: o software do cliente.Accept: os tipos de mídia que o cliente consegue tratar.Cookie: os cookies que o navegador devolve ao servidor.Authorization: credenciais, muitas vezes um token bearer.Content-Type e Content-Length: descrevem o corpo, quando há um.Cabeçalhos de resposta que você vai ver com mais frequência:
Content-Type: o tipo de mídia do corpo, como text/html.Content-Length: o tamanho do corpo em bytes.Date: o relógio do servidor, em GMT.Server: o nome do software. Muitos servidores o exibem. Em produção, costuma-se ocultá-lo.Last-Modified: quando o servidor alterou o recurso pela última vez.Set-Cookie: pede ao navegador que guarde um cookie.Cabeçalhos são dados que quem envia controla. O navegador envia o que o software dele envia, e um script ou um proxy pode enviar o que quiser. O X-Forwarded-For é o exemplo clássico: um proxy o adiciona, mas um cliente também pode enviá-lo. Nunca confie em um cabeçalho só porque ele parece oficial.
Um código de status tem três dígitos. O primeiro dígito indica a classe, definida na RFC 9110, seção 15:
| Classe | Significado | Exemplos |
|---|---|---|
| 1xx | Informativo. A requisição foi recebida e o processamento continua | 100 Continue |
| 2xx | Sucesso | 200 OK, 201 Created, 204 No Content |
| 3xx | Redirecionamento. O cliente precisa dar outro passo | 301 Moved Permanently, 304 Not Modified |
| 4xx | Erro do cliente. A requisição tem um problema | 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 405 Method Not Allowed |
| 5xx | Erro do servidor. O servidor não conseguiu atender a uma requisição válida | 500, 501 Not Implemented, 502, 503 |
Mesmo quando o cliente não reconhece um código específico, ele consegue agir pela classe. Um 4xx indica que a requisição precisa mudar. Um 5xx indica que a mesma requisição pode funcionar depois.
Dois códigos são confundidos com frequência. Um 401 significa que a requisição não tem credenciais válidas. Um 403 significa que o servidor entendeu a requisição e a recusa, mesmo com credenciais.
A frase de motivo, como Not Found, é um texto escolhido pelo servidor. A RFC 9112, seção 4, diz que o cliente deve ignorá-la. Escreva a lógica em cima do número, nunca das palavras.
Cookies não fazem parte da RFC 9110. Eles são definidos na RFC 6265. O ciclo funciona assim:
Set-Cookie: session=abc123; Path=/; HttpOnly; Secure; SameSite=Lax.Cookie: session=abc123.Um cookie de sessão é um identificador que o servidor entrega. Ele não é uma senha, e não é privado do usuário. Quem tem o valor normalmente consegue agir como aquela sessão até ela expirar ou ser revogada. HttpOnly impede que scripts da página leiam o valor. Secure permite enviá-lo só por HTTPS. SameSite limita quando o navegador o envia em requisições entre sites. Os artigos de segurança web voltam a esses atributos.
Você precisa de curl e Python 3. O Git Bash no Windows 11 inclui o curl, e a maioria dos sistemas Linux e macOS também tem. O servidor é o http.server, que vem com o Python. Rode-o apenas na sua máquina, preso a 127.0.0.1, e nunca o exponha a uma rede.
A saída abaixo vem de executar estes comandos no Windows 11 com Git Bash, curl 8.12.1 e Python 3.12.10. Nessa máquina, o python3 não estava no PATH do Git Bash, então o servidor foi iniciado com o caminho completo do executável Python 3.12. Use python3, py -3 ou python, conforme o seu sistema. Suas datas, horários e versões vão ser diferentes. A barra de progresso do curl foi removida da saída abaixo, e corpos HTML longos foram encurtados.
No primeiro terminal:
mkdir httplab && cd httplab && echo '<h1>hello</h1>' > index.html
python3 -m http.server 8000 --bind 127.0.0.1Deixe esse terminal aberto. O servidor escreve uma linha de log por requisição, então cada requisição que você enviar abaixo vai aparecer aqui.
No segundo terminal:
curl -v http://127.0.0.1:8000/Saída:
* Trying 127.0.0.1:8000...
* Connected to 127.0.0.1 (127.0.0.1) port 8000
* using HTTP/1.x
> GET / HTTP/1.1
> Host: 127.0.0.1:8000
> User-Agent: curl/8.12.1
> Accept: */*
>
* Request completely sent off
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/3.12.10
< Date: Sun, 08 Nov 2026 08:16:48 GMT
< Content-type: text/html
< Content-Length: 15
< Last-Modified: Sun, 08 Nov 2026 08:13:48 GMT
<
<h1>hello</h1>
* shutting down connection #0Leia nesta ordem:
* são anotações do curl sobre a conexão.> são o que o curl enviou. O próprio curl acrescentou Host, User-Agent e Accept.< são o que o servidor devolveu.> vazia encerra os cabeçalhos da requisição. A linha < vazia encerra os cabeçalhos da resposta.<h1>hello</h1> é o corpo. Content-Length: 15 bate com o arquivo, porque o echo acrescentou uma quebra de linha depois da tag.HTTP 1.0, assume close after body mostra um descompasso. O curl pediu HTTP/1.1, mas o servidor respondeu em HTTP/1.0. O servidor simples do Python fala HTTP/1.0, então o curl fecha a conexão assim que lê o corpo.curl -i http://127.0.0.1:8000/missingA opção -i mostra os cabeçalhos da resposta junto com o corpo. Saída, com o corpo HTML encurtado:
HTTP/1.0 404 File not found
Server: SimpleHTTP/0.6 Python/3.12.10
Date: Sun, 08 Nov 2026 08:16:49 GMT
Connection: close
Content-Type: text/html;charset=utf-8
Content-Length: 335
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error response</title>
</head>
<body>
<h1>Error response</h1>
<p>Error code: 404</p>
<p>Message: File not found.</p>
<p>Error code explanation: 404 - Nothing matches the given URI.</p>
</body>
</html>Olhe o primeiro terminal. Ele registrou:
127.0.0.1 - - [08/Nov/2026 05:16:49] code 404, message File not found
127.0.0.1 - - [08/Nov/2026 05:16:49] "GET /missing HTTP/1.1" 404 -O código de status é 404, um código da classe de erro do cliente: o caminho não corresponde a nenhum recurso. A frase de motivo File not found é o texto escolhido pelo próprio servidor. O corpo é uma página HTML que o servidor gerou para o erro. Qualquer status pode trazer qualquer corpo, então leia os dois.
O log mostra 05:16 e o cabeçalho Date mostra 08:16. O log usa o horário local e o cabeçalho usa GMT, então os dois diferem pelo deslocamento do fuso local.
curl -i -X POST http://127.0.0.1:8000/Saída, com o corpo HTML encurtado:
HTTP/1.0 501 Unsupported method ('POST')
Server: SimpleHTTP/0.6 Python/3.12.10
Date: Sun, 08 Nov 2026 08:16:49 GMT
Connection: close
Content-Type: text/html;charset=utf-8
Content-Length: 357
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error response</title>
</head>
<body>
<h1>Error response</h1>
<p>Error code: 501</p>
<p>Message: Unsupported method ('POST').</p>
<p>Error code explanation: 501 - Server does not support this operation.</p>
</body>
</html>A linha de log diz code 501, message Unsupported method ('POST'). A opção -X muda só o método. O curl enviou os mesmos cabeçalhos de antes.
O servidor simples não tem nenhum handler de POST, então 501 Not Implemented é a resposta honesta. A RFC 9110, seção 15.6.2, define o 501 para um servidor que não oferece a funcionalidade de que a requisição precisa. Uma aplicação real que conhece o recurso, mas recusa POST nele, normalmente responderia 405 Method Not Allowed. Uma resposta 405 precisa incluir um cabeçalho Allow com os métodos que o recurso aceita.
curl -I http://127.0.0.1:8000/index.htmlSaída:
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.12.10
Date: Sun, 08 Nov 2026 08:16:50 GMT
Content-type: text/html
Content-Length: 15
Last-Modified: Sun, 08 Nov 2026 08:13:48 GMT
A opção -I envia uma requisição HEAD. O status e os cabeçalhos são iguais aos de um GET, mas nenhum corpo vem depois. O Content-Length continua dizendo 15, porque descreve a representação que um GET devolveria. A RFC 9110, seção 9.3.2, define esse comportamento. O log mostra "HEAD /index.html HTTP/1.1" 200 -.
O HEAD é útil quando você quer saber se um arquivo existe, qual é o tamanho dele ou quando foi alterado pela última vez, sem baixá-lo.
curl -v -H 'Cookie: session=demo123' http://127.0.0.1:8000/As linhas relevantes da saída:
> GET / HTTP/1.1
> Host: 127.0.0.1:8000
> User-Agent: curl/8.12.1
> Accept: */*
> Cookie: session=demo123
>
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/3.12.10
< Date: Sun, 08 Nov 2026 08:18:28 GMT
< Content-type: text/html
< Content-Length: 15
< Last-Modified: Sun, 08 Nov 2026 08:13:48 GMT
< A linha do corpo foi omitida aqui. O servidor respondeu com o mesmo 200 de antes, porque não tem lógica de cookies e ignora o cabeçalho. Esse é o ponto do exercício. O navegador envia cookies, mas quem decide o que eles significam é o servidor. Um servidor que nunca define um cookie não vai agir sobre um que você enviar.
Pressione Ctrl+C no primeiro terminal quando terminar.
Host, User-Agent, Cookie e X-Forwarded-For vêm todos do lado do cliente. Valide-os no servidor.127.0.0.1.-X mude os cabeçalhos. Ele muda só o método. Para adicionar cabeçalhos, use -H.Content-Length e Transfer-Encoding.:8000 da URL.Um proxy como o ZAP exibe essas mesmas mensagens, e é por isso que este artigo dá base para os próximos, sobre vulnerabilidades web. A API da NotHoly, em api.notholy.com/v1, também é uma API HTTP com corpos JSON, servida sobre TLS, então os cabeçalhos e códigos de status acima valem quando você a chama.
Redes e web
Porta é uma entrada numerada na sua máquina. Entenda como TCP e UDP usam portas e teste um servidor local em 127.0.0.1.
Redes e web
TLS 1.3 dá ao HTTPS confidencialidade, integridade e autenticação do servidor. Veja o handshake, as cadeias de certificados e o que o cadeado não prova.
Redes e web
Como o DNS transforma nomes em endereços: resolvedores, servidores autoritativos, cache por TTL, registros A, AAAA, CNAME, MX e TXT, com teste seguro.