SSD Nodes Learn 🎉 VPS desde $5.50/mes
Guías Matt ConnorPor Matt Connor · Actualizado 2026-08-12

Cómo alojar un sitio .onion en un VPS con Tor y Nginx

Guía para configurar un servicio onion v3 en Ubuntu. Aprende a vincular Nginx a localhost y a prevenir fugas de IP que vinculen tu servidor con tu identidad real en la red.

Lo que está construyendo

Un sitio onion es un servidor web normal que solo responde a través de la red Tor. Instale tor, añada dos líneas a /etc/tor/torrc, lea la dirección que tor genera para usted y luego vincule nginx a 127.0.0.1 para que nada responda en la IP pública. La parte de la instalación lleva diez minutos. El resto de esta guía es la lista de fugas, ya que la forma habitual en que un sitio onion falla es que su propia configuración apunta directamente al operador.

Tor comenzó como "the onion router" (el enrutador cebolla), y un servicio onion es un servicio al que solo se puede acceder a través de él. Una dirección de versión 3 tiene 56 caracteres seguidos de .onion, y esos caracteres son la clave pública ed25519 del servicio más una suma de comprobación y un byte de versión, codificados en base32. Las direcciones de versión 2 (16 caracteres) fueron eliminadas de la red en 2021, por lo que todo lo que genere hoy es v3. La dirección es la clave, lo que tiene dos consecuencias. La conexión está cifrada y autenticada de extremo a extremo sin intervención de ninguna autoridad de certificación, y perder el archivo de clave significa perder la dirección para siempre.

Su servidor nunca acepta una conexión entrante. Tor elige algunos nodos como puntos de introducción, sube un descriptor firmado a los servidores de directorio y se encuentra con cada visitante en un nodo de encuentro elegido por el visitante. Cada una de esas conexiones es saliente desde su máquina. No hay ningún puerto que abrir ni ningún registro DNS que publicar.

Instalar Tor desde el repositorio del Tor Project

Ubuntu incluye un paquete tor en el repositorio universe, pero se mantiene cerca de la versión que estaba vigente cuando se congeló la distribución. El repositorio propio del Tor Project sigue la versión estable actual, que es lo que usted necesita para el software que decide si su dirección sigue siendo suya.

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/null

La entrada del repositorio utiliza el formato deb822, y Suites debe ser su nombre en clave de Ubuntu. Léalo desde /etc/os-release en lugar de escribirlo, ya que un nombre en clave incorrecto le dará un repositorio que resuelve correctamente pero que no contiene paquetes para su versión.

. /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-keyring

El paquete deb.torproject.org-keyring mantiene actualizada la clave de firma, de modo que una rotación de claves no interrumpa apt update dentro de un año. Compruebe que tor se inició y alcanzó la red:

tor --version
sudo journalctl -u tor@default -n 20

El registro (journal) debería terminar con Bootstrapped 100% (done): Done. Un tor atascado en Bootstrapped 10% no tiene ruta de salida, así que verifique el firewall de red de su proveedor y sus propias reglas de salida: sudo ufw status verbose debería mostrar allow (outgoing) como valor predeterminado.

A partir de aquí, dos nombres son importantes. El paquete ejecuta tor como el usuario debian-tor, y la unidad en ejecución es tor@default.service, ya que tor.service en Debian y Ubuntu es un envoltorio (wrapper) alrededor de la instancia. Solicite el estado y los registros mediante el nombre de la instancia y siempre obtendrá el proceso real.

Configurar el servicio onion en torrc

Añada dos líneas al archivo /etc/tor/torrc:

HiddenServiceDir /var/lib/tor/onion_site/
HiddenServicePort 80 127.0.0.1:8080

HiddenServiceDir es la ubicación donde tor almacena las claves y la dirección de este servicio. No lo cree manualmente. Tor lo crea al iniciarse con el propietario y los permisos necesarios; si crea el directorio como root, se producirá el primer error de la lista que aparece a continuación.

HiddenServicePort consta de dos partes, y confundirlas es el error más frecuente. El primer número es el puerto al que se conecta el visitante dentro del túnel, por lo que 80 es lo que los usuarios esperan y no hay motivo para cambiarlo. La segunda parte es la dirección local a la que tor redirige ese tráfico. Una entrada HiddenServicePort 80 simple redirige a 127.0.0.1:80, por lo que especificar la dirección y utilizar un puerto alto mantiene el vhost onion separado de cualquier servicio que ya esté escuchando en el puerto 80.

sudo systemctl restart tor@default
sudo ls -l /var/lib/tor/onion_site/

El listado debe contener hostname, hs_ed25519_public_key, hs_ed25519_secret_key y un directorio authorized_clients vacío.

Leer su dirección .onion

sudo cat /var/lib/tor/onion_site/hostname

Se devuelve una línea: 56 caracteres en base32 y .onion. Esa cadena es la identidad completa del sitio. Nadie la asigna, nadie puede transferirla y nadie puede quitarla mientras usted posea el archivo de clave. Cópiela ahora, ya que toda la configuración siguiente la requiere. El resto de esta guía la escribe como <your-address>.onion.

Servir el sitio desde nginx vinculado a 127.0.0.1

sudo apt install -y nginx
sudo install -d -m 755 /srv/onion

Escriba /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 nginx

Ahora verifique dos cosas desde el servidor. La primera es que nginx responde al nombre onion, que es exactamente la cabecera Host que tor enviará:

curl -s -H 'Host: <your-address>.onion' http://127.0.0.1:8080/

La segunda es que responde ahí y en ningún otro lugar:

sudo ss -tlnp | grep 8080

La columna de dirección debe mostrar 127.0.0.1:8080. Si muestra 0.0.0.0:8080 o *:8080, su sitio onion también está en la internet pública, lo cual es el primer punto en la lista de fugas. Una línea listen 8080; sin dirección se vincula a todas las interfaces, y ese es el valor predeterminado.

Abra la dirección en Tor Browser. La primera carga toma unos segundos mientras el cliente obtiene su descriptor y construye un circuito de encuentro.

La documentación propia de The Tor Project prefiere un socket unix en lugar de un puerto de loopback: HiddenServicePort 80 unix:/var/run/tor/onion_site.sock, con nginx escuchando en esa ruta. Un socket no puede ser alcanzado desde otro host en absoluto, incluso si el equipo añade una segunda interfaz más adelante. El costo son los permisos de archivo, ya que nginx crea el socket y tor se conecta a él como debian-tor, por lo que ambos usuarios deben coincidir en el directorio. El loopback con una salida ss verificada es más fácil de configurar correctamente, y es lo que el resto de esta guía asume.

Con el sitio en loopback, el equipo no necesita ninguna regla de entrada para él. Mantenga el puerto 22 abierto para usted y deniegue el resto (los valores predeterminados de ufw que vale la pena configurar en un VPS). Recuerde que un firewall no deshace un servicio que se vincula a 0.0.0.0, solo filtra los paquetes que llegan al firewall. Los contenedores hacen esto más crítico, porque publicar un puerto de Docker escribe reglas de iptables antes que ufw, por lo que -p 8080:80 expone su backend onion en la IP pública mientras ufw sigue reportando el puerto como denegado. Publique los puertos de los contenedores como -p 127.0.0.1:8080:80.

Las fugas que desanonimizan un sitio onion

Tor oculta la ubicación del servidor. Nada en Tor oculta lo que el servidor comunica. Cada elemento a continuación es algo que su propia pila de software publica.

El mismo sitio respondiendo en su IP pública

Este es el error que atrapa a la mayoría. Los escáneres indexan la respuesta HTTP de cada dirección enrutable de forma continua; esos resultados son públicos y consultables. Si sirve la misma página en su IP pública y en su dirección onion, unirlas es una sola consulta: mismo título, mismo hash de favicon, mismo ETag, mismo orden de cabeceras. La línea listen 127.0.0.1:8080; anterior es la solución. Verifíquelo desde una máquina distinta, no desde el servidor:

curl -sv --max-time 5 http://<your-public-ip>:8080/

Connection refused o un tiempo de espera (timeout) es el resultado correcto. Cualquier HTML significa que el sitio es público. Si el equipo también ejecuta un sitio en la red abierta (clearnet), asigne a ese vhost su propia raíz y mantenga un bloque default_server explícito en el listener público, de modo que una cabecera Host sin coincidencia nunca pueda derivar al vhost onion.

Banners de versión

curl -sI http://127.0.0.1:8080/ | grep -i '^server'

Un nginx por defecto responde Server: nginx/1.24.0. Esa cadena de versión, junto con el orden exacto de las otras cabeceras, es una huella digital que vincula su onion con su host de red abierta. server_tokens off; la reduce a Server: nginx. No elimina la cabecera, y nginx no tiene una directiva integrada para hacerlo, por lo que el módulo headers-more es la respuesta habitual si desea eliminarla. PHP añade X-Powered-By hasta que usted configura expose_php = Off. etag off; pertenece a la misma lista, ya que nginx construye el ETag a partir de la fecha de modificación y el tamaño de un archivo, por lo que los mismos archivos copiados en dos servidores entregan el mismo ETag en ambos.

URLs absolutas que apuntan a su dominio de red abierta

Una etiqueta rel="canonical", un Open Graph og:url, un feed RSS, un sitemap, un correo electrónico de restablecimiento de contraseña, una URL de logotipo codificada de forma rígida. Cualquiera de ellos nombra el sitio de red abierta dentro de una página servida a través de la red onion. Utilice rutas relativas a la raíz como /static/logo.svg y permita que la aplicación lea su URL base desde el host de la petición en lugar de una constante. Las redirecciones son el mismo error en otro lugar: return 301 https://example.com$request_uri; en un bloque catch-all envía al visitante onion a su dominio real, y la cabecera Location les entrega la respuesta directamente.

Un certificado TLS compartido con el sitio de red abierta

Una dirección onion se autentica a sí misma, ya que la dirección es la clave pública, por lo que http:// sobre una conexión onion ya está cifrado de extremo a extremo y Tor Browser lo trata como un contexto seguro. Instalar su certificado existente en el vhost onion publica el vínculo entre ambos, porque cada certificado de confianza pública se registra en los logs de Certificate Transparency, y esos logs son públicos, permanentes y consultables por nombre. Mantenga certificados de Let's Encrypt en el vhost de red abierta y deje el vhost onion en HTTP plano.

Fuentes y analíticas de terceros

Una fuente desde una CDN (red de distribución de contenidos) o un script de analíticas. El navegador del visitante obtiene cada uno directamente, por lo que el tercero sabe que alguien cargó su página y, por lo general, qué página; además, los niveles de seguridad más estrictos de Tor Browser bloquean la petición de todos modos, dejando un diseño roto. Aloje usted mismo cada recurso que la página necesite.

Desajuste en la cabecera Host

Si server_name no coincide con la cabecera Host que envía tor, nginx recurre al servidor por defecto para esa dirección de escucha. En un equipo con un solo vhost esto es invisible, porque el único bloque de servidor es también el predeterminado. Si añade un vhost de red abierta más tarde, las peticiones onion pueden empezar a aterrizar en él, junto con sus etiquetas canónicas y sus redirecciones. Vuelva a ejecutar la comprobación curl -H 'Host: ...' después de cada cambio en nginx, y utilice grep sobre el resultado para buscar su dominio real:

curl -s -H 'Host: <your-address>.onion' http://127.0.0.1:8080/ | grep -o 'https\?://[^"]*' | sort -u

Saber qué proceso posee qué socket es la mayor parte de este trabajo (cómo funcionan los puertos y los sockets de escucha en Linux).

Qué queda en los registros

Cada petición llega desde 127.0.0.1, por lo que nginx no tiene una dirección de visitante que registrar y access_log off; no le cuesta nada. La aplicación que se ejecuta encima es un asunto distinto, ya que un pedido, una dirección de correo electrónico o los metadatos de un archivo subido son responsabilidad suya. Sus propios hábitos también cuentan: administrar el equipo a través de un inicio de sesión no reforzado queda fuera de cualquier protección de Tor, así que trate el endurecimiento de SSH en el mismo VPS como parte de esta configuración.

Realice una copia de seguridad de la clave privada, ya que es la dirección

/var/lib/tor/onion_site/hs_ed25519_secret_key es el servicio. No existe un registrador ni un proceso de recuperación. Si la pierde, la dirección desaparece. Si la copia, quien posea dicha copia podrá servir su propio contenido en su dirección, sin que usted tenga forma de revocar 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@default

Cifre ese archivo (gpg -c onion-keys.tgz) y muévalo fuera del servidor. La restauración en un nuevo VPS consiste en el archivo más la propiedad que 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/hostname

La misma dirección vuelve a estar disponible en el nuevo hardware, uno o dos minutos después de que tor vuelva a publicar el descriptor. Esa es toda la migración: sin cambios en DNS y sin necesidad de volver a emitir certificados.

Onion-Location, cuando el sitio también existe en la clearnet

Si el onion es una comodidad en lugar de un secreto, anúncielo desde el vhost de la clearnet:

add_header Onion-Location http://<your-address>.onion$request_uri;

Tor Browser muestra entonces un botón .onion available en la barra de direcciones y ofrece el cambio. La cabecera solo se respeta cuando la página de la clearnet se sirve mediante HTTPS y el valor es una URL onion válida.

Una regla de nginx es importante aquí. Las directivas add_header se heredan en un bloque location solo cuando ese bloque no declara ninguna propia, por lo que un location con su propio add_header descarta silenciosamente Onion-Location. Repítalo allí o mantenga todas las cabeceras de respuesta en un solo lugar. Publicar esta cabecera vincula deliberadamente ambos sitios, lo cual es correcto para un espejo y erróneo para cualquier cosa que deba permanecer sin enlaces.

Direcciones personalizadas

mkp224o genera pares de claves hasta que uno produce una dirección que comienza con el prefijo solicitado. Es una búsqueda por fuerza bruta, por lo que no hay nada que configurar más allá del prefijo y el tiempo que esté dispuesto 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 blog

Cada coincidencia se guarda en onionkeys/<address>.onion/, que contiene hostname y hs_ed25519_secret_key. Instale una deteniendo tor, copiando ese directorio sobre su HiddenServiceDir y aplicando luego el mismo chown y chmod 700 que en la restauración anterior.

La longitud del prefijo determina el coste total. La dirección está en base32, por lo que cada carácter adicional que solicite multiplica por 32 el número esperado de claves. Un prefijo corto se completa en un portátil. Uno largo no terminará nunca en ningún equipo que usted posea. Un prefijo personalizado también enseña a los usuarios a reconocer solo los primeros caracteres en lugar de la dirección completa, y ese es el hábito sobre el que se construyen las copias de phishing de los sitios onion.

Modos de fallo y cadenas de error asociadas

No existe el archivo hostname tras el reinicio. Tor no se inició o rechazó el directorio. sudo journalctl -u tor@default -n 50 lo indica así:

/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?

Ese es el aspecto de un directorio creado manualmente. Corrija el propietario y los permisos, o elimine el directorio y permita que tor lo genere.

Tor Browser muestra Onionsite Not Found (0xF0). El cliente no pudo obtener un descriptor, por lo que, para la red, no hay nada publicado en esa dirección. Confirme que tor se está ejecutando y ha completado el arranque, compare la dirección que escribió con sudo cat /var/lib/tor/onion_site/hostname carácter por carácter y luego verifique el reloj. Tor necesita una hora precisa para publicar y validar descriptores, y timedatectl debería informar System clock synchronized: yes.

La dirección resuelve pero la página nunca carga. Tor completó el encuentro (rendezvous) y falló en el último salto, de tor a nginx; como ese salto es local, el registro de tor no muestra nada. Ejecute curl -sI http://127.0.0.1:8080/ en el servidor. Connection refused significa que nginx está caído o escuchando en una dirección distinta a la que apunta HiddenServicePort.

La página carga y todos los enlaces dirigen a su dominio real. Hay URLs absolutas en las plantillas. Ejecute la comprobación grep -o 'https\?://[^"]*' anterior y corrija lo que indique antes de compartir la dirección en cualquier lugar.

Funciona, pero deja de hacerlo tras un reinicio. Reinicie el equipo una vez a propósito antes de confiar en el sitio, luego ejecute sudo systemctl status tor@default y sudo systemctl status nginx. Un servicio iniciado manualmente parece idéntico a uno habilitado hasta que la máquina se reinicia.

FAQ

¿Necesito abrir un puerto en mi firewall para un servicio onion de Tor?

No. El daemon tor solo realiza conexiones salientes hacia los servidores de directorio, los puntos de introducción y cada repetidor de encuentro, por lo que no se requiere ninguna regla de entrada y el servidor web en sí escucha en 127.0.0.1. Mantenga ufw con la política predeterminada de denegar el tráfico entrante, permitiendo únicamente SSH. Esta misma propiedad implica que un servicio onion funciona desde una máquina detrás de NAT (traducción de direcciones de red) sin necesidad de una IP pública.

¿Por qué no puedo acceder a mi dirección .onion en Tor Browser?

Trabaje desde el servidor hacia afuera. sudo journalctl -u tor@default -n 50 debería mostrar Bootstrapped 100% (done): Done, luego curl -sI http://127.0.0.1:8080/ en el servidor debería devolver una línea de estado; después, compare la dirección que escribió con el archivo hostname, ya que un solo carácter incorrecto resulta en un servicio distinto. Onionsite Not Found (0xF0) significa que no se encontró ningún descriptor para la dirección, lo que generalmente indica que tor no se está ejecutando o que el reloj del sistema es incorrecto.

¿Puedo mover mi sitio onion a un servidor nuevo y mantener la misma dirección?

Sí. La dirección se deriva de hs_ed25519_secret_key, así que copie todo el directorio HiddenServiceDir a la nueva máquina, asígnele la propiedad debian-tor y permisos 700, e inicie tor. La dirección vuelve a estar activa una vez que el descriptor se republica, y no hay registros DNS que actualizar. Si pierde ese archivo, la dirección es irrecuperable; por lo tanto, realice una copia de seguridad cifrada fuera del servidor el mismo día que lo cree.

¿Necesita un sitio onion un certificado HTTPS?

No. La dirección de 56 caracteres es la clave pública del servicio, por lo que la conexión ya está cifrada y autenticada de extremo a extremo, y Tor Browser trata http:// en un nombre .onion como un contexto seguro. Reutilizar su certificado de la red pública (clearnet) en el vhost onion es peor que no hacer nada, ya que los registros de Transparencia de Certificados (Certificate Transparency logs) son públicos y registran permanentemente qué nombres comparten un certificado. La única razón para comprar un certificado para un nombre .onion es obtener una garantía de marca por parte de una CA que los emita, y ese vínculo es público por diseño.