Гайд по ограничению ssh на vps

,

Часто вижу на этом форуме советы, мол нужно перенести ssh на высокие порты, якобы это каким-то образом поможет скрыть его от пробинга цензора и других злоумышленников, и сделает ваш прокси сервер незаметнее. Это полнейшая чушь, цензор использует портскан (см. GitHub - tread-lightly/CyberOK_Skipa_ips: Это вам не балалайка, получается), найти ssh на нестандартном порте проблемой не является. Можете попробовать сами: nmap -p- IP_ВАШЕГО_VPS
Нужно закрывать сервер правилами фаервола, но многие говорят, мол нет такой возможности, т.к. домашний IP не статический, а дополнительного джамп сервера нет. Опишу способ, как можно это сделать даже с динамическим домашним адресом.

Подготовка

Прежде всего нужно настроить у себя дома динамический DNS (DDNS). Подробно разбирать не буду, этих сервисов целая куча, настраиваются элементарно, хотя бы 1-2 поддерживаются любым "домашним" роутером. Лично я долгое время использовал duckdns, пока не перешёл на cloudflare.

В конечном итоге у вас должен быть DDNS домен, который резолвит на ваш текущий домашний ip. Проверяем, если выполнить команду dig +short ВАШ_DDNS_ДОМЕН на VPS, должно вывести ваш текущий домашний IP-адрес.

Решение

Решение простое, мы создадим разрешающее правило в фаерволе vps, которое будет использовать ipset, а ipset будет постоянно обновляться IP-адресом из DDNS с помощью скрипта.

Сам скрипт:

#!/bin/bash
# Update ipset to let my dynamic IP in
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

set=whitelist
host=ВАШ_DDNS_ДОМЕН

me=$(basename "$0")

ip=$(dig +short $host)

if [ -z "$ip" ]; then
    logger -t "$me" "IP for '$host' not found"
    exit 1
fi

# make sure the set exists
ipset -exist create $set hash:ip

if ipset -q test $set $ip; then
    logger -t "$me" "IP '$ip' already in set '$set'."
else
    logger -t "$me" "Adding IP '$ip' to set '$set'."
    ipset flush $set
    ipset add $set $ip
fi

Размещаем скрипт в любом удобном месте, например в /etc/ipset-update-ddns.sh
Проверяем работу скрипта: sh /etc/ipset-update-ddns.sh
Должен был создаться ipset “whitelist” с текущим IP-адресом DDNS. Проверка: ipset list whitelist

Настроим обновление ipset в crontab:

*/5 * * * * /etc/ipset-update-ddns.sh
@reboot /etc/ipset-update-ddns.sh

И наконец добавляем разрешающее правило для ipset: (тут разрешён весь TCP, при желании можно ограничить порты)
iptables -A INPUT -p tcp -m set --match-set whitelist src -m state --state NEW -j ACCEPT

После этого можно отключить общее разрешающее правило для ssh и любые другие лишние правила. С вашего домашнего адреса теперь всегда будет открыт доступ. В качестве резервного доступа, если вдруг что-то пойдёт не так, можно использовать веб-консоль хостинга. Ещё можно прокинуть ssh внутри прокси соединения, например я прокидываю через vless-reality с socks5 инбаундом:

Host vps
        ProxyCommand  nc -X connect -x LOCAL_SOCKS5_PROXY_IP:PROXY_PORT %h %p
        Hostname IP_ВАШЕГО_VPS
        User ВАШ_VPS_USER
1 Like

Сделает менее заметным ввиду количества попыток сканирования высоких портов в 1% от общего числа скан пакетов.

Достаточно добавить в список разрешенных подсеть AS ISP.

TCP прокси будет определятся сканерами и также, как и на ssh, возможна какая-нибудь атака RCE с повышением привелегий из-за ошибок/закладок програмной реализации.

Лучше использовать тунель с запретом ответа без аутентификации (UDP с preshared key/tls-crypt или, например, для TCP udp2raw в режиме TCP raw — на сканирующие пакеты отвечать не будет, но используется симметричная криптография).

мол нужно перенести ssh на высокие порты

port-knocking можно попробовать еще настроить, на те случаи когда лазить по ssh на впс часто не нужно, для вариантов “поставил и забыл”

port-knocking нужно настроить, но только в комбинации с вышеописанным. А то можно случайно себя забанить

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

Termux, вроде бы есть возможность работать с некоторыми утилитами и без root.

Такой вопрос (возможно глупый) - будет ли работать данная схема, если IP’шник одновременно динамический и находится за CGNAT?
По идее должно, AnyDesk как-то же пробивается со своим пакетом Wake-on-Lan, ДАЖЕ когда ПК выключен (магия какая-то), но мне самому трудно сказать…

Вообще должна, ddns будет видеть внешний адрес
А вот anydesk скорее всего находит не спящий комп с anydesk в твоей сети (об этом явно сказано) или даже в сети провайдера, заранее оставив проброс по upnp и заранее его опробовав (тут уже сильно больше переменных, круто если работает)

Хм, а ведь действительно. У меня на постоянке лежит включенный старый нетбук, тоже как раз с установленным AnyDesk (на всякий случай). Не знал, что таким образом автоматически пробрасывается порт, это и вправду круто.

В таком случаее он и отправляет wake on lan)
Без какого либо проброса

Удобнее в таскер набить последовательность шелл комманд. Там можно довольно сложную логику наворотить, в т.ч. с пакетами рандомной длины, чтобы сниффером нельзя было однозначно считать последовательность.

Достаточно добавить в список разрешенных подсеть AS ISP.

Можно конечно, только правило получится сильно шире, и менее универсальное, чем мой способ, который будет просто работать даже в случае переезда или смены оператора.

Пока нет информации, способны ли они обнаружить ssh in tls или tls in tls. Скорее нет, чем да, потому что пока что их использование не вызывает сработку фильтра на хецнер. В любом случае это лучше голого ssh

Да, в теории всё возможно, но на мой взгляд вероятность этого минимальна, я оцениваю риск как допустимый. Даже в худшем случае RCE это всего-лишь прокси сервер для обхода, который можно “обнулить” через панель хостера. Все эти способы конечно использовать можно

Простите за возможно глупый вопрос, но все же. По поводу того, что в каких-то странах цензор банит серверы с открытым SSH портом - это подтвержденная информация?

Недавно писал кто-то, что ему забанили айпишник за соединение с сервером по SSH через ключ, причём при входе через пароль не блокировали. ИМХО, подключаться к серверу по SSH стоит только через сторонний VPN (к примеру WARP с AWG) либо через VNC панель хостера, так безопаснее.

либо через VNC панель хостера, так безопаснее.

+1

Как вариант еще можно перевесить ssh на onion hidden service. Я так сделал, теперь порт наружу не торчит, а задержки минимальные. И VNC (xfce) тоже.
Настраивается за 10-15 мин.

Была информация от иранских товарищей, что могут банить reality сервер после активного пробинга, если на нём открытые порты не соответствуют открытым портам на dest сервере, под который маскируешься. Собственно, отсюда и пошли рассуждения о необходимости прятать порты. Другое решение это маскировка под свой собственный сервер, тогда и прятать ничего не нужно.

А если перенаправлять все порты (кроме 443 и SSH разумеется) с помощью iptables, то это спасёт от active probing’а? К примеру вот так:

iptables -t nat -A PREROUTING -i ens3 -p tcp -m multiport ! --dports 443,1337 -j DNAT --to-destination <DONOR_IP>
iptables -t nat -A PREROUTING -i ens3 -p udp -j DNAT --to-destination <DONOR_IP>
iptables -t nat -A POSTROUTING -o ens3 -j SNAT --to-source <SERVER_IP>

Единственный правильный способ сокрытия ssh это обернуть его во что-то. Т.к могут собрать статистику через DPI

А зачем это всё? Нельзя просто доступ по паролю закрыть и оставить только по ключу?

По своему опыту, использую 3 метода для vps/vds:

  1. port knocking (+ ssh порт нестандарт, порт для открытия брать подальше)

  2. ssh вообще вырубаю, там где подключаюсь редко (включил и забыл).
    Если надо подключаюсь через саму панель (noVNC/realVNC и т.д.)

  3. ssh jump host (gateway), подключение к ssh через другую сессию ssh (ssh gateway должен быть в доверенной зоне)