Hoe host u een .onion site op uw eigen VPS
Leer hoe u een v3 onion service op Ubuntu configureert met Tor en Nginx. Voorkom dat uw publieke IP-adres lekt door de juiste loopback instellingen en beveiligingsstappen.
Wat u bouwt
Een onion-site is een normale webserver die alleen antwoordt via het Tor-netwerk. Installeer tor, voeg twee regels toe aan /etc/tor/torrc, lees het adres dat tor voor u genereert en bind nginx vervolgens aan 127.0.0.1, zodat er niets reageert op het publieke IP-adres. De installatie duurt tien minuten. De rest van deze handleiding is de lijst met lekken, omdat een onion-site meestal faalt doordat de eigen configuratie direct terugwijst naar de beheerder.
Tor begon als "the onion router" en een onion-service is een dienst die u alleen via dat netwerk kunt bereiken. Een versie 3-adres bestaat uit 56 tekens gevolgd door .onion; deze tekens vormen de ed25519 publieke sleutel van de service, plus een checksum en een versie-byte, gecodeerd in base32. Versie 2-adressen (16 tekens) zijn in 2021 uit het netwerk verwijderd, dus alles wat u vandaag genereert is v3. Het adres is de sleutel, wat twee gevolgen heeft. De verbinding is end-to-end versleuteld en geauthenticeerd zonder tussenkomst van een certificaatautoriteit, en het verlies van het sleutelbestand betekent dat het adres definitief verloren is.
Uw server accepteert nooit een inkomende verbinding. Tor kiest enkele relays als introductiepunten, uploadt een ondertekende descriptor naar de directory-servers en ontmoet elke bezoeker bij een rendezvous-relay die de bezoeker heeft gekozen. Elk van deze verbindingen is uitgaand vanaf uw server. Er is geen poort om te openen en geen DNS-record om te publiceren.
Tor installeren vanuit de repository van het Tor Project
Ubuntu levert een tor-pakket in universe, maar dit blijft steken op de versie die actueel was toen de release werd bevroren. De eigen repository van het Tor Project volgt de huidige stabiele release; dit is wat u wilt voor de software die bepaalt of uw adres van u blijft.
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/nullDe repository-vermelding gebruikt het deb822-formaat en Suites moet uw Ubuntu-codename zijn. Lees deze uit /etc/os-release in plaats van de naam te typen, omdat een onjuiste codename resulteert in een repository die weliswaar correct wordt opgelost, maar geen pakketten voor uw release bevat.
. /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-keyringHet deb.torproject.org-keyring-pakket houdt de ondertekeningssleutel actueel, zodat een sleutelrotatie apt update over een jaar niet voor problemen zorgt. Controleer of tor is gestart en verbinding heeft gemaakt met het netwerk:
tor --version
sudo journalctl -u tor@default -n 20De journal zou moeten eindigen met Bootstrapped 100% (done): Done. Een tor die blijft steken op Bootstrapped 10% heeft geen uitgaand pad; controleer daarom de netwerkfirewall van uw provider en uw eigen uitgaande regels: sudo ufw status verbose zou allow (outgoing) als standaard moeten tonen.
Vanaf dit punt zijn twee namen van belang. Het pakket voert tor uit als de debian-tor-gebruiker en de actieve unit is tor@default.service, aangezien tor.service op Debian en Ubuntu een wrapper is rondom de instantie. Vraag de status en logs op via de naam van de instantie om altijd het werkelijke proces te zien.
Configureer de onion service in torrc
Voeg twee regels toe aan /etc/tor/torrc:
HiddenServiceDir /var/lib/tor/onion_site/
HiddenServicePort 80 127.0.0.1:8080HiddenServiceDir is de locatie waar Tor de sleutels en het adres voor deze service bewaart. Maak deze map niet zelf aan. Tor maakt deze bij het opstarten aan met de juiste eigenaar en rechten; een map die u als root aanmaakt, leidt tot de eerste foutmelding in de onderstaande lijst met fouten.
HiddenServicePort bestaat uit twee delen, en het verwisselen hiervan is de meest gemaakte fout. Het eerste getal is de poort waarmee een bezoeker verbinding maakt binnen de tunnel, dus 80 is wat gebruikers verwachten en er is geen reden om dit te wijzigen. Het tweede deel is het lokale adres waarnaar Tor het verkeer doorstuurt. Een kale HiddenServicePort 80 stuurt door naar 127.0.0.1:80, dus het volledig uitschrijven van het adres en het gebruik van een hoog poortnummer houdt de onion vhost gescheiden van services die al op poort 80 luisteren.
sudo systemctl restart tor@default
sudo ls -l /var/lib/tor/onion_site/De lijst moet hostname, hs_ed25519_public_key, hs_ed25519_secret_key en een lege authorized_clients map bevatten.
Uw .onion-adres uitlezen
sudo cat /var/lib/tor/onion_site/hostnameEr verschijnt één regel: 56 base32-tekens en .onion. Deze reeks vormt de volledige identiteit van de site. Niemand wijst deze toe, niemand kan deze overdragen en niemand kan deze afnemen zolang u het sleutelbestand in bezit heeft. Kopieer deze reeks nu, aangezien elke onderstaande configuratie deze vereist. De rest van deze handleiding gebruikt hiervoor de aanduiding <your-address>.onion.
De site serveren via nginx gebonden aan 127.0.0.1
sudo apt install -y nginx
sudo install -d -m 755 /srv/onionSchrijf /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 nginxControleer nu twee zaken vanaf de server. Ten eerste dat nginx reageert op de onion-naam, wat de exacte Host header is die tor zal versturen:
curl -s -H 'Host: <your-address>.onion' http://127.0.0.1:8080/Ten tweede dat de server alleen daar reageert en nergens anders:
sudo ss -tlnp | grep 8080De kolom met het adres moet 127.0.0.1:8080 weergeven. Als hier 0.0.0.0:8080 of *:8080 staat, is uw onion-site ook bereikbaar via het openbare internet; dit is het eerste punt op de lijst met datalekken. Een listen 8080; regel zonder adres bindt aan elke interface, wat de standaardinstelling is.
Open het adres in de Tor Browser. De eerste keer laden duurt enkele seconden terwijl de client uw descriptor ophaalt en een rendezvous-circuit opbouwt.
De documentatie van het Tor Project geeft de voorkeur aan een unix socket boven een loopback-poort: HiddenServicePort 80 unix:/var/run/tor/onion_site.sock, waarbij nginx luistert op dat pad. Een socket is vanaf een andere host helemaal niet bereikbaar, zelfs niet als de server later een tweede interface krijgt. De uitdaging hierbij zijn de bestandsrechten, aangezien nginx de socket aanmaakt en tor er verbinding mee maakt als debian-tor; de twee gebruikers moeten dus toegang hebben tot dezelfde map. Loopback met een geverifieerde ss output is eenvoudiger correct te configureren en is wat de rest van deze handleiding aanneemt.
Met de site op loopback heeft de server geen inkomende firewallregels nodig voor deze verbinding. Houd poort 22 open voor uzelf en blokkeer de rest (de ufw-standaardinstellingen die de moeite waard zijn op een VPS). Onthoud dat een firewall een service die bindt aan 0.0.0.0 niet ongedaan maakt; deze filtert alleen pakketten die de firewall bereiken. Containers maken dit risico groter, omdat het publiceren van een Docker-poort iptables-regels schrijft die voorrang hebben op ufw, waardoor -p 8080:80 uw onion-backend op het openbare IP-adres plaatst terwijl ufw de poort nog steeds als geblokkeerd rapporteert. Publiceer containerpoorten als -p 127.0.0.1:8080:80.
Lekken die een onion-site de-anonimiseren
Tor verbergt waar de server zich bevindt. Niets in Tor verbergt wat de server zegt. Elk punt hieronder is informatie die uw eigen stack publiceert.
Dezelfde site reageert op uw publieke IP
Dit is de fout waar mensen vaak de mist in gaan. Scanners indexeren continu de HTTP-respons van elk routeerbaar adres; deze resultaten zijn openbaar en doorzoekbaar. Serveer dezelfde pagina op uw publieke IP en op uw onion-adres, en het koppelen ervan is slechts één zoekopdracht: dezelfde titel, dezelfde favicon-hash, dezelfde ETag, dezelfde volgorde van headers. De listen 127.0.0.1:8080;-regel hierboven is de oplossing. Controleer dit vanaf een andere machine, niet vanaf de server zelf:
curl -sv --max-time 5 http://<your-public-ip>:8080/Connection refused of een timeout is het juiste resultaat. Elke vorm van HTML betekent dat de site openbaar is. Als de server ook een clearnet-site draait, geef die vhost dan een eigen root en behoud een expliciet default_server-blok op de publieke listener, zodat een niet-overeenkomende Host-header nooit kan doorvallen naar de onion-vhost.
Versiebanners
curl -sI http://127.0.0.1:8080/ | grep -i '^server'Een standaard nginx antwoordt met Server: nginx/1.24.0. Die versiestring, samen met de exacte volgorde van de andere headers, is een vingerafdruk die uw onion-site koppelt aan uw clearnet-host. server_tokens off; reduceert dit tot Server: nginx. Het verwijdert de header niet, en nginx heeft geen ingebouwde richtlijn die dit doet, dus de headers-more-module is de gebruikelijke oplossing als u deze wilt verwijderen. PHP voegt X-Powered-By toe totdat u expose_php = Off instelt. etag off; hoort in hetzelfde rijtje thuis, omdat nginx de ETag opbouwt op basis van de wijzigingstijd en grootte van een bestand; dezelfde bestanden gekopieerd naar twee servers geven dus op beide dezelfde ETag af.
Absolute URL's die naar uw clearnet-domein wijzen
Een rel="canonical"-tag, een Open Graph og:url, een RSS-feed, een sitemap, een e-mail voor wachtwoordherstel, een hardcoded logo-URL. Elk van deze benoemt de clearnet-site binnen een pagina die via de onion wordt geserveerd. Gebruik root-relatieve paden zoals /static/logo.svg en laat de applicatie zijn basis-URL lezen vanaf de request-host in plaats van een constante. Redirects zijn hetzelfde probleem op een andere plek: return 301 https://example.com$request_uri; in een catch-all-blok stuurt de onion-bezoeker naar uw echte domein, en de Location-header geeft hen direct het antwoord.
Een TLS-certificaat gedeeld met de clearnet-site
Een onion-adres authenticeert zichzelf, omdat het adres de publieke sleutel is. Daarom is http:// over een onion-verbinding al end-to-end versleuteld en behandelt Tor Browser dit als een veilige context. Het installeren van uw bestaande certificaat op de onion-vhost publiceert de link tussen beide, omdat elk publiek vertrouwd certificaat wordt vastgelegd in Certificate Transparency-logs. Deze logs zijn openbaar, permanent en doorzoekbaar op naam. Houd Let's Encrypt-certificaten op de clearnet-vhost en laat de onion-vhost op plain HTTP staan.
Lettertypes en analytics van derden
Een lettertype van een CDN (content delivery network) of een analytics-script. De browser van de bezoeker haalt elk item direct op, waardoor de derde partij leert dat iemand uw pagina heeft geladen en meestal ook welke pagina. De strengere beveiligingsniveaus van Tor Browser blokkeren het verzoek sowieso, wat resulteert in een kapotte lay-out. Host elk asset dat de pagina nodig heeft zelf.
Host-header mismatch
Als server_name niet overeenkomt met de Host-header die tor verstuurt, valt nginx terug op de standaardserver voor dat luisteradres. Op een server met één vhost is dit onzichtbaar, omdat het enige serverblok ook de standaard is. Voeg later een clearnet-vhost toe en onion-verzoeken kunnen daarop terechtkomen, inclusief de canonical-tags en redirects. Voer de curl -H 'Host: ...'-controle opnieuw uit na elke wijziging in nginx en gebruik grep op het resultaat voor uw echte domein:
curl -s -H 'Host: <your-address>.onion' http://127.0.0.1:8080/ | grep -o 'https\?://[^"]*' | sort -uWeten welk proces bij welke socket hoort, is het grootste deel van dit werk (hoe poorten en listening sockets werken op Linux).
Wat er in de logs achterblijft
Elk verzoek komt binnen vanaf 127.0.0.1, dus nginx heeft geen bezoekersadres om te registreren en access_log off; kost u niets. De applicatie daarboven is een ander verhaal, aangezien een bestelling, een e-mailadres of de metadata van een geüpload bestand zaken zijn die u zelf moet afhandelen. Uw eigen gewoonten tellen ook mee: het beheren van de server via een niet-geharde login valt buiten alles wat Tor beschermt. Behandel SSH-hardening op dezelfde VPS daarom als onderdeel van deze build.
Maak een back-up van de private key, want dit is het adres
/var/lib/tor/onion_site/hs_ed25519_secret_key is de service. Er is geen registrar en geen herstelprocedure. Raakt u deze kwijt, dan is het adres verloren. Kopieert u deze, dan kan iedereen die de kopie bezit eigen content op uw adres serveren, zonder dat u de mogelijkheid heeft om dit in te trekken.
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@defaultVersleutel dat archief (gpg -c onion-keys.tgz) en verplaats het van de server af. Herstellen op een nieuwe VPS vereist het archief en het eigenaarschap dat tor verwacht:
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/hostnameHet adres keert terug op de nieuwe hardware, een minuut of twee nadat tor de descriptor opnieuw heeft gepubliceerd. Dat is de gehele migratie: geen DNS-wijziging en geen heruitgifte van certificaten.
Onion-Location, wanneer de site ook op het clearnet beschikbaar is
Als de onion-site bedoeld is voor het gemak en niet als geheim, adverteer deze dan vanuit de clearnet vhost:
add_header Onion-Location http://<your-address>.onion$request_uri;Tor Browser toont vervolgens een .onion available-knop in de adresbalk en biedt de overstap aan. De header wordt alleen geaccepteerd wanneer de clearnet-pagina via HTTPS wordt geserveerd en de waarde een geldige onion-URL is.
Eén nginx-regel is hier van belang. add_header-richtlijnen worden alleen overgeërfd door een location-blok wanneer dat blok zelf geen eigen richtlijnen bevat. Een location met een eigen add_header verwijdert daarom stilletjes de Onion-Location. Herhaal de header daar, of bewaar alle response headers op één centrale plek. Het publiceren van deze header koppelt de twee sites bewust aan elkaar; dit is correct voor een mirror, maar onjuist voor alles wat bewust losgekoppeld moet blijven.
Vanity-adressen
mkp224o genereert sleutelparen totdat er een adres wordt geproduceerd dat begint met het door u gevraagde voorvoegsel. Dit is een brute-force-zoekopdracht, dus er valt niets te configureren behalve het voorvoegsel en de tijd die u bereid bent te wachten.
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 blogElke treffer komt terecht in onionkeys/<address>.onion/, dat hostname en hs_ed25519_secret_key bevat. Installeer er een door tor te stoppen, die map naar uw HiddenServiceDir te kopiëren en vervolgens dezelfde chown en chmod 700 toe te passen als bij het herstel hierboven.
De lengte van het voorvoegsel bepaalt de volledige kosten. Het adres is base32, dus elk extra teken dat u vereist, vermenigvuldigt het verwachte aantal sleutels met 32. Een kort voorvoegsel is snel klaar op een laptop. Een lang voorvoegsel is op geen enkel apparaat dat u bezit te voltooien. Een vanity-voorvoegsel leert lezers bovendien om alleen de eerste paar tekens te herkennen in plaats van het volledige adres, en dat is de gewoonte waarop phishing-kopieën van onion-sites zijn gebouwd.
Foutmodi en de bijbehorende meldingen
Geen hostname-bestand na de herstart. Tor is niet gestart of heeft de directory geweigerd. sudo journalctl -u tor@default -n 50 benoemt het:
/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?Zo ziet een handmatig aangemaakte directory eruit. Herstel de eigenaar en de rechten, of verwijder de directory en laat Tor deze zelf aanmaken.
Tor Browser toont Onionsite Not Found (0xF0). De client kon geen descriptor ophalen; voor het netwerk bestaat er dus niets op dat adres. Controleer of Tor draait en is opgestart, vergelijk het adres dat u heeft ingevoerd teken voor teken met sudo cat /var/lib/tor/onion_site/hostname, en controleer vervolgens de klok. Tor heeft een nauwkeurige tijd nodig om descriptors te publiceren en te valideren, en timedatectl zou System clock synchronized: yes moeten rapporteren.
Het adres wordt omgezet, maar de pagina laadt niet. Tor heeft de rendezvous voltooid, maar faalde bij de laatste hop, van Tor naar Nginx. Omdat deze hop lokaal is, blijft het Tor-logboek stil. Voer curl -sI http://127.0.0.1:8080/ uit op de server. Connection refused betekent dat Nginx niet draait of luistert op een ander adres dan waar HiddenServicePort naar verwijst.
De pagina laadt en elke link verwijst naar uw echte domein. Dit komt door absolute URL's in de templates. Voer de grep -o 'https\?://[^"]*'-controle hierboven uit en corrigeer wat er wordt weergegeven voordat u het adres deelt.
Het werkt, maar stopt na een herstart. Herstart de machine één keer bewust voordat u op de site vertrouwt, en voer daarna sudo systemctl status tor@default en sudo systemctl status nginx uit. Een service die handmatig is gestart, ziet er hetzelfde uit als een ingeschakelde service totdat de machine opnieuw opstart.
FAQ
Moet ik een poort openen in mijn firewall voor een Tor onion service?
Nee. De tor daemon maakt alleen uitgaande verbindingen naar de directory servers, naar zijn introductiepunten en naar elke rendezvous relay. Er is dus geen inkomende regel nodig en de webserver zelf luistert op 127.0.0.1. Houd ufw op de standaardinstelling 'deny' voor inkomend verkeer, met SSH toegestaan. Deze eigenschap betekent ook dat een onion service werkt vanaf een machine achter NAT (network address translation) zonder publiek IP-adres.
Waarom kan ik mijn .onion-adres niet bereiken in Tor Browser?
Werk van buiten naar binnen vanaf de server. sudo journalctl -u tor@default -n 50 zou Bootstrapped 100% (done): Done moeten tonen, daarna zou curl -sI http://127.0.0.1:8080/ op de server een statusregel moeten retourneren. Vergelijk vervolgens het adres dat u heeft ingevoerd met het bestand hostname, aangezien één verkeerd teken simpelweg een andere service betekent. Onionsite Not Found (0xF0) betekent dat er geen descriptor is gevonden voor het adres; dit betekent meestal dat tor niet draait of dat de systeemklok onjuist is.
Kan ik mijn onion-site verplaatsen naar een nieuwe server en hetzelfde adres behouden?
Ja. Het adres is afgeleid van hs_ed25519_secret_key, dus kopieer de volledige map HiddenServiceDir naar de nieuwe machine, stel het eigenaarschap in op debian-tor met modus 700 en start tor. Het adres is weer actief zodra de descriptor opnieuw is gepubliceerd; er is geen DNS-record dat bijgewerkt moet worden. Verliest u dat bestand, dan is het adres onherstelbaar. Maak er daarom op de dag van aanmaak een versleutelde back-up van, buiten de server.
Heeft een onion-site een HTTPS-certificaat nodig?
Nee. Het adres van 56 tekens is de publieke sleutel van de service, waardoor de verbinding al end-to-end versleuteld en geverifieerd is. Tor Browser behandelt http:// op een .onion-naam als een veilige context. Het hergebruiken van uw clearnet-certificaat op de onion vhost is slechter dan niets doen, omdat Certificate Transparency-logs openbaar zijn en permanent vastleggen welke namen een certificaat delen. De enige reden om een certificaat voor een .onion-naam te kopen is merkgarantie van een CA die deze uitgeeft, en die koppeling is per ontwerp openbaar.