Перейти к содержимому
WebShield Docs

Домашний сервер на динамическом адресе

Как держать имя домена привязанным к меняющемуся адресу дома — настройка роутеров, Linux и Windows, проксирование и что делать с SSH.

Домашний интернет выдаёт адрес на время. Перезагрузили роутер, провайдер переподключил сессию — адрес другой, и всё, что на него ссылалось, перестало отвечать. Лечится это так: устройство само сообщает нам свой текущий адрес, а мы держим запись домена в актуальном состоянии.

Понадобится: домен, делегированный на наши NS-серверы, и устройство, которое умеет хотя бы curl раз в десять минут.

  1. Личный кабинет → DNS нужного домена.
  2. Карточка Динамический IP → Добавить имя. Короткое имя, например home — получится home.example.com.
  3. Скопируйте токен. Он показывается один раз; потерянный не восстанавливается, только выпускается новый.

Имя сразу появится в общем списке записей с пометкой Динамический. До первого обновления там будет написано «адрес ещё не сообщали» — это нормально, записи в зоне пока нет.

Почти любой роутер умеет протокол dyndns2. Ищите раздел «DynDNS», «Динамический DNS» или «DDNS», выбирайте произвольный сервис — Custom, «Другой», dyndns2 — и заполняйте:

Поле Значение
Сервер / Service dyn.webshield.pro
Имя пользователя home.example.com
Пароль выпущенный токен
Имя хоста home.example.com

Если прошивка просит адрес обновления целиком:

https://dyn.webshield.pro/nic/update?hostname=home.example.com&myip=<IP>

Обязательно https — по открытому HTTP мы обновления не принимаем, иначе токен уходил бы по сети открытым текстом. Совсем старые прошивки, которые не следуют редиректу с 80-го порта, работать не будут; для них подойдёт способ с curl ниже.

Штатный клиент RouterOS привязан к своему сервису, поэтому проще запланировать запрос:

/system scheduler
add name=webshield-dyndns interval=10m on-event={
/tool fetch url="https://dyn.webshield.pro/update?token=ТОКЕН" keep-result=no
}

Пакет ddns-scripts, в /etc/config/ddns свой сервис:

config service 'webshield'
option enabled '1'
option lookup_host 'home.example.com'
option domain 'home.example.com'
option username 'home.example.com'
option password 'ТОКЕН'
option update_url 'https://[USERNAME]:[PASSWORD]@dyn.webshield.pro/nic/update?hostname=[DOMAIN]&myip=[IP]'
option use_https '1'
option ip_source 'web'
option ip_url 'https://dyn.webshield.pro/ip'
protocol=dyndns2
server=dyn.webshield.pro
ssl=yes
use=web, web=https://dyn.webshield.pro/ip
login=home.example.com
password='ТОКЕН'
home.example.com

Своего внешнего адреса машина за NAT не знает — и не надо. Не передавайте адрес вовсе, мы возьмём тот, с которого пришёл запрос:

Окно терминала
curl -fsS "https://dyn.webshield.pro/update?token=ТОКЕН"

В crontab -e:

*/10 * * * * curl -fsS "https://dyn.webshield.pro/update?token=ТОКЕН" >/dev/null

Либо systemd-таймер, если хочется журнала и запуска после пробуждения:

/etc/systemd/system/webshield-dyndns.service
[Service]
Type=oneshot
ExecStart=/usr/bin/curl -fsS "https://dyn.webshield.pro/update?token=ТОКЕН"
# /etc/systemd/system/webshield-dyndns.timer
[Timer]
OnBootSec=1min
OnUnitActiveSec=10min
Persistent=true
[Install]
WantedBy=timers.target
Окно терминала
systemctl enable --now webshield-dyndns.timer

Планировщик заданий, действие — PowerShell:

Окно терминала
Invoke-RestMethod "https://dyn.webshield.pro/update?token=ТОКЕН"

Или одной строкой из консоли с правами администратора:

schtasks /create /tn "WebShield DynDNS" /sc minute /mo 10 /tr ^
"powershell -NoProfile -WindowStyle Hidden -Command \"Invoke-RestMethod 'https://dyn.webshield.pro/update?token=ТОКЕН'\""

Зависит от того, знаете ли вы адреса.

Знаете — хватит одного запроса. Оба адреса можно передать вместе:

Окно терминала
curl -fsS -u "home.example.com:ТОКЕН" \
"https://dyn.webshield.pro/nic/update?myip=203.0.113.7,2001:db8::5"

Или раздельными параметрами — myip для IPv4, myipv6 для IPv6. Результат тот же.

Полагаетесь на автоопределение — нужны два запроса. Мы видим ровно один адрес: тот, с которого пришёл запрос. Приехали по IPv4 — узнаем только IPv4. Поэтому:

*/10 * * * * curl -fsS -4 "https://dyn.webshield.pro/update?token=ТОКЕН" >/dev/null
*/10 * * * * curl -fsS -6 "https://dyn.webshield.pro/update?token=ТОКЕН" >/dev/null

Два запроса друг другу не мешают: обновление одной семьи не трогает другую. Запрос только с IPv4 не удалит запись AAAA, и наоборот. Так что даже если IPv6 дома появляется и пропадает, последний известный адрес останется на месте.

Роутеры с двойным стеком обычно шлют обе семьи сами, одним запросом — отдельно настраивать ничего не нужно. Проверить, что видим мы:

Окно терминала
curl https://dyn.webshield.pro/ip # как придёт, так и ответим
curl -4 https://dyn.webshield.pro/ip
curl -6 https://dyn.webshield.pro/ip

Домашний адрес в публичном DNS — это приглашение: его просканируют в первые же часы. От этого есть готовое лекарство — проксирование: посетители приходят на наш edge, а мы обращаемся к вашему серверу по текущему адресу.

Что это даёт:

  • домашний адрес не виден в DNS;
  • сертификат выпускаем мы, открывать 80-й порт наружу для проверки не нужно;
  • работают WAF, фильтрация ботов, кеш и защита от DDoS;
  • переезд адреса посетитель не замечает.

Как включить:

  1. Дождитесь первого обновления — в списке DNS появится запись A с вашим адресом.
  2. Включите у неё переключатель Прокси.
  3. Раздел Хосты → параметры защиты для этого имени (см. CDN и защита).

Дальше всё продолжает работать как раньше: клиент сообщает адрес, а мы обновляем не публичную запись, а адрес, по которому ходим к вам сами. После смены адреса переключение занимает до минуты.

На самом сервере после этого можно закрыть 80 и 443 для всех, кроме наших адресов. Учтите: список наших узлов меняется, так что либо держите правило в актуальном состоянии, либо оставьте порты открытыми и проверяйте на своей стороне заголовок Host — запросы мимо нас с чужим именем хоста просто не обслуживайте.

Через проксируемое имя идёт только веб: HTTP и HTTPS на портах 80 и 443, включая WebSocket. Остальное — SSH, RDP, VPN, игровые серверы, торренты, произвольные TCP-порты — через нас не проходит. Мы обратный прокси для веба, а не туннель.

Поэтому: включили проксирование — по SSH на это имя больше не подключиться. Имя резолвится в наши адреса, а на 22-м порту у нас ничего нет.

Обойти можно двумя способами.

Отдельное имя без проксирования. Заведите второе динамическое имя, например ssh.example.com, и не включайте у него прокси. Веб живёт на проксируемом home, а ssh ведёт прямо домой. Размен честный: это имя раскрывает ваш адрес, поэтому

  • смените порт SSH со стандартного и выключите вход по паролю — только ключи;
  • поставьте fail2ban или аналог;
  • если провайдер даёт статический IPv6 — пускайте только по нему.

Веб-доступ вместо SSH. Всё, что говорит по HTTPS, спокойно живёт за проксированием: веб-терминал, панель управления сервером, Git по HTTPS, API. Если задача — «иногда зайти на домашнюю машину», веб-консоль за нашей защитой безопаснее открытого наружу SSH.

Посмотрите, что отвечает сервер обновления — ответ короткий и говорящий:

Ответ Что значит
good <адрес> адрес принят и записан
nochg <адрес> адрес тот же, менять нечего
badauth токен неверный или не передан
nohost имя не то, для которого выпущен токен, либо обновления выключены
dnserr адрес не похож на публичный
911 слишком часто, повторите позже

Ограничение — 10 смен адреса за 10 минут на имя. Повторы с тем же адресом (а перезагрузка роутера выглядит именно так) в счёт не идут, так что перезагружать устройство можно сколько угодно.

dnserr почти всегда означает, что устройство отправило свой серый адрес из локальной сети: 192.168.*, 10.* или адрес из диапазона операторского NAT. В публичном DNS от такого адреса нет пользы, поэтому мы его не принимаем. Уберите адрес из настроек клиента и дайте нам определить его самим.

Подробности протокола — на странице Динамический IP.