Hospede um site .onion no seu VPS com Tor e nginx
Configure um serviço onion v3 no Ubuntu com tor e nginx no loopback. Veja como evitar vazamentos que associem o endereço .onion ao IP público.
O que você está construindo
Um site onion é um servidor Web normal que só responde pela rede Tor. Instale o tor, adicione duas linhas a /etc/tor/torrc, leia o endereço que o tor gravar e vincule o nginx a 127.0.0.1 para que nada responda no IP público. A instalação demora dez minutos. O restante deste guia é uma lista de possíveis vazamentos, porque a forma habitual de um site onion falhar é a própria configuração apontar diretamente para o operador.
O Tor começou como “the onion router”, e um serviço onion é um serviço que só pode ser acessado por meio dele. Um endereço da versão 3 tem 56 caracteres seguidos de .onion. Esses caracteres correspondem à chave pública ed25519 do serviço, a uma soma de verificação e a um byte de versão, codificados em base32. Os endereços da versão 2 (16 caracteres) foram removidos da rede em 2021. Portanto, tudo o que você gerar hoje será v3. O endereço é a chave, o que tem duas consequências. A conexão é criptografada e autenticada de ponta a ponta, sem envolver uma autoridade certificadora. Se você perder o arquivo da chave, perderá o endereço permanentemente.
Seu servidor nunca aceita uma conexão de entrada. O Tor escolhe alguns relays como pontos de introdução, envia um descritor assinado aos servidores de diretório e encontra cada visitante em um relay de rendezvous escolhido pelo visitante. Todas essas conexões são de saída a partir do seu servidor. Não há nenhuma porta para abrir nem registro DNS para publicar.
Instalar tor a partir do repositório do Tor Project
O Ubuntu disponibiliza o pacote tor em universe, mas este permanece próximo da versão disponível quando a versão do sistema deixou de receber alterações. O repositório do Tor Project acompanha a versão estável atual. É essa versão que deve usar para o componente que determina se o seu endereço continua a ser seu.
sudo apt update
sudo apt install -y apt-transport-https gnupg wget
KEYURL=https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc
wget -qO- "$KEYURL" | gpg --dearmor | sudo tee /usr/share/keyrings/deb.torproject.org-keyring.gpg >/dev/nullA entrada do repositório usa o formato deb822, e Suites deve ser o codinome da sua versão do Ubuntu. Leia-o a partir de /etc/os-release em vez de o escrever manualmente. Um codinome incorreto produz um repositório que é resolvido corretamente, mas que não contém pacotes para a sua versão.
. /etc/os-release
sudo tee /etc/apt/sources.list.d/tor.sources >/dev/null <<EOF
Types: deb deb-src
URIs: https://deb.torproject.org/torproject.org/
Suites: $VERSION_CODENAME
Components: main
Signed-By: /usr/share/keyrings/deb.torproject.org-keyring.gpg
EOF
sudo apt update
sudo apt install -y tor deb.torproject.org-keyringO pacote deb.torproject.org-keyring mantém a chave de assinatura atualizada. Assim, uma rotação de chaves não interrompe apt update daqui a um ano. Verifique se tor iniciou e alcançou a rede:
tor --version
sudo journalctl -u tor@default -n 20O journal deve terminar com Bootstrapped 100% (done): Done. Um tor bloqueado em Bootstrapped 10% não tem um caminho de saída. Verifique a firewall de rede do seu fornecedor e as suas próprias regras de saída: sudo ufw status verbose deve mostrar allow (outgoing) como predefinição.
A partir daqui, há dois nomes importantes. O pacote executa tor com o utilizador debian-tor, e a unidade em execução é tor@default.service, porque tor.service no Debian e no Ubuntu é um wrapper para a instância. Consulte o estado e os logs pelo nome da instância para obter sempre o processo real.
Configurar o serviço onion no torrc
Acrescente duas linhas a /etc/tor/torrc:
HiddenServiceDir /var/lib/tor/onion_site/
HiddenServicePort 80 127.0.0.1:8080HiddenServiceDir é o local onde o tor guarda as chaves e o endereço deste serviço. Não o crie manualmente. O Tor cria-o no arranque, com o proprietário e as permissões necessárias. Um diretório criado por root provoca a primeira falha da lista abaixo.
HiddenServicePort tem duas partes, e confundi-las é o erro inicial mais comum. O primeiro número é a porta à qual um visitante se liga dentro do túnel. Por isso, 80 é o valor esperado e não há motivo para o alterar. A segunda parte é o endereço local para o qual o tor encaminha esse tráfego. Um HiddenServicePort 80 sem endereço encaminha para 127.0.0.1:80. Especificar o endereço e usar uma porta alta mantém o vhost onion separado de qualquer serviço que já esteja a escutar na porta 80.
sudo systemctl restart tor@default
sudo ls -l /var/lib/tor/onion_site/A listagem deve conter hostname, hs_ed25519_public_key, hs_ed25519_secret_key e um diretório authorized_clients vazio.
Leia o seu endereço .onion
sudo cat /var/lib/tor/onion_site/hostnameÉ devolvida uma linha: 56 caracteres base32 e .onion. Essa cadeia de caracteres é a identidade completa do site. Ninguém a atribui, ninguém a pode transferir e ninguém a pode retirar enquanto tiver o ficheiro da chave. Copie-a agora, porque todas as configurações abaixo precisam dela. O restante deste guia representa-a como <your-address>.onion.
Servir o site a partir do nginx ligado a 127.0.0.1
sudo apt install -y nginx
sudo install -d -m 755 /srv/onionEscreva /etc/nginx/sites-available/onion:
server {
listen 127.0.0.1:8080;
server_name <your-address>.onion;
root /srv/onion;
index index.html;
server_tokens off;
etag off;
access_log off;
error_log /var/log/nginx/onion.error.log error;
}echo '<h1>hello from the onion</h1>' | sudo tee /srv/onion/index.html
sudo ln -s /etc/nginx/sites-available/onion /etc/nginx/sites-enabled/onion
sudo nginx -t
sudo systemctl reload nginxAgora confirme duas coisas a partir do servidor. A primeira é que o nginx responde pelo nome onion, que corresponde exatamente ao cabeçalho Host que o tor enviará:
curl -s -H 'Host: <your-address>.onion' http://127.0.0.1:8080/A segunda é que responde nesse endereço e em nenhum outro:
sudo ss -tlnp | grep 8080A coluna de endereço deve indicar 127.0.0.1:8080. Se indicar 0.0.0.0:8080 ou *:8080, o seu site onion também está disponível na Internet pública, o que constitui o primeiro item da lista de fugas. Uma linha listen 8080; sem endereço liga-se a todas as interfaces. Esse é o comportamento predefinido.
Abra o endereço no Tor Browser. O primeiro carregamento demora alguns segundos enquanto o cliente obtém o seu descritor e cria um circuito de rendezvous.
A documentação do próprio Tor Project recomenda um socket Unix em vez de uma porta de loopback: HiddenServicePort 80 unix:/var/run/tor/onion_site.sock, com o nginx a escutar nesse caminho. Um socket não pode ser acedido a partir de outro host, mesmo que o servidor passe posteriormente a ter uma segunda interface. O custo são as permissões do ficheiro, porque o nginx cria o socket e o tor liga-se a ele como debian-tor. Por isso, os dois utilizadores têm de ter permissões compatíveis no diretório. O loopback, com um resultado ss verificado, é mais fácil de configurar corretamente e é o método assumido no restante deste guia.
Com o site no loopback, o servidor não precisa de nenhuma regra de entrada para ele. Mantenha a porta 22 aberta para si e bloqueie as restantes (os valores predefinidos do ufw que vale a pena configurar num VPS). Lembre-se de que uma firewall não anula um serviço ligado a 0.0.0.0. Apenas filtra os pacotes que chegam à firewall. Os contentores tornam este problema mais evidente, porque a publicação de uma porta Docker escreve regras iptables antes das regras do ufw. Assim, -p 8080:80 coloca o backend onion no IP público, enquanto o ufw continua a indicar que a porta está bloqueada. Publique as portas dos contentores como -p 127.0.0.1:8080:80.
Os vazamentos que desanonimizam um site onion
O Tor oculta onde o servidor está. Nada no Tor oculta o que o servidor publica. Cada item abaixo é algo que a sua própria stack expõe.
O mesmo site a responder no seu IP público
Este é o problema que apanha muitas pessoas. Os scanners indexam continuamente a resposta HTTP de todos os endereços acessíveis pela rede, e esses resultados são públicos e pesquisáveis. Sirva a mesma página no seu IP público e no seu endereço onion, e associá-los passa a exigir apenas uma pesquisa: o mesmo título, o mesmo hash do favicon, o mesmo ETag e a mesma ordem dos cabeçalhos. A linha listen 127.0.0.1:8080; acima é a correção. Verifique a partir de outra máquina, não a partir do servidor:
curl -sv --max-time 5 http://<your-public-ip>:8080/Connection refused ou um timeout é o resultado correto. Qualquer HTML significa que o site está público. Se a máquina também executar um site clearnet, atribua a esse vhost a sua própria raiz e mantenha um bloco default_server explícito no listener público, para que um cabeçalho Host não correspondente nunca seja encaminhado para o vhost onion.
Banners de versão
curl -sI http://127.0.0.1:8080/ | grep -i '^server'Um nginx padrão responde Server: nginx/1.24.0. Essa string de versão, juntamente com a ordem exata dos outros cabeçalhos, cria uma impressão digital que associa o seu onion ao host clearnet. server_tokens off; reduz isso a Server: nginx. Isto não remove o cabeçalho, e o nginx não tem uma diretiva incorporada para o remover, portanto o módulo headers-more é a opção habitual quando pretende eliminá-lo. O PHP acrescenta X-Powered-By até definir expose_php = Off. etag off; deve estar na mesma lista, porque o nginx cria o ETag a partir da hora de modificação e do tamanho de um ficheiro. Assim, os mesmos ficheiros copiados para dois servidores produzem o mesmo ETag em ambos.
URLs absolutas que apontam para o seu domínio clearnet
Uma etiqueta rel="canonical", um og:url do Open Graph, um feed RSS, um sitemap, um email de reposição de palavra-passe ou um URL de logótipo definido diretamente no código. Qualquer um deles identifica o site clearnet dentro de uma página servida pelo onion. Use caminhos relativos à raiz, como /static/logo.svg, e faça a aplicação ler o URL base a partir do host do pedido, em vez de usar uma constante. Os redirecionamentos são o mesmo problema noutro local: return 301 https://example.com$request_uri; num bloco catch-all envia o visitante onion para o seu domínio real, e o cabeçalho Location fornece-lhe a resposta diretamente.
Um certificado TLS partilhado com o site clearnet
Um endereço onion autentica-se por si próprio, porque o endereço é a chave pública. Por isso, http:// através de uma ligação onion já está cifrado de ponta a ponta, e o Tor Browser trata-o como um contexto seguro. Instalar o certificado existente no vhost onion publica a ligação entre os dois, porque todos os certificados confiados publicamente são registados nos logs de Certificate Transparency, que são públicos, permanentes e pesquisáveis por nome. Mantenha os certificados Let's Encrypt no vhost clearnet e deixe o vhost onion em HTTP simples.
Fontes e ferramentas de análise de terceiros
Uma fonte de um CDN (content delivery network) ou um script de análise. O navegador do visitante obtém cada recurso diretamente, por isso o terceiro fica a saber que alguém carregou a sua página e, normalmente, qual página foi carregada. Além disso, os níveis de segurança mais rigorosos do Tor Browser bloqueiam o pedido, deixando o layout incompleto. Aloje localmente todos os recursos necessários à página.
Incompatibilidade do cabeçalho Host
Se server_name não corresponder ao cabeçalho Host enviado pelo tor, o nginx recorre ao servidor predefinido para esse endereço de listen. Num sistema com um único vhost, isto não é visível, porque o único bloco de servidor também é o predefinido. Se adicionar posteriormente um vhost clearnet, os pedidos onion podem começar a ser encaminhados para ele, incluindo as suas etiquetas canónicas e os seus redirecionamentos. Execute novamente a verificação curl -H 'Host: ...' depois de cada alteração no nginx e procure o seu domínio real no resultado:
curl -s -H 'Host: <your-address>.onion' http://127.0.0.1:8080/ | grep -o 'https\?://[^"]*' | sort -uSaber qual processo é proprietário de cada socket constitui grande parte deste trabalho (como funcionam as portas e os sockets em escuta no Linux).
O que fica nos logs
Todos os pedidos chegam de 127.0.0.1, por isso o nginx não tem um endereço do visitante para registar e access_log off; não lhe custa nada. A aplicação acima dele é uma questão diferente, porque uma encomenda, um endereço de email ou os metadados de um ficheiro carregado são da sua responsabilidade. Os seus próprios hábitos também contam: administrar a máquina através de um login sem proteção adequada não é abrangido pelo que o Tor protege. Por isso, trate do reforço de segurança do SSH no mesmo VPS como parte desta configuração.
Faça uma cópia de segurança da chave privada, porque ela é o endereço
/var/lib/tor/onion_site/hs_ed25519_secret_key é o serviço. Não existe registrador nem recuperação. Se a perder, o endereço desaparece. Copie-a, e qualquer pessoa que tenha a cópia poderá servir o seu próprio conteúdo no seu endereço, sem que possa revogar nada.
sudo systemctl stop tor@default
sudo tar -C /var/lib/tor -czf onion-keys.tgz onion_site
sudo chmod 600 onion-keys.tgz
sudo systemctl start tor@defaultEncripte esse arquivo (gpg -c onion-keys.tgz) e retire-o do servidor. Para restaurar num novo VPS, basta o arquivo e a propriedade que o tor espera:
sudo systemctl stop tor@default
sudo tar -C /var/lib/tor -xzf onion-keys.tgz
sudo chown -R debian-tor:debian-tor /var/lib/tor/onion_site
sudo chmod 700 /var/lib/tor/onion_site
sudo systemctl start tor@default
sudo cat /var/lib/tor/onion_site/hostnameO mesmo endereço volta a funcionar no novo hardware um ou dois minutos depois de o tor republicar o descritor. Essa é toda a migração: não é necessário alterar o DNS nem emitir novamente o certificado.
Onion-Location, quando o site também está disponível na clearnet
Se o onion é uma conveniência, e não um segredo, anuncie-o a partir do vhost da clearnet:
add_header Onion-Location http://<your-address>.onion$request_uri;O Tor Browser mostra então um botão .onion available na barra de endereços e oferece a mudança. O cabeçalho só é considerado quando a página da clearnet é servida por HTTPS e o valor é um URL onion válido.
Há uma regra do nginx que causa problemas neste caso. As diretivas add_header são herdadas por um bloco location apenas quando esse bloco não declara nenhuma diretiva própria. Por isso, um location com o seu próprio add_header elimina silenciosamente o Onion-Location. Repita-o nesse bloco ou mantenha todos os cabeçalhos de resposta num único local. A publicação deliberada deste cabeçalho associa os dois sites. Isso é correto para um espelho, mas está errado para qualquer site que deva permanecer sem ligação entre si.
Endereços personalizados
mkp224o gera pares de chaves até que um deles produza um endereço que comece pelo prefixo solicitado. É uma pesquisa por força bruta. Não há nada para configurar além do prefixo e do tempo que está disposto a esperar.
sudo apt install -y git gcc libc6-dev libsodium-dev make autoconf
git clone https://github.com/cathugger/mkp224o
cd mkp224o
./autogen.sh
./configure --enable-amd64-51-30k
make
./mkp224o -d onionkeys blogCada resultado é guardado em onionkeys/<address>.onion/, que contém hostname e hs_ed25519_secret_key. Para instalar um deles, pare o tor, copie esse diretório para HiddenServiceDir e aplique o mesmo chown e chmod 700 usados no restauro acima.
O comprimento do prefixo determina todo o custo. O endereço usa base32. Por isso, cada carácter adicional multiplica por 32 o número esperado de chaves. Um prefixo curto é gerado rapidamente num laptop. Um prefixo longo não termina em nenhum equipamento que possua. Um prefixo personalizado também habitua os leitores a reconhecer os primeiros caracteres, em vez do endereço completo. É esse o comportamento explorado pelas cópias de sites onion usadas em ataques de phishing.
Modos de falha e as mensagens apresentadas
Não existe nenhum ficheiro hostname depois do reinício. O Tor não arrancou ou recusou o diretório. O sudo journalctl -u tor@default -n 50 identifica-o:
/var/lib/tor/onion_site/ is not owned by this user (debian-tor, 108) but by root (0). Perhaps you are running Tor as the wrong user?Este é o aspeto de um diretório criado manualmente. Corrija o proprietário e as permissões, ou elimine o diretório e deixe o tor criá-lo.
O Tor Browser apresenta Onionsite Not Found (0xF0). O cliente não conseguiu obter um descritor. Por isso, do ponto de vista da rede, nada está publicado nesse endereço. Confirme se o tor está em execução e concluído o bootstrap. Compare, carácter a carácter, o endereço introduzido com sudo cat /var/lib/tor/onion_site/hostname e verifique depois o relógio. O Tor precisa de uma hora correta para publicar e validar descritores, e timedatectl deve indicar System clock synchronized: yes.
O endereço é resolvido, mas a página nunca carrega. O Tor concluiu o rendezvous e falhou no último salto, entre o tor e o nginx. Esse salto é local, por isso o log do tor permanece silencioso. Execute curl -sI http://127.0.0.1:8080/ no servidor. Connection refused significa que o nginx está parado ou está a escutar num endereço diferente daquele para o qual HiddenServicePort aponta.
A página carrega, mas todas as ligações apontam para o seu domínio real. Existem URLs absolutos nos modelos. Execute a verificação grep -o 'https\?://[^"]*' acima e corrija o que ela apresentar antes de partilhar o endereço.
Funciona, mas deixa de funcionar depois de um reinício. Reinicie o servidor uma vez de propósito antes de depender do site. Em seguida, execute sudo systemctl status tor@default e sudo systemctl status nginx. Um serviço iniciado manualmente parece igual a um serviço ativado até a máquina ser reiniciada.
FAQ
Preciso de abrir uma porta na firewall para um serviço onion do Tor?
Não. O daemon tor estabelece apenas ligações de saída, para os servidores de diretório, para os pontos de introdução e para cada relay de rendezvous. Por isso, não é necessária nenhuma regra de entrada, e o próprio servidor Web escuta em 127.0.0.1. Mantenha o ufw com a política padrão de negar o tráfego de entrada, permitindo SSH. A mesma propriedade permite que um serviço onion funcione numa máquina atrás de NAT (network address translation), mesmo sem qualquer IP público.
Por que não consigo aceder ao meu endereço .onion no Tor Browser?
Comece pelo servidor e avance para fora. sudo journalctl -u tor@default -n 50 deve mostrar Bootstrapped 100% (done): Done. Em seguida, curl -sI http://127.0.0.1:8080/ no servidor deve devolver uma linha de estado. Depois, compare o endereço introduzido com o ficheiro hostname, porque um único carácter incorreto corresponde simplesmente a um serviço diferente. Onionsite Not Found (0xF0) significa que não foi encontrado nenhum descritor para o endereço. Normalmente, isso indica que o tor não está em execução ou que o relógio do sistema está incorreto.
Posso mover o meu site onion para um servidor novo e manter o mesmo endereço?
Sim. O endereço é derivado de hs_ed25519_secret_key. Por isso, copie todo o conteúdo de HiddenServiceDir para o novo servidor, defina o proprietário como debian-tor e o modo como 700, e inicie o tor. O endereço volta a funcionar quando o descritor for publicado novamente. Não existe nenhum registo DNS para atualizar. Se perder esse ficheiro, o endereço não pode ser recuperado. Faça uma cópia de segurança encriptada e fora do servidor no próprio dia em que o criar.
Um site onion precisa de um certificado HTTPS?
Não. O endereço com 56 caracteres é a chave pública do serviço. Por isso, a ligação já é encriptada e autenticada de ponta a ponta, e o Tor Browser trata http:// num nome .onion como um contexto seguro. Reutilizar o seu certificado clearnet no vhost onion é pior do que não fazer nada, porque os logs de Certificate Transparency são públicos e registam permanentemente quais os nomes que partilham um certificado. A única razão para comprar um certificado para um nome .onion é obter garantia de marca através de uma CA que os emita. Essa ligação é pública por conceção.