lenec ru

← все посты

Cloudflare Tunnel: открыть локальный сервер без публичного IP

12K

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

Контекст: Linux-сервер за NAT (домашний роутер, корпоративная сеть, серверный VPS без публичного IP). Cloudflare как DNS-провайдер для домена.

Как это работает

Идея простая: на твоём сервере запускается процесс cloudflared, который сам устанавливает исходящее соединение к Cloudflare. Когда из интернета приходит запрос на твой домен, Cloudflare пробрасывает его через этот туннель прямо на сервер. Никаких входящих портов, никаких пробросов на роутере, никакого настоящего IP-адреса в открытом доступе.

Важный нюанс: трафик проходит через Cloudflare. Это значит, что Cloudflare видит твой трафик в расшифрованном виде (там можно настроить mTLS до своего сервера, но это уже отдельная история). Для большинства dev и прод-сценариев — приемлемо, но если у тебя строгие требования к локализации данных, тут стоит дважды подумать.

Что нужно

  • Аккаунт в Cloudflare (Free-плана достаточно).
  • Домен, делегированный на Cloudflare DNS.
  • Сервер с возможностью исходящих подключений на 443 порт.
  • Установленный cloudflared.

Установка cloudflared

На Ubuntu/Debian:

curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.deb
cloudflared --version

На других ОС есть бинарики и пакеты на странице релизов. Под Alpine — скачать бинарь, положить в /usr/local/bin.

Авторизация

cloudflared login

Команда откроет браузер и попросит выбрать домен, делегированный на Cloudflare. После авторизации создастся файл ~/.cloudflared/cert.pem с сертификатом, привязанным к твоему аккаунту и домену. Этот файл — основа дальнейшей работы. Не теряй его и не публикуй.

Создание туннеля

cloudflared tunnel create my-tunnel

Вернётся UUID туннеля и путь к credentials-файлу: ~/.cloudflared/<uuid>.json. Этот файл нужен сервису, чтобы аутентифицироваться при подключении к Cloudflare.

Конфиг

В ~/.cloudflared/config.yml:

tunnel: my-tunnel
credentials-file: /home/user/.cloudflared/<uuid>.json

ingress:
  - hostname: app.example.ru
    service: http://localhost:3000
  - hostname: api.example.ru
    service: http://localhost:4000
  - hostname: db-admin.example.ru
    service: http://localhost:8081
  # обязательный «catch-all»
  - service: http_status:404

Каждый блок ingress — это правило: «запросы на такой-то hostname кидать на такой-то локальный URL». Последний catch-all обязателен — без него будет ошибка.

DNS-записи

cloudflared умеет сам прописать DNS-записи:

cloudflared tunnel route dns my-tunnel app.example.ru
cloudflared tunnel route dns my-tunnel api.example.ru
cloudflared tunnel route dns my-tunnel db-admin.example.ru

В Cloudflare DNS появятся CNAME-записи вида app.example.ru → <tunnel_uuid>.cfargotunnel.com. SSL-сертификаты Cloudflare выпускает автоматически.

Запуск

Тестово:

cloudflared tunnel run my-tunnel

Если в логах connection registered — туннель работает. Заходи в браузер на https://app.example.ru и проверяй.

Для прод запускаешь как сервис:

sudo cloudflared service install
sudo systemctl enable --now cloudflared

cloudflared положит свой systemd-юнит и запустит его. Конфиг будет браться из /etc/cloudflared/config.yml; убедись, что туда скопирован твой config.yml и credentials-файл.

Сценарии использования

Dev-стенд за корпоративным файрволом

Хочешь показать заказчику ветку без деплоя на staging — поднимаешь приложение на ноуте, открываешь tunnel preview-1.example.ru, кидаешь ссылку. Всё работает, никаких VPN-ов и публикаций портов на корпоративном маршрутизаторе.

Внутренние админки

Bull Board, Grafana, pgAdmin, Adminer — всё это сервисы, которые лучше не светить наружу. Через Cloudflare Tunnel + Cloudflare Access ты получаешь zero-trust доступ: «только сотрудники с email на @example.ru». Внешним сканерам интерфейс невидим, не нужно раздавать VPN-доступ.

Webhooks для локальной разработки

Никаких ngrok-токенов и эфемерных URL. Один раз настроил dev-webhooks.example.ru, он живёт месяцами и ходит ровно к твоему ноуту. Стабильный URL для тестов оплат, бот-вебхуков, сторонних интеграций.

Self-hosted сервисы дома

Файловое хранилище, Plex, Home Assistant — всё это можно опубликовать через Tunnel без проброса портов на домашнем роутере. Я держу пару домашних сервисов на этом сетапе уже два года.

Cloudflare Access — это важная часть

Tunnel сам по себе делает сервис доступным из интернета. Если это админка — нужна аутентификация. Cloudflare Access — это zero-trust gateway, который ставится перед сервисом и требует аутентификации до того, как запрос дойдёт до тебя.

Настройка через панель Cloudflare:

  1. Zero Trust → Access → Applications → Add an application.
  2. Указываешь поддомен (например, db-admin.example.ru).
  3. Выбираешь политику: доступ только для конкретных email или domain. Можно подключить SSO через Google/Microsoft/Okta.

На бесплатном плане Cloudflare даётся до 50 пользователей, которым можно настроить такой доступ. Этого хватает почти для любых внутренних команд.

Подводные камни

WebSocket и SSE

Tunnel поддерживает их без отдельной настройки. Но Cloudflare имеет таймауты на длинные соединения: для бесплатного плана — 100 секунд idle. Если у тебя SSE с тонким стримом, добавь heartbeat-сообщения раз в 30 секунд.

Большие POST-запросы

Cloudflare ограничивает размер тела запроса: на бесплатном плане 100 MB, на платном — 500 MB и больше. Если хочешь грузить большие файлы напрямую — это не подойдёт, лучше использовать прямой upload в Object Storage с presigned URL.

Несколько туннелей на один сервер

На одном сервере может работать несколько cloudflared с разными config.yml — это нормально. Я держу два: один публичный (admins на zero-trust), второй приватный для дев-преврью с другим credentials-файлом. Не путаться помогает строгое именование.

Бэкап credentials

Файл <uuid>.json с приватным ключом туннеля незаменимый. Если потеряешь — придётся пересоздавать туннель и обновлять DNS-записи. Я держу его в защищённом backup-хранилище и в репозитории секретов.

Обновление

cloudflared обновляется не автоматически. На свежих версиях бывают улучшения по производительности и новые опции. Раз в пару месяцев обновляй вручную:

sudo cloudflared service stop
sudo dpkg -i <new cloudflared.deb>
sudo cloudflared service start

Сравнение с ngrok и tailscale

Я часто слышу вопрос «а почему не ngrok / tailscale».

  • ngrok. Удобный для разовой ссылки. Tunnel держит постоянный URL без подписки и абонентки.
  • tailscale. Отлично для соединения нескольких устройств в общую mesh-сеть. Но не для публикации сервиса наружу: внешние пользователи не получат прозрачный доступ через домен.

Каждый инструмент на своём месте. Для «опубликовать сервис в интернете без публичного IP» — Tunnel лучший вариант, который я пробовал.

Шпаргалка

  • cloudflared login, потом tunnel create.
  • config.yml с ingress-правилами, обязательный catch-all 404.
  • DNS-записи через cloudflared tunnel route dns.
  • Запуск как systemd-сервис.
  • Защищай админки через Cloudflare Access.
  • Бэкап credentials-файла.
  • Помни про лимиты на размер запроса и таймауты.

Cloudflare Tunnel — то решение, которое экономит мне много времени. На простых задачах разворачивается за 10 минут, работает годами без вмешательства, не требует прав на роутер. Для большинства dev и внутренних сценариев — почти идеальный инструмент.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.