Из командировки нужно попадать на домашний сервер: поправить сайт, посмотреть журнал, перезапустить службу. Классический совет — поднять VPN. Я решил проще: только SSH, но настроенный так, чтобы открытый наружу порт не стал приглашением. Как это устроено, как проверить снаружи, не выходя из дома, и почему в первой же поездке не заработало подключение по имени.
Это девятая часть цикла «Домашняя инфраструктура».
Почему не VPN
VPN даёт доступ ко всей домашней сети, но это ещё одна служба, ещё ключи на каждом устройстве и ещё одна вещь, которая может сломаться ровно в поездке. А задача одна — попасть на сервер. SSH и так шифрует всё, умеет пробрасывать порты для веб-интерфейсов и есть на любом компьютере. К тому же UDP-туннели в чужих сетях — гостиничных, мобильных — работают нестабильно, а SSH поверх TCP проходит почти везде.
Высокий порт снаружи, 22 внутри
На сервере sshd остался на стандартном 22-м порту — дома всё работает как раньше. А роутер транслирует снаружи высокий порт на 22-й порт сервера:
/ip firewall nat add chain=dstnat in-interface-list=WAN protocol=tcp dst-port=<высокий порт> \
action=dst-nat to-addresses=192.168.88.10 to-ports=22 comment="ssh from outside"
Снаружи 22-й порт закрыт, и это убирает почти весь фоновый шум: сканеры паролей стучатся именно туда. Нестандартный порт — не защита сам по себе (полный скан портов его найдёт), но он отсекает массовый перебор, а защита — дальше. Фильтр роутера править не нужно: стандартное правило MikroTik «из WAN только то, что прошло dstnat» пропустит ровно этот порт.
Ужесточение sshd
# /etc/ssh/sshd_config.d/00-hardening.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
MaxAuthTries 3
AllowUsers <ваш пользователь>
- вход только по ключу — подобрать пароль, которого нет, невозможно;
AllowUsers— даже если на сервере появится другая учётка с ключом, войти под ней извне не выйдет. Перед включением проверьте, чтоauthorized_keysесть только у того, кого перечисляете, — иначе запрёте себя;- имя файла с
00-— чтобы он читался раньше файла установщика сPasswordAuthentication yes(в sshd побеждает первое значение).
Плюс fail2ban на sshd: три неудачи за 10 минут — бан на сутки (было пять неудач и бан на час — для сервера, куда ходит один человек с ключом, это слишком мягко).
Проверить снаружи, не выходя из дома
Проверка изнутри дома ничего не скажет: запрос на свой белый адрес из домашней сети разворачивается у провайдера и идёт не внешним путём. Даже проверка из соседнего здания на том же проводе провайдера — тот же разворот. Нужна машина в чужой сети. У меня это рабочий сервер в дата-центре:
- баннер отвечает:
SSH-2.0-OpenSSH_10.2p1— порт проброшен, sshd жив; - 22-й порт снаружи закрыт;
- три попытки входа чужой учёткой:
Permission denied (publickey), в журнале сервера —Invalid user; - четвёртая попытка — таймаут: fail2ban забанил адрес на пороге;
- счётчик правила на роутере показал пакеты от проверки — трафик шёл именно через это правило.
Бан fail2ban на хосте срабатывает по dport 22, а не по внешнему порту: трансляция на роутере происходит раньше, и до сервера пакет приходит уже на 22-й. Если когда-нибудь перенесёте sshd на другой порт — поправьте port в джейле. И бан снаружи выглядит как таймаут, а не как отказ: ответный ICMP теряется на NAT провайдера.
Поездка: по адресу работает, по имени — нет
Первые два входа из командировки прошли по ключу из агента без проблем. А потом в одной мобильной сети подключение по имени перестало работать — и SSH, и часть сайтов. Клиент падал с ошибкой 10049 (это ошибка самого Windows-клиента: «адрес недоступен», до сервера дело не доходит и бана не вызывает). По IP-адресу всё подключалось сразу.
Отсюда правила для дороги:
- в клиенте SSH держать два профиля: по имени и по адресу. В чужой сети сразу пробовать по адресу;
- включить keepalive раз в 30 секунд — мобильная сеть рвёт простаивающие соединения, и сессия «зависает» посреди работы;
- ключ держать и в агенте, и файлом — на случай, если агент не запущен на ноутбуке.
Порядок, если «не пускает»
Test-NetConnection <адрес> -Port <порт>(илиnc -vz) — открыт ли порт вообще;- подключаться по адресу, а не по имени;
- если можно попасть с другой машины —
fail2ban-client status sshd: не забанен ли ваш адрес; journalctl -u ssh | grep publickey— с каким ключом пришла попытка.
Честная цена такой схемы: второго независимого пути нет. Три неудачные попытки подряд — например, клиент перебирает не те ключи — забанят адрес гостиницы на сутки, а разбанить можно только изнутри. Поэтому IdentitiesOnly yes и конкретный ключ в профиле, а не «пробуй всё, что есть в агенте».
Нужен удалённый доступ к своему серверу?
Опишите, откуда и что нужно делать, — подскажу схему без лишних открытых портов и проверю её снаружи.
// загружаю комментарии…