Configurar Onion-Location en nginx sin filtrar datos
Publica Onion-Location en nginx para que Tor Browser ofrezca tu dirección onion. Revisa redirecciones y recursos externos, dos fugas que pueden revelar tu sitio.
Qué hace la cabecera Onion-Location
La cabecera Onion-Location es una línea del vhost de clearnet que anuncia la dirección onion al Tor Browser. Un visitante que accede a https://example.com mediante Tor ve una pastilla morada en la barra de direcciones con el texto .onion available, y un clic lo lleva a tu servicio onion. Es un mecanismo de descubrimiento y nada más. La cabecera no crea el servicio onion ni oculta nada sobre ti.
Esta guía presupone que ambas partes ya existen. Tienes un sitio en un VPS detrás de nginx y un servicio onion v3 operativo que apunta a él. Si todavía no tienes la segunda parte, créala primero: alojar un sitio onion en un VPS explica las líneas de torrc y el primer archivo hostname. Lo siguiente trata sobre cómo conectar ambos elementos sin filtrar información de uno al otro.
Requisitos de Tor Browser antes de aceptar la cabecera
El proyecto Tor documenta tres condiciones. Las tres deben cumplirse; de lo contrario, la pastilla no aparece.
- El valor de
Onion-Locationdebe ser una URL válida con un esquemahttp:ohttps:y un nombre de host.onion. - La página web que define la cabecera debe servirse mediante HTTPS.
- La página web que define la cabecera no debe ser un sitio onion.
La segunda condición es la que suele causar problemas. La tercera explica por qué nunca se debe configurar esta cabecera en el virtual host onion. Existe una cuarta regla que no aparece en la documentación narrativa, pero sí en la implementación: Tor Browser sólo actúa sobre la cabecera del documento de nivel superior. El código compara el destino de carga con el documento antes de hacer nada. Por tanto, ignora una cabecera devuelta por una hoja de estilos, una imagen o una respuesta de API.
De forma predeterminada, el navegador muestra la pastilla y espera a que el usuario haga clic. Para activar un salto automático, el usuario debe ir a Settings, después a Privacy and Security y luego a Onion Services, donde puede establecer "Prioritize .onion sites when known" en "Always". No se puede forzar esta opción desde el servidor. Considere la cabecera una oferta, no una redirección.
Añadir la cabecera Onion-Location en nginx
La cabecera debe estar en el bloque server que termina TLS para el dominio clearnet. Si la coloca en el bloque del puerto 80, no ocurre nada, porque ese bloque sólo emite una redirección y la segunda condición excluye una cabecera definida en una página HTTP sin cifrar.
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
add_header Onion-Location http://<your-onion-address>.onion$request_uri always;
root /srv/example.com/public;
}$request_uri incluye la ruta y la cadena de consulta, por lo que un lector en https://example.com/guides/tor recibe la misma ruta en el dominio onion. Si la omite, todos los visitantes llegan a la página principal del dominio onion en lugar de a la página que estaban leyendo.
always es importante por una limitación documentada de nginx. add_header añade el campo sólo cuando el código de respuesta es 200, 201, 204, 206, 301, 302, 303, 304, 307 o 308. La página 404 es un punto de entrada real desde los resultados de búsqueda y, sin always, no incluye ninguna cabecera.
La segunda trampa de nginx es la herencia, que falla de forma silenciosa. Las directivas add_header se heredan del nivel de configuración anterior sólo si no hay directivas add_header en el nivel actual. Por tanto, un bloque location /assets/ { add_header Cache-Control ...; } descarta Onion-Location definido en el nivel server para todas las URL que contiene. Si configura cabeceras por ubicación en algún punto, repita la línea Onion-Location dentro de cada uno de esos bloques. Cómo selecciona nginx un bloque server y location merece una lectura si este comportamiento es nuevo para usted.
Recargue la configuración y compruebe una página normal y otra inexistente:
sudo nginx -t && sudo systemctl reload nginx
curl -sI https://example.com/ | grep -i onion-location
curl -sI https://example.com/no-such-page | grep -i onion-locationAmbos comandos deberían mostrar una línea onion-location:. El segundo comando demuestra que always funciona. Si el segundo comando no muestra ninguna salida, falta el indicador o un bloque location está ocultando la directiva.
La etiqueta meta de HTML cuando no puede configurar cabeceras
Los hosts estáticos y algunos paneles de CDN no permiten añadir una cabecera de respuesta arbitraria. El mismo valor funciona como un elemento meta en la cabecera del documento, porque el navegador lo lee a través de los mismos datos de cabecera del documento, tanto si llegó mediante HTTP como si llegó como una etiqueta http-equiv.
<meta http-equiv="onion-location" content="http://<your-onion-address>.onion" />Los tres requisitos siguen siendo aplicables. La página que contiene la etiqueta debe usar HTTPS y no debe ser un onion. La diferencia es que la etiqueta contiene una única dirección fija sin ruta, porque no existe una variable del servidor que expandir. Cada página que la contiene ofrece la página de inicio del onion. Ese es el coste de esta alternativa, por lo que debe preferir la cabecera siempre que controle el servidor.
Sirva el sitio onion desde su propio vhost de nginx
El sitio clearnet y el onion no deben compartir un bloque de servidor. Tor Browser envía Host: <your-onion-address>.onion. Si ningún bloque de servidor reclama ese nombre, nginx recurre al servidor predeterminado, que es su vhost clearnet, y todas las URL que genera ese vhost incluyen el nombre de su dominio.
Apunte el servicio oculto a un puerto al que sólo responda la interfaz de loopback:
HiddenServiceDir /var/lib/tor/onion_site/
HiddenServicePort 80 127.0.0.1:8080Después, asigne a ese puerto su propio vhost:
server {
listen 127.0.0.1:8080;
server_name <your-onion-address>.onion;
absolute_redirect off;
port_in_redirect off;
root /srv/example.com/public;
}listen 127.0.0.1:8080 mantiene este vhost fuera de su IP pública, por lo que alguien que analice la dirección del VPS no puede obtenerlo ni compararlo byte a byte con la copia clearnet. absolute_redirect off hace que nginx emita valores Location relativos, de modo que la redirección de una URL de directorio que termina en barra devuelve Location: /guides/ y no una URL completa. nginx ya genera redirecciones absolutas a partir de la cabecera Host y no de server_name, porque server_name_in_redirect tiene el valor predeterminado off, pero una redirección relativa elimina por completo la cuestión.
¿Por qué la página onion sigue enviando a los visitantes al sitio clearnet?
nginx rara vez es la fuente de la fuga. La aplicación lo es. Cualquier componente que genere una URL absoluta a partir de la dirección del sitio configurada usará el nombre de su dominio, independientemente del vhost que haya atendido la petición.
- Una etiqueta de enlace
rel="canonical"que apunta ahttps://example.com/.... Es el caso más habitual y muestra la página clearnet exacta a cualquiera que consulte el código fuente. - Redirecciones generadas por el framework en lugar de nginx, como
SECURE_SSL_REDIRECTde Django o las opcioneshomeysiteurlde WordPress. og:urly las demás etiquetas meta de tarjetas sociales.- Entradas de Sitemap y RSS, que son absolutas por especificación.
- Páginas de error de la aplicación, que normalmente incluyen un enlace «volver a la página de inicio» generado a partir de la misma configuración.
La solución depende de la pila que use y no existe una solución genérica. La comprobación sí es genérica. Obtenga la página onion a través de Tor y busque su dominio en la respuesta.
curl -s --socks5-hostname 127.0.0.1:9050 http://<your-onion-address>.onion/ \
| grep -i 'example\.com'--socks5-hostname envía el nombre al puerto SOCKS de tor para resolverlo. Esto es necesario porque ningún componente de su máquina puede resolver localmente un nombre .onion. El puerto 9050 es el valor predeterminado de un daemon tor instalado mediante un paquete. Un resultado vacío indica que la comprobación ha pasado. Cualquier coincidencia corresponde a una página que entrega su dominio clearnet a todos los visitantes onion. Ejecute la comprobación contra la página de inicio y después contra una URL que produzca un 404.
Compruebe la cadena de redirecciones por separado, porque el cuerpo de una redirección normalmente está vacío:
curl -sI --socks5-hostname 127.0.0.1:9050 http://<your-onion-address>.onion/guides \
| grep -i '^location'Un valor Location que contiene example.com indica que una redirección está devolviendo al visitante onion a la red clearnet mediante un nodo de salida, en una petición que creía que permanecía dentro de Tor.
No presente el certificado de clearnet en el servicio onion
Una dirección onion v3 se deriva de la clave pública del propio servicio. Por tanto, Tor autentica y cifra el circuito hacia ese servicio concreto antes de enviar cualquier petición HTTP. Usar HTTP sin cifrar dentro de un servicio onion es la configuración normal. No es lo mismo que usar HTTP sin cifrar a través de Internet.
Si crea el vhost onion copiando el de clearnet, también copia ssl_certificate. En ese caso, el servicio onion presenta un certificado cuyos nombres alternativos del sujeto incluyen example.com. Esto provoca dos problemas. El navegador muestra un error de coincidencia de nombres porque la URL es la dirección onion y el certificado no la cubre. Además, cada visitante que continúa recibe una declaración firmada de que ambos sitios pertenecen a la misma máquina. Mantenga el vhost onion en su propio archivo con su propio server_name. Esto también lo mantiene separado de el plugin de Nginx de Certbot, ya que ese plugin modifica el bloque de servidor que coincide con el dominio para el que solicita un certificado.
Qué paquete de tor usar y cómo proteger la clave del servicio
El paquete tor del archivo de Ubuntu funciona para esto y no requiere configuración adicional. Está por detrás de la serie estable actual. Por eso, para un servicio que piense mantener activo, use el repositorio Debian propio de Tor y deje que apt lo actualice junto con el resto del sistema. En agosto de 2026, los pasos documentados son los siguientes:
sudo apt install apt-transport-https
wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc \
| gpg --dearmor \
| sudo tee /usr/share/keyrings/deb.torproject.org-keyring.gpg >/dev/nullEscriba /etc/apt/sources.list.d/tor.sources y sustituya la suite por el nombre en clave de su versión, que puede obtener de lsb_release -c:
Types: deb deb-src
URIs: https://deb.torproject.org/torproject.org/
Suites: noble
Components: main
Signed-By: /usr/share/keyrings/deb.torproject.org-keyring.gpgsudo apt update
sudo apt install tor deb.torproject.org-keyringEl paquete deb.torproject.org-keyring mantiene actualizada la clave de firma, para que el repositorio siga verificándose dentro de un año. Elija una fuente y manténgala. El paquete del archivo y el paquete del repositorio contienen versiones diferentes. Si ambos están habilitados, apt cambiará entre ellos durante las actualizaciones.
El directorio HiddenServiceDir contiene la identidad del servicio. El archivo hs_ed25519_secret_key de ese directorio es su dirección onion, porque la dirección es la mitad pública de ese par de claves. Si pierde el archivo, la dirección desaparece permanentemente, ya que ninguna autoridad puede volver a emitirla. Si copia el archivo en un lugar sin protección, quien tenga la copia podrá ejecutar su servicio onion.
tor no utiliza un directorio que otros usuarios puedan leer. Compruebe el modo y el propietario antes de revisar cualquier otra cosa:
sudo ls -ld /var/lib/tor/onion_site
sudo -u debian-tor cat /var/lib/tor/onion_site/hostnameLa salida debería mostrar drwx------, con el propietario y el grupo debian-tor en Debian y Ubuntu. Si los permisos son más amplios, tor registra una línea como Permissions on directory /var/lib/tor/onion_site/ are too permissive. y el servicio no se inicia. Corríjalo con sudo chown -R debian-tor:debian-tor /var/lib/tor/onion_site seguido de sudo chmod 700 /var/lib/tor/onion_site, reinicie con sudo systemctl restart tor y compruebe el resultado con sudo journalctl -u tor@default -n 30.
Haga una copia de seguridad de ese directorio como la haría de una clave privada: fuera del servidor y cifrada. Nunca lo confirme en el repositorio que contiene su sitio. Si el mismo servidor también necesita acceso administrativo mediante Tor, acceder a SSH mediante un servicio onion separa mejor esa función que exponer una ruta de administración en el sitio público.
Los análisis y los recursos de terceros filtran más información que la cabecera
Esta es la parte más importante y no tiene nada que ver con Onion-Location. Cada recurso de terceros al que hace referencia la página implica una solicitud que el navegador del visitante realiza fuera de la red onion y vuelve a enviar a la clearnet a través de un nodo de salida. Una fuente de un CDN público, un script de análisis alojado por un tercero, un reproductor de vídeo incrustado o un widget de comentarios: cada uno informa a ese tercero de que alguien está cargando la página en una sesión que el lector ha encaminado deliberadamente a través de Tor.
Esto tiene dos consecuencias. El tercero obtiene información sobre la visita. Además, como la copia en la clearnet carga los mismos recursos de los mismos proveedores, cualquiera que pueda observar uno de los dos lados puede asociar ambas propiedades sin esfuerzo.
Sirva todo desde el mismo origen. Aloje las fuentes en su propio servidor. Elimine la etiqueta de análisis alojada por un tercero o muévala a su propio servidor, donde los análisis autohospedados en un VPS mantienen la solicitud dentro de la red onion. Espere que la configuración predeterminada de Tor Browser bloquee o limite gran parte de lo que cualquier herramienta de análisis intenta recopilar. Ese es el resultado correcto. Si una página no puede funcionar sin un script de terceros, no publique esa página en la red onion.
Enumere lo que carga realmente una página:
curl -s --socks5-hostname 127.0.0.1:9050 http://<your-onion-address>.onion/ \
| grep -oE '(src|href)="https?://[^"]+"' | sort -uCada línea que muestra este comando es una URL absoluta que la página solicita al navegador que descargue. Todo lo que no sea su propia dirección onion es una solicitud saliente a la clearnet que está pidiendo a sus lectores que realicen en su nombre.
El modelo de amenazas, explicado claramente
Onion-Location facilita encontrar un servicio onion, y eso es todo lo que hace. No te anonimiza como operador, porque tu dominio clearnet sigue teniendo registros del registrador, registros DNS, un certificado publicado en los registros de Certificate Transparency y una cuenta de VPS asociada a tus datos de facturación. Tampoco anonimiza el servicio onion, porque acabas de publicar desde ese dominio clearnet una declaración pública y permanente de que ambas direcciones corresponden al mismo sitio. El beneficio es para el lector: quien llega mediante Tor puede permanecer dentro de Tor, sin un nodo de salida en la ruta y sin una consulta DNS para tu dominio. Si tu objetivo es un servicio onion al que nadie pueda conectarse para identificarte, no publiques esta cabecera y no ejecutes las dos copias en una sola máquina.
Aquí surgen dos preguntas relacionadas y cada una tiene su propia respuesta. La diferencia entre Tor y una VPN determina qué usas para tu propio tráfico, una decisión independiente de lo que publiques. Además, si los lectores de una red censurada no pueden acceder al sitio clearnet, nunca verán la cabecera. En ese caso, los bridges y los pluggable transports son más importantes que cualquier otra cosa de esta página.
Verifique toda la configuración
Ejecute estos comandos en orden. Cada uno produce un resultado que puede comprobar.
curl -sI https://example.com/ | grep -i onion-locationmuestra la cabecera.- El mismo comando contra una URL que devuelve 404 también la muestra.
curl -s --socks5-hostname 127.0.0.1:9050 http://<your-onion-address>.onion/devuelve su página.- Buscar su dominio clearnet en esa salida no devuelve resultados.
- Tor Browser en
https://example.commuestra la etiqueta.onion available.
Si los pasos 1 a 4 funcionan y el paso 5 no, la causa casi siempre está en el lugar desde el que se sirve la cabecera, no en la cabecera. Confirme que el navegador cargó realmente la página HTTPS y no una redirección almacenada en caché. Después, ejecute curl -sI contra la URL exacta que abrió, porque un bloque location en esa ruta específica puede descartar la directiva definida a nivel del servidor.
FAQ
¿Por qué Tor Browser no muestra la etiqueta «.onion available»?
Compruebe primero los tres requisitos documentados. El valor debe ser una URL completa con un esquema http: o https: y un host .onion. Una dirección sin esquema no es válida y no muestra ningún error. La página debe servirse mediante HTTPS. Por tanto, nunca se lee una cabecera configurada en el bloque de redirección del puerto 80. Además, la propia página no debe ser un servicio onion. Después, revise nginx: cualquier add_header dentro del bloque location coincidente descarta todos los add_header definidos en el nivel del servidor. Sin la opción always, la cabecera no aparece en las respuestas 404 ni 500. Ejecute curl -sI contra la URL exacta que cargó en el navegador y confirme que la cabecera se envía realmente por la red.
¿Necesito un certificado TLS para mi sitio onion?
No. Una dirección onion v3 se deriva de la clave pública del servicio. Por tanto, el circuito se autentica para ese servicio concreto y se cifra de extremo a extremo antes de enviar cualquier petición HTTP. HTTP sin cifrar dentro de un servicio onion es la configuración habitual. Lo que debe evitar es presentar el certificado de su sitio clearnet en el servicio onion. La lista de nombres alternativos del sujeto contiene su dominio. Esto provoca una advertencia de incompatibilidad de nombres en el navegador y confirma a todos los visitantes que ambos sitios se ejecutan en una misma máquina.
¿Publicar Onion-Location hace que mi sitio sea anónimo?
No. La cabecera es una declaración pública de su dominio clearnet que indica que una dirección onion concreta le pertenece, y cualquiera puede consultarla. La ventaja es para el lector, que puede pasar al servicio onion y eliminar de su ruta el nodo de salida y la consulta DNS. Como operador, usted no obtiene anonimato y vincula permanentemente ambas direcciones. Un servicio onion que no deba poder relacionarse con usted debe publicarse en otro lugar, en hardware que no comparta nada con el sitio clearnet.
¿Puedo usar la etiqueta meta en lugar de la cabecera HTTP?
Sí, cuando no pueda establecer cabeceras de respuesta, que es lo habitual en un host estático. Coloque <meta http-equiv="onion-location" content="http://youraddress.onion" /> en la cabecera del documento. Se aplican los mismos tres requisitos. Por tanto, la página debe usar HTTPS y no debe ser un servicio onion. La única diferencia importante es que la etiqueta contiene una dirección fija sin ruta, mientras que la cabecera de nginx puede añadir $request_uri y ofrecer al visitante la misma página en el servicio onion en lugar de la página de inicio.