1. Блог
  2. Мануали

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

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 лише з цієї адреси.

Відеоінструкція

YouTube video
#port knocking#knockd#ssh#firewall#безпека

Ця стаття іншими мовами:EnglishРусский