Port knocking: як приховати SSH-порт на сервері Linux

Port knocking — спосіб приховати службу від сторонніх. Порт SSH закритий файрволом для всіх, і сканер бачить сервер без відкритих портів керування. Щоб підключитися, клієнт спочатку «стукає» в кілька закритих портів у певному порядку — після правильної послідовності файрвол відкриває SSH лише для його IP-адреси.
Коли це має сенс
Port knocking — додатковий шар, а не основа захисту. Він корисний, коли:
- ви підключаєтеся з різних адрес і не можете обмежити SSH списком IP;
- хочеться прибрати сервер із результатів масових сканувань;
- потрібно приховати сам факт наявності служби.
Основою захисту SSH залишаються ключі замість паролів. Послідовність стуків передається у відкритому вигляді, і той, хто бачить ваш трафік, може її повторити.
Як це працює
Служба knockd стежить за вхідними пакетами на мережевому інтерфейсі. Коли з однієї адреси надходять спроби підключення до заданих портів у потрібному порядку й у відведений час, вона виконує команду — додає у файрвол правило, що дозволяє цій адресі доступ до SSH. Після спливу часу або після зворотної послідовності правило видаляється.
Крок 1. Встановлення
Ubuntu і Debian:
sudo apt update
sudo apt install knockd
AlmaLinux, Rocky Linux (пакет міститься в EPEL):
sudo dnf install epel-release
sudo dnf install knock-server
Крок 2. Підготовка файрвола
Правила нижче дозволяють уже встановлені з’єднання й закривають SSH для нових. Завдяки першому правилу ваша поточна сесія не обірветься.
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j REJECT
Збережіть правила, щоб вони відновилися після перезавантаження:
sudo apt install iptables-persistent
sudo netfilter-persistent save
Якщо ви використовуєте UFW або firewalld, не змішуйте їх із прямими правилами iptables: замість команд iptables у налаштуваннях knockd вкажіть відповідні команди свого файрвола, наприклад ufw allow from %IP% to any port 22.
Крок 3. Налаштування knockd
Дізнайтеся ім’я мережевого інтерфейсу:
ip -br a
Відкрийте файл налаштувань:
sudo nano /etc/knockd.conf
[options]
UseSyslog
Interface = eth0
[SSH]
sequence = 7341,8523,9417
seq_timeout = 10
tcpflags = syn
start_command = /usr/sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
cmd_timeout = 30
stop_command = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
sequence— послідовність портів. Придумайте власну й не використовуйте значення з прикладів в інтернеті. Можна змішувати протоколи:7341:tcp,8523:udp,9417:tcp;seq_timeout— скільки секунд дається на всю послідовність;start_command— команда після правильного стуку;%IP%замінюється адресою клієнта;cmd_timeout— через скільки секунд виконаєтьсяstop_command.
У цій схемі порт відкривається на 30 секунд. Цього достатньо, щоб підключитися: уже встановлене з’єднання й далі працюватиме завдяки правилу для ESTABLISHED, а для нових підключень порт знову закриється. Окрема закривальна послідовність не потрібна.
У Debian і Ubuntu додатково вкажіть інтерфейс і дозвольте запуск у файлі /etc/default/knockd:
START_KNOCKD=1
KNOCKD_OPTS="-i eth0"
Крок 4. Запуск
sudo systemctl enable --now knockd
sudo systemctl status knockd
Крок 5. Підключення
Встановіть клієнт на своєму комп’ютері: у Linux це той самий пакет knockd (утиліта knock), у macOS — brew install knock.
knock -d 300 203.0.113.10 7341 8523 9417
ssh root@203.0.113.10
Ключ -d 300 додає паузу 300 мс між пакетами, щоб вони точно надійшли в потрібному порядку.
Якщо клієнта knock немає, підійде nmap:
for p in 7341 8523 9417; do nmap -Pn --max-retries 0 -p $p 203.0.113.10 > /dev/null; done
У Windows послідовність можна надіслати з PowerShell:
7341,8523,9417 | ForEach-Object { Test-NetConnection 203.0.113.10 -Port $_ -WarningAction SilentlyContinue | Out-Null }
Стук і підключення однією командою
Додайте в ~/.ssh/config:
Host myserver
HostName 203.0.113.10
User root
ProxyCommand sh -c "knock -d 300 %h 7341 8523 9417; sleep 1; nc %h %p"
Тепер ssh myserver сам надішле послідовність перед підключенням.
Перевірка
З іншого комп’ютера переконайтеся, що порт закритий:
nc -vz 203.0.113.10 22
Потім надішліть послідовність і повторіть перевірку — порт має відкритися. Роботу служби видно в журналі:
sudo journalctl -u knockd -f
За правильного стуку з’являться рядки Stage 1, Stage 2, Stage 3 і OPEN SESAME.
Якщо не працює
- Порт не відкривається. Перевірте ім’я інтерфейсу в налаштуваннях і збільште паузу між стуками. Пакети могли надійти в іншому порядку.
- Стуки не доходять. Порти послідовності можуть фільтруватися вашим провайдером або мережевим файрволом хостингу.
- Команда не виконується. Перевірте шлях до
iptables:which iptables. - Ви заблокували себе. Увійдіть через консоль у панелі керування й видаліть заборонне правило:
iptables -D INPUT -p tcp --dport 22 -j REJECT.
Альтернативи
- VPN. Найнадійніший спосіб приховати керування: SSH доступний лише всередині тунелю WireGuard.
- Fail2Ban. Не приховує порт, але блокує перебір: інструкція з налаштування.
- Single Packet Authorization. Розвиток ідеї port knocking із шифруванням: замість послідовності стуків надсилається один підписаний пакет, який неможливо перехопити й повторити. Реалізація — проєкт fwknop.
На VPS із постійною адресою адміністратора простіше й надійніше дозволити SSH лише з цієї адреси.
Відеоінструкція



