Reenvío de puertos de Gluetun para clientes torrent
Las descargas funcionan, pero no entran conexiones. Configura el reenvío de puertos de Gluetun, actualiza el puerto del cliente torrent tras cada reconexión y verifícalo.
Por qué no entra ninguna conexión sin un puerto redirigido
El reenvío de puertos de Gluetun solicita al proveedor de VPN que asigne un puerto público de su dirección de salida y lo redirija a tu contenedor. Es la única forma de que otro peer pueda iniciar una conexión con tu cliente torrent. Sin esa asignación, el túnel funciona, las descargas se ejecutan y no llega ninguna conexión por sí sola. Todas las conexiones activas son conexiones que tu cliente inició primero.
El mecanismo es NAT (traducción de direcciones de red). Tu contenedor comparte la dirección de salida del proveedor con muchos otros clientes. Cuando tu cliente abre una conexión hacia el exterior, el proveedor registra ese flujo y envía las respuestas de vuelta por el túnel. La conexión entrante de un peer externo no coincide con ningún flujo registrado, por lo que el paquete llega a la dirección de salida y se descarta allí. Tu cliente sigue conectándose con todos los peers que sí aceptan conexiones, por lo que las descargas terminan y el problema puede pasar inadvertido. Se hace evidente al compartir, porque un seeder es un equipo al que se conectan otros usuarios.
Un puerto entrante abierto cambia dos aspectos. Te incorporas más rápido al swarm, porque los peers que no pueden aceptar conexiones ahora sí pueden llegar hasta ti. Además, puedes cargar datos a esos peers.
Por qué la mayoría de los proveedores de VPN no ofrecen reenvío de puertos
Un puerto reenviado es un recurso limitado en una dirección compartida. El proveedor reserva un número de puerto en una IP de salida para un cliente y, después, responde por todo lo que ese cliente haga con él. Varios proveedores grandes eliminaron esta función y señalaron la gestión de abusos como motivo. Considere la compatibilidad como una cuestión de categoría, no como una casilla de verificación: pregunte si el proveedor ofrece reenvío de puertos actualmente, con su plan y en servidores que realmente pueda seleccionar.
Cuando existe el reenvío, el puerto es dinámico. Pertenece a la sesión de VPN y no a su cuenta, por lo que puede ser un número distinto después de cada reconexión. Private Internet Access emite un puerto firmado que gluetun actualiza, y la documentación original indica que el mismo puerto se conserva durante 60 días siempre que monte /gluetun como bind mount para que el estado sobreviva a un reinicio. ProtonVPN asigna un puerto aleatorio mediante NAT-PMP (protocolo de asignación de puertos NAT) con una concesión breve que debe renovarse continuamente. Por eso, configurar el puerto una sola vez en el cliente nunca funciona de forma permanente.
Proveedores a los que gluetun puede solicitar un puerto
A partir de gluetun v3.41.3, publicado el 30 July 2026, la integración nativa valida cuatro nombres de proveedores: Private Internet Access, ProtonVPN, Perfect Privacy y PrivateVPN. Actívela con VPN_PORT_FORWARDING=on, que es off de forma predeterminada. Las guías antiguas usan PORT_FORWARDING o PRIVATE_INTERNET_ACCESS_VPN_PORT_FORWARDING. Ambos siguen funcionando en esta versión como nombres compatibles con versiones anteriores, pero se retirarán próximamente.
Dos detalles del proveedor determinan si la solicitud puede completarse. ProtonVPN requiere un plan de pago y NAT-PMP debe estar habilitado: active NAT-PMP (Port Forwarding) en las opciones de VPN al generar la configuración de WireGuard, o añada +pmp a su nombre de usuario cuando use OpenVPN. En OpenVPN, Private Internet Access usa PORT_FORWARD_ONLY, que limita la selección de servidores a los que admiten el reenvío de puertos. Así no se conecta a un servidor que nunca lo admitió. WireGuard y OpenVPN difieren en cómo se solicita el puerto, así que consulte la página de su proveedor antes de elegir.
Cuando gluetun usa una configuración personalizada en lugar de un proveedor integrado, VPN_PORT_FORWARDING_PROVIDER indica la API a la que gluetun debe llamar. La página de Private Internet Access en el proyecto upstream combina esa variable con VPN_PORT_FORWARDING_USERNAME y VPN_PORT_FORWARDING_PASSWORD, que contienen las credenciales de la cuenta necesarias para solicitar el puerto.
Activar el reenvío de puertos de gluetun en Docker Compose
Esto presupone que el túnel ya funciona. Si no funciona, empiece por enrutar el tráfico de los contenedores Docker a través de gluetun y vuelva cuando las descargas se ejecuten.
services:
gluetun:
image: qmcgaw/gluetun:v3.41.3
container_name: gluetun
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
ports:
- 8080:8080/tcp
- 8000:8000/tcp
volumes:
- ./gluetun:/gluetun
environment:
- VPN_SERVICE_PROVIDER=protonvpn
- VPN_TYPE=wireguard
- WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}
- VPN_PORT_FORWARDING=on
- TZ=Etc/UTC
restart: unless-stopped
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:5.2.3
container_name: qbittorrent
network_mode: "service:gluetun"
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- WEBUI_PORT=8080
volumes:
- ./qbittorrent:/config
- ./downloads:/downloads
depends_on:
- gluetun
restart: unless-stoppedFije la etiqueta. qmcgaw/gluetun:latest sigue la rama master, donde los componentes internos del reenvío de puertos están cambiando para la versión 4, por lo que una imagen sin una etiqueta fija puede cambiar su comportamiento en la siguiente docker compose pull. Mantenga la clave privada fuera del archivo de Compose mediante un archivo de entorno para los secretos de Compose.
Dónde escribe gluetun el puerto reenviado
Gluetun expone el puerto en tres lugares, y todos contienen el mismo valor.
Registra el puerto una vez por cada obtención. La línea contiene port forwarded is 45678 y no port forwarded cuando la solicitud no devuelve ningún valor.
docker logs gluetun 2>&1 | grep -i "port forwarded"Escribe el número en el archivo indicado por VPN_PORT_FORWARDING_STATUS_FILE, cuyo valor predeterminado es /tmp/gluetun/forwarded_port. El archivo contiene un puerto por línea, se escribe con el modo 0644 y se cambia su propietario al PUID y PGID del contenedor. Cuando se detiene el reenvío, gluetun vacía el archivo en lugar de eliminarlo. Así, un consumidor puede leer un archivo vacío en vez de encontrar que falta.
docker exec gluetun cat /tmp/gluetun/forwarded_portSirve el valor en el servidor de control, que escucha en :8000 de forma predeterminada y se configura mediante HTTP_CONTROL_SERVER_ADDRESS.
curl -s http://127.0.0.1:8000/v1/portforward{"port":45678,"ports":[45678]}Gluetun también abre ese puerto en su propio firewall de la interfaz VPN. Por tanto, FIREWALL_VPN_INPUT_PORTS no es necesario mientras la integración nativa realiza el trabajo. Esa variable cubre el otro caso: un proveedor que gluetun no puede consultar, cuando se asignó un puerto estático por otro medio y es necesario permitirlo manualmente.
Uno de estos tres mecanismos es persistente y los otros dos no. La documentación del proyecto marca el archivo de estado como obsoleto desde v4.0.0, y GET /v1/openvpn/portforwarded ya responde con 301 Moved Permanently, que apunta a /v1/portforward. El código nuevo debe leer el servidor de control.
Por qué hay que informar el puerto al cliente en cada reconexión
Un cliente de torrents guarda el puerto de escucha en su propia configuración y conserva ese número después de reiniciarse. El puerto reenviado es una propiedad de la sesión VPN. Después de una reconexión, los dos números no coinciden. El proveedor asigna entonces un puerto en el que no escucha ningún proceso, mientras el cliente escucha en un puerto que no está asignado. Las reconexiones no son poco frecuentes: pueden deberse al reinicio de un contenedor, a un cambio de servidor, a una caída del túnel que el control de estado de gluetun reinicia o a una concesión que no se pudo renovar. El resultado es una configuración que ayer era accesible y hoy no lo es, sin que aparezca ningún error en los registros.
Por tanto, el puerto debe aplicarse en el momento en que gluetun lo obtiene. Hay dos formas de configurarlo y se diferencian en qué proceso realiza el trabajo.
Opción 1: gluetun envía el puerto con un comando up
VPN_PORT_FORWARDING_UP_COMMAND se ejecuta cuando se activa el reenvío de puertos y VPN_PORT_FORWARDING_DOWN_COMMAND cuando se desactiva. Gluetun sustituye {{PORT}} (el primer puerto), {{PORTS}} (todos los puertos, separados por comas) y {{VPN_INTERFACE}} (el nombre de la interfaz del túnel, tun0 de forma predeterminada) antes de ejecutar el comando. La sintaxis de shell requiere un contenedor explícito /bin/sh -c. Este es el ejemplo de qBittorrent del proyecto original, escrito como dos entradas de entorno de compose:
- VPN_PORT_FORWARDING_UP_COMMAND=/bin/sh -c 'wget -O- -nv --retry-connrefused --post-data "json={\"listen_port\":{{PORT}},\"current_network_interface\":\"{{VPN_INTERFACE}}\",\"random_port\":false,\"upnp\":false}" http://127.0.0.1:8080/api/v2/app/setPreferences'
- VPN_PORT_FORWARDING_DOWN_COMMAND=/bin/sh -c 'wget -O- -nv --retry-connrefused --post-data "json={\"listen_port\":0,\"current_network_interface\":\"lo\"}" http://127.0.0.1:8080/api/v2/app/setPreferences'Cada campo de esa llamada tiene una función. listen_port es el nuevo puerto. current_network_interface vincula qBittorrent al túnel. Establecer random_port en false impide que qBittorrent elija su propio puerto en el siguiente arranque. Establecer upnp en false impide que intente asignar un puerto mediante un router que no existe.
Este enfoque tiene dos requisitos. La interfaz web de qBittorrent debe estar habilitada y escuchar en el puerto 8080. Además, compartir el espacio de nombres de red de gluetun permite que responda en 127.0.0.1:8080 desde dentro del contenedor de gluetun. También debe estar habilitado Bypass authentication for clients on localhost (bypass_local_auth), porque el comando no envía credenciales. El comando down es necesario porque qBittorrent no siempre restablece el puerto después de una desconexión.
El comando se ejecuta dentro del contenedor de gluetun, basado en Alpine, que incluye wget. Esa imagen no contiene curl. Un comando que indique un binario ausente en la imagen falla cada vez que se activa el reenvío.
Opción 2: un proceso externo a gluetun lee el puerto
El otro patrón ejecuta un proceso pequeño junto a gluetun. Este proceso obtiene el puerto y lo envía al cliente mediante la API del propio cliente. Puede leerlo desde el servidor de control:
port=$(curl -s http://127.0.0.1:8000/v1/portforward | jq -r .port)También puede leer el archivo si el proceso tiene acceso a él. /tmp/gluetun/forwarded_port se encuentra dentro del contenedor de gluetun. Por tanto, un sidecar necesita un volumen compartido montado en /tmp/gluetun en ambos contenedores. Otra opción es apuntar VPN_PORT_FORWARDING_STATUS_FILE a una ruta dentro de un volumen que ya esté montado.
La autenticación es importante. En v3.41.3, la ruta GET /v1/portforward pertenece a un rol predeterminado llamado public con auth = "none". Por eso responde sin credenciales y gluetun registra una advertencia que comienza por route GET /v1/portforward is unprotected by default, please set up authentication. Upstream cerrará esta posibilidad en una versión posterior. La documentación actual del servidor de control ya describe todas las rutas como privadas de forma predeterminada. Defina ahora un rol en el archivo montado mediante bind mount en /gluetun/auth/config.toml:
roles = [
{ name = "qbittorrent", routes = ["GET /v1/portforward"], auth = "apikey", apikey = "myapikey" }
]Genere una clave con docker run --rm qmcgaw/gluetun:v3.41.3 genkey y envíela en la cabecera X-API-Key. HTTP_CONTROL_SERVER_AUTH_DEFAULT_ROLE realiza la misma función que una variable de entorno codificada como JSON cuando prefiera no montar un archivo. En cuanto defina cualquier rol, v3.41.3 dejará de aplicar el rol integrado public. Por tanto, todas las rutas que invoque después necesitarán un rol que las incluya. Si no define ningún rol, el rol integrado public también cubre PUT /v1/vpn/status. En ese caso, publicar el puerto 8000 sin configurar autenticación permite que cualquiera que pueda acceder a él controle el estado de la VPN. Determine deliberadamente hasta dónde se expone al consultar cómo acceder a gluetun desde el host y otros contenedores.
Elija el comando up cuando el cliente exponga una API que pueda controlarse con una sola llamada wget. Se ejecuta exactamente una vez por evento y no requiere mantener ningún proceso en ejecución. Elija un proceso externo cuando el cliente necesite un flujo de inicio de sesión, reescribir un archivo de configuración o reiniciarse. En una pila de aplicaciones detrás de un único contenedor gluetun, esto normalmente termina siendo un único proceso de consulta periódica, porque sólo el cliente torrent necesita el puerto.
La trampa: compartir el espacio de nombres no establece el puerto de escucha
Este fallo hace perder más tiempo que cualquier otro. network_mode: "service:gluetun" coloca el cliente en el espacio de nombres de red de gluetun, por lo que el cliente obtiene la dirección VPN, las rutas del túnel y las reglas del firewall de gluetun. Nada de eso establece el puerto de escucha del cliente. Gluetun abre el puerto reenviado en la interfaz VPN. Los paquetes destinados a ese puerto llegan al espacio de nombres. Si el cliente escucha en otro puerto, el kernel no tiene ningún proceso al que entregárselos. La conexión se rechaza o agota el tiempo de espera, aunque todas las comprobaciones de salida indiquen que el servicio funciona correctamente. El puerto reenviado y el puerto de escucha del cliente son dos números distintos. La tarea consiste en mantenerlos iguales.
Compárelos en lugar de adivinarlos. Ambos comandos se ejecutan en el mismo espacio de nombres:
docker exec gluetun cat /tmp/gluetun/forwarded_port
docker exec gluetun wget -qO- http://127.0.0.1:8080/api/v2/app/preferences | grep -o '"listen_port":[0-9]*'Hay otro ajuste que lleva a muchos usuarios en la dirección equivocada. VPN_PORT_FORWARDING_LISTENING_PORT redirige el tráfico entrante del puerto reenviado a un puerto local fijo mediante iptables. La documentación de upstream indica que no debe usarse con clientes torrent, porque el cliente anuncia su propio puerto de escucha a los trackers y a los pares. Por tanto, el enjambre aprende el número incorrecto.
Cómo demostrar que el puerto reenviado es accesible
El indicador de conexión del propio cliente refleja las conexiones salientes con los trackers, por lo que puede aparecer en verde aunque nadie pueda conectarse contigo. Haz la prueba con un listener que controles, desde una red situada fuera del túnel. Upstream publica una herramienta pequeña para este fin. Detén primero el cliente de torrents, porque dos procesos no pueden asociar el mismo puerto.
docker stop qbittorrent
docker exec -it gluetun /bin/shDentro del contenedor, cambia amd64 por la arquitectura de tu CPU y 4567 por el puerto reenviado:
wget -qO port-checker https://github.com/qdm12/port-checker/releases/download/v0.4.0/port-checker_0.4.0_linux_amd64
chmod +x port-checker
./port-checker --listening-address=":4567"Ahora comprueba la dirección de salida que está usando gluetun. La respuesta está en formato JSON y la dirección se encuentra en el campo public_ip.
curl -s http://127.0.0.1:8000/v1/publicip/ipEsa petición sin parámetros sólo responde mientras v3.41.3 se ejecuta sin una configuración de autenticación. Si definiste roles como en la Opción 2, añade GET /v1/publicip/ip a routes de un rol y envía la clave de ese rol, por ejemplo curl -s -H "X-API-Key: myapikey" http://127.0.0.1:8000/v1/publicip/ip.
Abre http://<that address>:4567 desde un dispositivo que no esté en la misma VPN. Un teléfono conectado mediante datos móviles sirve. Una página que muestre la dirección IP y el agente de usuario de tu navegador, junto con una petición coincidente registrada por port-checker, indica que el tráfico TCP entrante llega al namespace. Un tiempo de espera agotado indica que no llega y que la causa está por encima del cliente. Detén la herramienta con CTRL+C, sal del shell con exit y vuelve a iniciar el cliente. Esta comprobación sólo prueba TCP. El tráfico DHT (distributed hash table) y uTP usa UDP en el mismo número de puerto, y esta prueba no lo comprueba.
Modos de fallo y mensajes que verá
No hay ninguna línea de puerto en el registro. No se solicitó ningún puerto. Confirme que la variable haya llegado realmente al contenedor con docker exec gluetun printenv | grep PORT_FORWARDING, ya que definirla en el servicio incorrecto de Compose es una causa habitual.
Gluetun no se inicia y muestra un error sobre el proveedor. VPN_PORT_FORWARDING_PROVIDER se valida con los cuatro nombres compatibles. Un error tipográfico detiene el contenedor en lugar de ejecutarlo silenciosamente sin reenvío.
El registro muestra no port forwarded. Gluetun hizo la solicitud, pero el proveedor no devolvió ningún puerto. En ProtonVPN, normalmente significa que NAT-PMP no estaba habilitado en la configuración generada o que el plan no incluye reenvío de puertos. En Private Internet Access, normalmente significa que el servidor seleccionado no ofrece esta función.
Se asigna un puerto, pero no se puede establecer ninguna conexión entrante. Compare el puerto reenviado con el puerto de escucha del cliente mediante los dos comandos anteriores. Si coinciden, compruebe que el cliente esté asociado a la interfaz del túnel y que la opción de puerto aleatorio esté desactivada, ya que esa opción cambia el puerto de escucha en cada inicio.
El comando up parece no hacer nada. Ejecute el comando exacto dentro del contenedor para ver el error: docker exec gluetun /bin/sh -c '<your command>'. curl: not found es el resultado habitual, porque la imagen sólo incluye wget.
401 Unauthorized desde el servidor de control. Definió una configuración de autenticación, pero el rol no incluye la ruta que está invocando. Las rutas se comparan como método más ruta, por lo que un rol que sólo incluya /v1/portforward no cubre GET /v1/portforward.
Un puerto diferente en Private Internet Access después de cada reinicio. Monte /gluetun como volumen para conservar el estado del puerto guardado después del reinicio. Sin ese volumen, gluetun solicita un puerto nuevo cada vez.
FAQ
¿Por qué mis torrents se descargan, pero nunca reciben conexiones entrantes?
Sin un puerto redirigido, el proveedor de VPN no tiene ninguna regla NAT que envíe los paquetes entrantes de un puerto a tu túnel. Por eso, las conexiones que no iniciaste tú se descartan en la dirección de salida. Las descargas siguen funcionando porque tu cliente abre esas conexiones por sí mismo y puede llegar a cualquier peer que sea accesible. La compartición y la incorporación a los enjambres se ven afectadas, porque ambas dependen de que otros usuarios puedan conectarse contigo. La solución es usar un proveedor que ofrezca redirección de puertos, VPN_PORT_FORWARDING=on en gluetun y aplicar el puerto resultante al puerto de escucha del cliente.
¿Funciona gluetun con la redirección de puertos de cualquier proveedor de VPN?
No. Gluetun v3.41.3 tiene integración nativa con cuatro proveedores: Private Internet Access, ProtonVPN, Perfect Privacy y PrivateVPN. Todo lo que no esté en esa lista falla la validación de VPN_PORT_FORWARDING_PROVIDER y el contenedor se detiene durante el arranque. Si tu proveedor asigna un puerto estático desde su propio panel de control, gluetun no puede solicitarlo por ti, pero FIREWALL_VPN_INPUT_PORTS permitirá ese puerto fijo a través del firewall de gluetun. Las políticas de los proveedores cambian, así que consulta la página actual del proveedor antes de contratar un plan para este fin.
¿Tengo que actualizar el puerto después de cada reconexión?
Sí, y esa actualización debería ser automática. El puerto redirigido pertenece a la sesión de VPN. Por eso, un reinicio del contenedor, un cambio de servidor o una renovación fallida de la concesión pueden generar un número nuevo, mientras el cliente conserva el puerto almacenado en su propia configuración. Puedes dejar que gluetun lo aplique mediante VPN_PORT_FORWARDING_UP_COMMAND, que se ejecuta en cuanto se activa la redirección, o ejecutar un proceso pequeño que lea GET /v1/portforward del servidor de control y escriba el valor en el cliente mediante su API.
¿Cómo compruebo que el puerto redirigido está realmente abierto?
Ejecuta un listener en ese puerto exacto dentro del espacio de nombres de red de gluetun y conéctate desde fuera de la VPN. Detén primero el cliente de torrents para que el puerto quede libre. Después, ejecuta el binario upstream port-checker dentro del contenedor de gluetun con --listening-address=":<port>". Obtén la dirección de salida mediante curl -s http://127.0.0.1:8000/v1/publicip/ip, añadiendo -H "X-API-Key: <key>" para un rol que enumere GET /v1/publicip/ip si has configurado la autenticación del servidor de control, y abre http://<address>:<port> desde un teléfono conectado mediante datos móviles. Si aparece una solicitud en el registro de port-checker, se confirma que el tráfico TCP entrante llega. Un tiempo de espera agotado significa que no llega, independientemente del icono de estado del propio cliente.