Проблема IoT: устройства за NAT без публичного доступа
Raspberry Pi стоит на полке дома. ESP32-датчики разбросаны по складу. Контроллер умного дома сидит за CGNAT провайдера. Ни у одного из них нет статического IP и прямого доступа из интернета. Когда вам нужно зайти на Pi по SSH из офиса, отправить данные с датчика в облако или показать веб-интерфейс ESP32 коллеге – сеть не пускает.
Это фундаментальная проблема IoT: устройства должны быть доступны извне, но сетевая инфраструктура активно этому мешает. Туннелирование решает задачу – устройство само устанавливает исходящее соединение с публичным сервером и получает адрес, доступный откуда угодно.
IoT-устройства за NAT (нет публичного IP)
┌──────────────────────────────────────────────┐
│ Домашняя / офисная сеть │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Raspberry Pi│ │ ESP32 │ │
│ │ SSH :22 │ │ Web :80 │ │
│ │ Grafana:3000│ │ MQTT :1883 │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ └───────┬────────┘ │
│ │ │
│ ┌───────▼────────┐ │
│ │ NAT / Роутер │ │
│ │ (нет проброса)│ │
│ └───────┬────────┘ │
└─────────────────┼────────────────────────────┘
│ исходящее соединение (TLS)
▼
┌──────────────────┐
│ fxTunnel Server │
│ tunnel.fxtun.dev│
└────────┬─────────┘
│
▼
Публичные адреса:
ssh → tunnel.fxtun.dev:41234
web → https://rpi.fxtun.dev
mqtt → tunnel.fxtun.dev:51883
Традиционные решения и их проблемы
Без туннеля остаются три классических варианта: проброс портов на роутере, VPN или аренда статического IP. Все три сложны в настройке и создают дополнительные проблемы. Подробнее о компромиссах – в статье «Как открыть localhost из интернета».
Проброс портов на роутере требует доступа к настройкам роутера, публичного IP (не CGNAT) и ручной конфигурации для каждого устройства. Порт открыт всему интернету без шифрования — это прямая угроза безопасности для IoT-устройств, которые часто имеют слабую защиту.
VPN (WireGuard, OpenVPN) создаёт зашифрованный канал, но требует сервера с публичным IP, настройки на каждом устройстве и поддержки. Для одного Raspberry Pi — это избыточное решение. Для ESP32 — часто невозможное из-за ограничений памяти и процессора.
Статический IP стоит денег, привязывает к провайдеру и всё равно требует проброса портов и настройки файрвола. Многие провайдеры не предоставляют статический IP для домашних тарифов.
Туннель — это одна команда на устройстве. Никаких настроек роутера, никакого VPN-сервера, никакого статического IP. Устройство устанавливает исходящее TLS-соединение, а fxTunnel выдаёт публичный адрес.
Как туннели решают проблему IoT-связности
Клиент на IoT-устройстве открывает исходящее TLS-соединение с сервером fxTunnel. Сервер выделяет публичный адрес (URL для HTTP или хост:порт для TCP/UDP) и маршрутизирует входящий трафик через это соединение на локальный порт устройства. NAT и файрвол не мешают, потому что соединение идёт изнутри сети.
Что делает fxTunnel особенно полезным для IoT – поддержка TCP и UDP. Большинство IoT-протоколов (MQTT, CoAP, Modbus TCP) работают поверх TCP, а некоторые (CoAP, mDNS) – поверх UDP. fxTunnel покрывает оба случая, в отличие от ngrok (только TCP/HTTP) или Cloudflare Tunnel (только HTTP на бесплатном тарифе).
Сценарий 1: Удалённый доступ к Raspberry Pi
Нужно зайти по SSH на Raspberry Pi, который стоит дома, а вы – в офисе? Это, пожалуй, самый распространённый IoT-сценарий для туннеля.
SSH через TCP-туннель
# На Raspberry Pi: пробрасываем SSH-порт
fxtunnel tcp 22
# → tunnel.fxtun.dev:41234
# С любого компьютера: подключаемся к Raspberry Pi
ssh -p 41234 pi@tunnel.fxtun.dev
Готово. Вы получили SSH-доступ к Raspberry Pi без статического IP, без проброса портов и без VPN.
Веб-интерфейс через HTTP-туннель
Если на Raspberry Pi работает веб-приложение (Home Assistant, OctoPrint, Pi-hole), откройте HTTP-туннель:
# Веб-интерфейс Home Assistant на порте 8123
fxtunnel http 8123
# → https://rpi-home.fxtun.dev
Публичный HTTPS-URL можно открыть в браузере с любого устройства — телефона, рабочего компьютера, планшета.
Сценарий 2: MQTT-брокер через TCP-туннель
MQTT — основной протокол для IoT-сенсоров и актуаторов. Брокер (Mosquitto, EMQX) обычно работает на Raspberry Pi или сервере в локальной сети. Чтобы IoT-устройства из других сетей могли публиковать и получать сообщения, нужен публичный доступ к брокеру.
# На машине с MQTT-брокером
# Mosquitto слушает порт 1883 (TCP)
fxtunnel tcp 1883
# → tunnel.fxtun.dev:51883
┌─────────────┐ ┌─────────────────────┐ ┌─────────────┐
│ ESP32 #1 │ │ fxTunnel Server │ │ Raspberry Pi│
│ (датчик │────▶│ tunnel.fxtun.dev │◀────│ Mosquitto │
│ температуры)│ │ :51883 │ │ :1883 │
└─────────────┘ └─────────────────────┘ └─────────────┘
▲
┌─────────────┐ │
│ ESP32 #2 │─────────────┘
│ (датчик │
│ влажности) │
└─────────────┘
Теперь ESP32 из любой сети может подключиться к брокеру:
// Arduino / ESP32 — подключение к MQTT через туннель
#include <WiFi.h>
#include <PubSubClient.h>
const char* mqtt_server = "tunnel.fxtun.dev";
const int mqtt_port = 51883;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
WiFi.begin("SSID", "password");
while (WiFi.status() != WL_CONNECTED) delay(500);
client.setServer(mqtt_server, mqtt_port);
while (!client.connected()) {
client.connect("esp32-sensor-01");
delay(1000);
}
}
void loop() {
float temp = analogRead(34) * 0.1; // пример чтения датчика
char payload[16];
snprintf(payload, sizeof(payload), "%.1f", temp);
client.publish("sensors/temperature", payload);
client.loop();
delay(5000);
}
Сценарий 3: Веб-сервер ESP32
ESP32 часто используется с встроенным веб-сервером для конфигурации и мониторинга. Проблема — веб-интерфейс доступен только в локальной сети. Через туннель вы можете открыть его для удалённого доступа.
Поскольку ESP32 не может запустить fxTunnel напрямую (ограничения ресурсов), используйте промежуточный хост — Raspberry Pi или любой компьютер в той же сети:
# На Raspberry Pi в той же сети, что и ESP32
# ESP32 имеет IP 192.168.1.50 и веб-сервер на порте 80
fxtunnel http 192.168.1.50:80
# → https://esp32-web.fxtun.dev
Теперь веб-интерфейс ESP32 доступен по публичному HTTPS-адресу. Это полезно для удалённой отладки, конфигурации устройства и демонстрации прототипов.
Сценарий 4: Дашборд мониторинга (Grafana / Node-RED)
На Raspberry Pi часто работают дашборды для мониторинга IoT-данных: Grafana (визуализация метрик), Node-RED (автоматизация потоков) или собственные веб-приложения. Чтобы дать доступ команде, откройте HTTP-туннель:
# Grafana на порте 3000
fxtunnel http 3000
# → https://iot-dashboard.fxtun.dev
# Node-RED на порте 1880
fxtunnel http 1880
# → https://nodered.fxtun.dev
Для сценария с несколькими сервисами на одном Raspberry Pi запустите отдельный туннель для каждого:
# Запускаем все туннели одновременно
fxtunnel tcp 22 & # SSH-доступ
fxtunnel http 3000 & # Grafana
fxtunnel http 1880 & # Node-RED
fxtunnel tcp 1883 & # MQTT-брокер
Установка fxTunnel на Raspberry Pi
fxTunnel написан на Go и поставляется с ARM-бинарниками из коробки. Установка одной командой работает на всех моделях Raspberry Pi – от Zero до Pi 5.
Установка
# Установка fxTunnel (автоматически определяет ARM-архитектуру)
curl -fsSL https://fxtun.dev/install.sh | bash
# Проверяем установку
fxtunnel --version
Автозапуск через systemd
Для IoT-устройств критично, чтобы туннель запускался автоматически при загрузке и перезапускался при сбоях. Создайте systemd-сервис:
# /etc/systemd/system/fxtunnel.service
[Unit]
Description=fxTunnel - IoT tunnel service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/fxtunnel tcp 22
Restart=always
RestartSec=5
User=pi
Environment=FXTUNNEL_TOKEN=your-auth-token-here
[Install]
WantedBy=multi-user.target
Активируйте сервис:
# Перечитываем конфигурацию systemd
sudo systemctl daemon-reload
# Включаем автозапуск при загрузке
sudo systemctl enable fxtunnel
# Запускаем сейчас
sudo systemctl start fxtunnel
# Проверяем статус
sudo systemctl status fxtunnel
Несколько туннелей через systemd
Если нужно пробросить несколько портов, создайте отдельный сервис для каждого:
# /etc/systemd/system/fxtunnel-ssh.service
[Unit]
Description=fxTunnel SSH tunnel
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/fxtunnel tcp 22
Restart=always
RestartSec=5
User=pi
Environment=FXTUNNEL_TOKEN=your-auth-token-here
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/fxtunnel-mqtt.service
[Unit]
Description=fxTunnel MQTT tunnel
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/fxtunnel tcp 1883
Restart=always
RestartSec=5
User=pi
Environment=FXTUNNEL_TOKEN=your-auth-token-here
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable fxtunnel-ssh fxtunnel-mqtt
sudo systemctl start fxtunnel-ssh fxtunnel-mqtt
Безопасность IoT-туннелей
IoT-устройства — частая цель атак из-за слабых паролей, устаревшего ПО и отсутствия мониторинга. Туннель шифрует трафик через TLS, но безопасность устройства — ваша ответственность.
Аутентификация и токены
Используйте токены аутентификации fxTunnel, чтобы только авторизованные клиенты могли создавать туннели:
# Указываем токен при запуске
fxtunnel tcp 22 --token=your-secure-token
# Или через переменную окружения (рекомендуется для systemd)
export FXTUNNEL_TOKEN=your-secure-token
fxtunnel tcp 22
SSH-ключи вместо паролей
Для SSH-доступа к Raspberry Pi всегда используйте ключи вместо паролей:
# На Raspberry Pi: отключаем вход по паролю
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart sshd
Файрвол на устройстве
Настройте ufw, чтобы ограничить доступ к портам:
# Устанавливаем ufw
sudo apt install ufw
# Разрешаем только SSH и необходимые порты
sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw allow 1883/tcp # MQTT
sudo ufw enable
Принцип минимального доступа
Открывайте через туннель только те порты, которые действительно нужны. Не пробрасывайте все порты устройства «на всякий случай». Закрывайте туннели к сервисам, которые не используются в данный момент.
FAQ
Как получить удалённый доступ к Raspberry Pi без статического IP?
Выполните curl -fsSL https://fxtun.dev/install.sh | bash на Pi, затем fxtunnel tcp 22. Вы получите публичный адрес вроде tunnel.fxtun.dev:41234 и сможете зайти по SSH откуда угодно. Статический IP не нужен, проброс портов на роутере – тоже.
Поддерживает ли fxTunnel ARM-архитектуру для Raspberry Pi?
Да. Go-бинарник кросс-компилируется под armv6, armv7 и arm64. Установочный скрипт сам определяет архитектуру и скачивает подходящий файл. Работает на любой модели Pi, от Zero до Pi 5.
Можно ли пробросить MQTT-брокер через туннель?
Можно – MQTT работает поверх TCP, так что fxtunnel tcp 1883 откроет ваш локальный Mosquitto наружу. После этого IoT-устройства из любой сети смогут публиковать и получать сообщения через публичный адрес туннеля.
Как сделать автозапуск туннеля при загрузке Raspberry Pi?
Создайте systemd-сервис /etc/systemd/system/fxtunnel.service с ExecStart=/usr/local/bin/fxtunnel tcp 22 и включите его через systemctl enable fxtunnel. Туннель будет подниматься при каждой загрузке и перезапускаться автоматически при сбоях.
Безопасно ли открывать IoT-устройства через туннель?
При правильной настройке – да. fxTunnel шифрует трафик через TLS, но со своей стороны стоит использовать SSH-ключи вместо паролей, настроить файрвол (ufw) и закрывать туннели к сервисам, которые сейчас не нужны. Устройства с реальными данными не стоит открывать без аутентификации.