SSD Nodes Learn 🎉 VPS от $5.50/мес
Руководства Matt ConnorАвтор: Matt Connor

Настройка проброса портов в Gluetun для торрент-клиентов

Настройте проброс портов в Gluetun, чтобы входящие соединения работали корректно. Узнайте, как передать актуальный порт в торрент-клиент при каждом переподключении и проверить статус.

Почему входящие соединения не работают без проброса порта

Функция проброса портов в Gluetun запрашивает у вашего VPN-провайдера привязку одного публичного порта на его выходном адресе к вашему контейнеру. Это единственный способ для другого участника сети инициировать соединение с вашим торрент-клиентом. Без такой привязки туннель работает исправно, загрузки идут, но входящие запросы извне не поступают. Любое работающее соединение — это соединение, которое ваш клиент открыл первым.

Механизм основан на NAT (network address translation). Ваш контейнер использует выходной адрес провайдера совместно со множеством других клиентов. Когда ваш клиент открывает исходящее соединение, провайдер фиксирует этот поток и направляет ответы обратно в ваш туннель. Попытка стороннего участника сети подключиться к вам не соответствует ни одному зафиксированному потоку, поэтому пакет достигает выходного адреса и отбрасывается. Ваш клиент по-прежнему может подключаться к любому участнику, который сам доступен для соединений, поэтому загрузки завершаются, а проблема остается незаметной. Она проявляется при раздаче, так как раздающий — это узел, к которому подключаются другие люди.

Открытый входящий порт меняет две вещи. Вы быстрее присоединяетесь к рою, так как участники, которые сами не могут принимать соединения, теперь могут связаться с вами, и вы получаете возможность отдавать данные этим участникам.

Почему большинство VPN-провайдеров не предоставляют проброс портов

Проброшенный порт — это дефицитный ресурс при использовании общего IP-адреса. Провайдер резервирует один номер порта на одном выходном IP-адресе для одного клиента и затем несет ответственность за любые действия этого клиента с данным портом. Ряд крупных провайдеров убрали эту функцию, сославшись на сложности с обработкой злоупотреблений. Рассматривайте поддержку этой функции как категориальный вопрос, а не как наличие галочки в списке: уточняйте, предлагает ли провайдер проброс портов прямо сейчас, доступен ли он на вашем тарифном плане и на тех серверах, которые вы можете выбрать.

Там, где проброс портов реализован, номер порта является динамическим. Он привязан к VPN-сессии, а не к вашей учетной записи, поэтому после каждого переподключения номер может измениться. Private Internet Access выдает подписанный порт, который обновляется через gluetun. Согласно документации вышестоящего сервиса, вы сохраняете один и тот же порт в течение 60 дней, если используете bind mount для директории /gluetun, чтобы состояние сохранялось после перезапуска. ProtonVPN назначает случайный порт через NAT-PMP (NAT port mapping protocol) с коротким сроком аренды, который необходимо постоянно продлевать. Именно поэтому однократная настройка порта в клиенте перестает работать через некоторое время.

Провайдеры, у которых gluetun может запросить порт

Начиная с версии gluetun v3.41.3, выпущенной 30 июля 2026 года, встроенная интеграция поддерживает четыре имени провайдеров: Private Internet Access, ProtonVPN, Perfect Privacy и PrivateVPN. Включите эту функцию с помощью VPN_PORT_FORWARDING=on, которая по умолчанию имеет значение off. В старых руководствах используются PORT_FORWARDING или PRIVATE_INTERNET_ACCESS_VPN_PORT_FORWARDING. Оба варианта всё ещё работают в этой версии как обратно совместимые имена, но постепенно выводятся из употребления.

Успех запроса зависит от двух параметров провайдера. Для ProtonVPN требуется платный тариф, а также должна быть включена функция NAT-PMP: активируйте NAT-PMP (Port Forwarding) в настройках VPN при генерации конфигурации WireGuard или добавьте +pmp к имени пользователя при использовании OpenVPN. У Private Internet Access при работе через OpenVPN есть параметр PORT_FORWARD_ONLY, который ограничивает выбор серверов только теми, что поддерживают переадресацию, чтобы вы не попали на сервер, где эта функция отсутствует. WireGuard и OpenVPN различаются способом запроса порта, поэтому ознакомьтесь со страницей вашего провайдера перед выбором.

Когда gluetun использует пользовательскую конфигурацию вместо встроенного провайдера, VPN_PORT_FORWARDING_PROVIDER указывает имя API, к которому должен обращаться gluetun. На странице Private Internet Access эта переменная используется в паре с VPN_PORT_FORWARDING_USERNAME и VPN_PORT_FORWARDING_PASSWORD, которые содержат учетные данные, необходимые для запроса порта.

Включение переадресации портов в gluetun через docker compose

Данное руководство предполагает, что VPN-туннель уже функционирует. Если это не так, начните с настройки маршрутизации трафика Docker-контейнера через gluetun и вернитесь сюда после того, как загрузки начнут работать.

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-stopped

Зафиксируйте версию образа (тег). qmcgaw/gluetun:latest следует за веткой master, где внутренняя логика переадресации портов меняется для v4, поэтому использование незафиксированного образа может привести к изменению поведения при следующем docker compose pull. Храните закрытый ключ отдельно от файла compose, используя env-файл для секретов compose.

Где gluetun записывает перенаправленный порт

Gluetun предоставляет информацию о порте в трех местах, и во всех них содержится одно и то же значение.

Он записывает порт в лог один раз при получении. Строка выглядит как port forwarded is 45678, а при отсутствии результата запроса — как no port forwarded.

docker logs gluetun 2>&1 | grep -i "port forwarded"

Он записывает номер в файл, указанный в VPN_PORT_FORWARDING_STATUS_FILE, значением по умолчанию для которого является /tmp/gluetun/forwarded_port. Файл содержит один порт на строку, записывается с правами 0644 и владельцем PUID:PGID внутри контейнера. При остановке перенаправления gluetun очищает файл вместо его удаления, чтобы потребитель мог прочитать пустой файл, а не столкнуться с ошибкой отсутствия файла.

docker exec gluetun cat /tmp/gluetun/forwarded_port

Он предоставляет значение через управляющий сервер, который по умолчанию слушает :8000 и настраивается через HTTP_CONTROL_SERVER_ADDRESS.

curl -s http://127.0.0.1:8000/v1/portforward
{"port":45678,"ports":[45678]}

Gluetun также открывает этот порт в собственном межсетевом экране на VPN-интерфейсе, поэтому FIREWALL_VPN_INPUT_PORTS не требуется, пока работает встроенная интеграция. Эта переменная покрывает другой случай: провайдер, который gluetun не может опросить, когда вам был выдан статический порт вне системы и его нужно разрешить вручную.

Один из этих трех способов является постоянным, а два других — нет. В документации вышестоящего проекта статус-файл помечен как устаревший в версии v4.0.0, а GET /v1/openvpn/portforwarded уже отвечает 301 Moved Permanently, указывая на /v1/portforward. Новые разработки должны использовать чтение через управляющий сервер.

Почему клиенту необходимо сообщать порт при каждом переподключении

Торрент-клиент сохраняет номер порта для входящих соединений в своей конфигурации и использует его после перезапуска. Проброшенный порт является свойством VPN-сессии. После переподключения эти значения перестают совпадать: провайдер назначает порт, на котором никто не слушает, а клиент слушает порт, который никто не пробрасывает. Переподключения происходят часто: при перезапуске контейнера, смене сервера, разрыве туннеля, который восстанавливает health check в gluetun, или при невозможности продлить аренду IP-адреса. В результате конфигурация, которая работала вчера, сегодня становится недоступной без каких-либо ошибок в логах.

Поэтому порт должен применяться в тот момент, когда gluetun получает его от провайдера. Существует два способа реализации этой задачи, которые различаются тем, какой процесс выполняет работу.

Вариант 1: gluetun передает порт через команду up

VPN_PORT_FORWARDING_UP_COMMAND выполняется при установке переадресации портов, а VPN_PORT_FORWARDING_DOWN_COMMAND — при её отключении. Перед выполнением команды gluetun подставляет {{PORT}} (первый порт), {{PORTS}} (все порты через запятую) и {{VPN_INTERFACE}} (имя туннельного интерфейса, по умолчанию tun0). Синтаксис оболочки требует явного использования обертки /bin/sh -c. Ниже приведен пример для qBittorrent, оформленный в виде двух переменных окружения для 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'

Каждое поле в этом вызове выполняет свою задачу. listen_port — это новый порт. current_network_interface привязывает qBittorrent к туннелю. Параметр random_port, установленный в false, запрещает qBittorrent выбирать собственный порт при следующем запуске. Параметр upnp, установленный в false, отключает попытки настроить проброс порта через несуществующий маршрутизатор.

Для этого подхода существуют два требования. Веб-интерфейс qBittorrent должен отвечать на 127.0.0.1:8080 изнутри контейнера gluetun, что происходит автоматически, когда клиент использует сетевое пространство имен gluetun. Также должен быть включен Bypass authentication for clients on localhost (bypass_local_auth), так как команда не передает учетные данные. Команда down необходима, так как qBittorrent не всегда восстанавливает порт после разрыва соединения.

Команда выполняется внутри контейнера gluetun, который построен на базе Alpine и содержит wget. В этом образе отсутствует curl. Команда, вызывающая бинарный файл, которого нет в образе, будет приводить к ошибке при каждой попытке включения переадресации.

Вариант 2: процесс вне gluetun считывает порт

Другой шаблон предполагает запуск небольшого процесса рядом с gluetun, который получает порт и передает его клиенту через собственный API клиента. Считайте его с сервера управления:

port=$(curl -s http://127.0.0.1:8000/v1/portforward | jq -r .port)

Или считайте файл, если процесс имеет к нему доступ. /tmp/gluetun/forwarded_port находится внутри контейнера gluetun, поэтому sidecar-контейнеру требуется общий том, смонтированный в /tmp/gluetun в обоих контейнерах, либо вы можете указать VPN_PORT_FORWARDING_STATUS_FILE путь внутри тома, который вы уже монтируете.

Здесь важна аутентификация. В версии v3.41.3 маршрут GET /v1/portforward относится к роли по умолчанию с именем public и с auth = "none", поэтому он отвечает без учетных данных, а gluetun записывает в лог предупреждение, начинающееся с route GET /v1/portforward is unprotected by default, please set up authentication. В будущих релизах разработчики планируют закрыть этот доступ. Определите роль сейчас в файле, подключенном через bind mount в /gluetun/auth/config.toml:

roles = [
  { name = "qbittorrent", routes = ["GET /v1/portforward"], auth = "apikey", apikey = "myapikey" }
]

Сгенерируйте ключ с помощью docker run --rm qmcgaw/gluetun:v3.41.3 genkey и передайте его в заголовке X-API-Key. HTTP_CONTROL_SERVER_AUTH_DEFAULT_ROLE выполняет ту же задачу, что и одна переменная окружения в формате JSON, если вы не хотите монтировать файл. Порт 8000, опубликованный без роли, дает любому, кто имеет к нему доступ, управление состоянием VPN, поэтому тщательно продумайте область доступа, когда будете изучать как получить доступ к gluetun с хоста и других контейнеров.

Выбирайте команду up, если клиент предоставляет API, который можно вызвать одним запросом wget, так как она срабатывает ровно один раз на событие и не требует постоянной работы. Выбирайте внешний процесс, если клиенту требуется процедура входа, перезапись конфигурационного файла или перезапуск. В стеке arr за одним контейнером gluetun это обычно сводится к одному небольшому поллеру, так как порт важен только для торрент-клиента.

Ловушка: использование общего пространства имен не настраивает порт для прослушивания

Эта ошибка отнимает больше всего времени. network_mode: "service:gluetun" помещает клиент в сетевое пространство имен gluetun, поэтому он получает VPN-адрес, маршруты туннеля и правила межсетевого экрана gluetun. Ничто из этого не настраивает порт для прослушивания на стороне клиента. Gluetun открывает перенаправленный порт на VPN-интерфейсе, пакеты для него поступают в пространство имен, но если клиент слушает другой порт, ядру некуда их доставлять. Соединение отклоняется или истекает по тайм-ауту, хотя все проверки исходящего трафика выглядят успешно. Перенаправленный порт и порт прослушивания клиента — это два разных числа, и вся задача заключается в том, чтобы они совпадали.

Сравнивайте их, а не гадайте. Обе команды выполняются в одном и том же пространстве имен:

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]*'

Еще одна настройка сбивает пользователей с толку. VPN_PORT_FORWARDING_LISTENING_PORT перенаправляет входящий трафик с перенаправленного порта на фиксированный локальный порт с помощью iptables. Разработчики не рекомендуют использовать её с торрент-клиентами, так как клиент сообщает трекерам и пирам свой собственный порт прослушивания, из-за чего в сети распространяется неверный номер порта.

Как проверить доступность проброшенного порта

Индикатор соединения в клиенте отображает исходящие подключения к трекеру, поэтому он может гореть зеленым, даже если входящие соединения недоступны. Проведите тестирование с помощью слушающего процесса, который вы контролируете, из сети вне туннеля. Разработчики upstream предоставляют для этого небольшую утилиту. Сначала остановите torrent-клиент, так как два процесса не могут использовать один и тот же порт одновременно.

docker stop qbittorrent
docker exec -it gluetun /bin/sh

Внутри контейнера замените amd64 на вашу архитектуру процессора, а 4567 — на ваш проброшенный порт:

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"

Теперь определите выходной IP-адрес, который использует gluetun. Ответ придет в формате JSON, адрес будет указан в поле public_ip.

curl -s http://127.0.0.1:8000/v1/publicip/ip

Откройте http://<that address>:4567 с устройства, которое не подключено к этому же VPN. Подойдет телефон с мобильным интернетом. Если страница показывает IP-адрес вашего браузера и user agent, а в логах port-checker отображается соответствующий запрос, значит, входящий TCP-трафик достигает пространства имен. Если возникает таймаут, значит, трафик не проходит, и проблема находится на уровне выше клиента. Остановите утилиту комбинацией CTRL+C, выйдите из оболочки командой exit и запустите клиент снова. Эта проверка затрагивает только TCP. DHT (distributed hash table) и трафик uTP используют UDP на том же номере порта, что данный тест не проверяет.

Типичные ошибки и сообщения в логах

В логах вообще нет строки с портом. Никакой запрос на получение порта не был выполнен. Убедитесь, что переменная окружения действительно передана в контейнер с помощью docker exec gluetun printenv | grep PORT_FORWARDING, так как установка переменной не в том сервисе docker-compose — частая причина ошибки.

Gluetun не запускается и выдает ошибку провайдера. Значение VPN_PORT_FORWARDING_PROVIDER проверяется на соответствие четырем поддерживаемым именам, поэтому опечатка приведет к остановке контейнера, а не к его тихой работе без проброса портов.

В логах указано no port forwarded. Gluetun отправил запрос, но провайдер не вернул данные. В случае с ProtonVPN это обычно означает, что NAT-PMP не включен в сгенерированной конфигурации или ваш тарифный план не поддерживает проброс портов. Для Private Internet Access это чаще всего означает, что выбранный сервер не поддерживает данную функцию.

Порт получен, но соединения не проходят. Сравните проброшенный порт с портом, который слушает клиент, используя две команды выше. Если они совпадают, убедитесь, что клиент привязан к интерфейсу туннеля и что опция использования случайного порта (random-port) отключена, так как она меняет порт прослушивания при каждом запуске.

Команда up кажется нерабочей. Выполните команду напрямую внутри контейнера, чтобы увидеть ошибку: docker exec gluetun /bin/sh -c '<your command>'. Обычно результатом является curl: not found, так как образ содержит только wget.

401 Unauthorized от сервера управления. Вы настроили конфигурацию аутентификации, но в роли не указан маршрут, к которому вы обращаетесь. Маршруты сопоставляются как метод плюс путь, поэтому роль, в которой указан только /v1/portforward, не дает доступа к GET /v1/portforward.

Разные порты при каждом перезапуске на Private Internet Access. Используйте bind mount для /gluetun, чтобы сохраненное состояние порта не терялось после перезагрузки. Без этого тома gluetun каждый раз запрашивает новый порт.

FAQ

Почему мои торренты скачиваются, но входящие соединения не устанавливаются?

Без проброса порта у VPN-провайдера нет правила NAT, которое направляло бы входящие пакеты с какого-либо порта в ваш туннель, поэтому соединения, которые вы не инициировали сами, отбрасываются на выходном узле. Загрузка работает, так как клиент сам открывает эти соединения и может связаться с любым доступным участником сети. Раздача и присоединение к рою затруднены, так как оба процесса зависят от возможности других участников подключиться к вам. Решение заключается в использовании провайдера, поддерживающего проброс портов, настройке VPN_PORT_FORWARDING=on в gluetun и применении полученного порта в качестве порта для прослушивания в клиенте.

Работает ли gluetun с пробросом портов любого VPN-провайдера?

Нет. Gluetun версии v3.41.3 имеет встроенную интеграцию для четырех провайдеров: Private Internet Access, ProtonVPN, Perfect Privacy и PrivateVPN. Любой провайдер вне этого списка не пройдет проверку VPN_PORT_FORWARDING_PROVIDER, и контейнер остановится при запуске. Если ваш провайдер выдает статический порт через собственную панель управления, gluetun не сможет запросить его для вас, но FIREWALL_VPN_INPUT_PORTS позволит пропустить этот фиксированный порт через межсетевой экран gluetun. Политики провайдеров меняются, поэтому перед покупкой тарифа ознакомьтесь с актуальной информацией на странице провайдера.

Нужно ли обновлять порт после каждого переподключения?

Да, и это обновление должно происходить автоматически. Проброшенный порт привязан к VPN-сессии, поэтому перезапуск контейнера, смена сервера или неудачное продление аренды могут привести к получению нового номера, в то время как клиент будет использовать старый порт, сохраненный в его конфигурации. Либо позвольте gluetun передать его с помощью VPN_PORT_FORWARDING_UP_COMMAND, который срабатывает в момент появления проброса, либо запустите небольшой процесс, который считывает GET /v1/portforward с сервера управления и записывает значение в клиент через его API.

Как проверить, что проброшенный порт действительно открыт?

Запустите прослушивание на этом порту внутри сетевого пространства имен gluetun и подключитесь к нему извне VPN. Сначала остановите торрент-клиент, чтобы освободить порт, затем запустите исполняемый файл для проверки портов внутри контейнера gluetun с помощью --listening-address=":<port>". Узнайте адрес выходного узла через curl -s http://127.0.0.1:8000/v1/publicip/ip и откройте http://<address>:<port> с телефона через мобильную сеть. Появление запроса в логе проверки порта подтверждает, что входящий TCP-трафик доходит до вас. Тайм-аут означает, что трафик не проходит, независимо от того, что показывает значок статуса в самом клиенте.

#gluetun#vpn#port-forwarding#docker#torrenting