Як використовувати Port Knocking в Linux (і чому не слід)

Перекриття портів є методом підвищення безпеки сервера шляхом блокування портів брандмауера, навіть тих, які, як відомо, використовуються. Ці порти залишаються закритими до моменту, поки спеціальний запит з’єднання не надасть секретний “стук”, який їх відкриє.

“Таємний стук” у світ комп’ютерних мереж

Концепція “стуку” походить із часів сухого закону, коли для того, щоб увійти в підпільний заклад, потрібно було знати спеціальний стук. Перекриття портів є сучасним аналогом цього. Якщо ви бажаєте, щоб певні служби на вашому комп’ютері були доступні, але не хочете залишати брандмауер відкритим для загального доступу, ви можете використовувати цю техніку. Вона дозволяє блокувати порти для вхідних з’єднань і автоматично відкривати їх після того, як буде виконана визначена послідовність спроб з’єднання. Послідовність цих спроб і є секретним “стуком”, а інший, аналогічний “стук” – знову закриває порт.

Хоча перекриття портів може здаватися цікавим рішенням, важливо розуміти, що це приклад “безпеки через приховування”, концепція, яка має свої недоліки. Безпека системи, заснована на таємниці, працює, поки ця таємниця відома лише обмеженому колу осіб. Однак, як тільки ця таємниця стає відомою – через витік, спостереження, здогадку – безпека стає вразливою. Тому рекомендується використовувати більш надійні методи захисту сервера, такі як авторизація на основі ключа для SSH.

Загальновизнано, що надійна кібербезпека має бути багаторівневою, і перекриття портів може бути одним із таких рівнів. Чим більше шарів захисту, тим краще, проте, варто зазначити, що перекриття портів може не мати суттєвого впливу на вже добре захищену систему.

Кібербезпека є складною темою, і перекриття портів не повинно бути єдиним засобом захисту.

Встановлення `knockd` для керування портами

Для демонстрації перекриття портів, ми будемо використовувати його для керування портом 22, який є портом SSH. Ми скористаємося утилітою під назвою `knockd`. Якщо ви використовуєте дистрибутив Linux на базі Debian, наприклад Ubuntu, ви можете встановити цей пакет за допомогою команди `apt-get`.

Введіть наступне:

sudo apt-get install knockd

Скоріше за все, у вашій системі вже встановлено брандмауер iptables, але вам може знадобитися встановити пакет `iptables-persistent`. Він відповідає за автоматичне завантаження збережених правил iptables.

Для його встановлення введіть наступне:

sudo apt-get install iptables-persistent

Коли з’явиться вікно конфігурації IPV4, натисніть пробіл, щоб вибрати опцію “Так”.

Аналогічно, натисніть пробіл ще раз у вікні конфігурації IPv6, щоб прийняти опцію “Так”.

Наступною командою ми повідомимо iptables дозволити встановлені та поточні з’єднання. Після цього ми дамо команду закрити порт SSH.

Якщо хтось підключений через SSH, ми не хочемо, щоб його з’єднання було розірвано:

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Ця команда додає правило до брандмауера, яке означає:

`-A`: Додати правило в кінець таблиці правил брандмауера.
`INPUT`: Це правило стосується вхідних підключень.
`-m conntrack`: Правила брандмауера застосовуються до мережевого трафіку (пакетів), що відповідають критеріям правила. Параметр `-m` змушує iptables використовувати додаткові модулі узгодження пакетів, в даному випадку `conntrack`, який працює з можливостями ядра для відстеження мережевих з’єднань.
`–ctstate ESTABLISHED,RELATED`: Вказує тип з’єднання, до якого буде застосовуватися правило, а саме `ВСТАНОВЛЕНІ` та `ПОВ’ЯЗАНІ` з’єднання. Встановлене з’єднання – це з’єднання, яке вже встановлено. Пов’язане з’єднання – це з’єднання, створене внаслідок дії встановленого з’єднання. Наприклад, якщо хтось завантажує файл, це може відбуватися через нове підключення, ініційоване хостом.
`-j ACCEPT`: Якщо трафік відповідає правилу, він переходить до цілі `ACCEPT` в брандмауері. Іншими словами, трафік приймається та пропускається через брандмауер.

Тепер ми можемо видати команду, щоб закрити порт:

sudo iptables -A INPUT -p tcp --dport 22 -j REJECT

Ця команда додає правило до брандмауера, яке означає:

`-A`: Додати правило в кінець таблиці правил брандмауера.
`INPUT`: Це правило стосується вхідних підключень.
`-p tcp`: Це правило застосовується до трафіку, який використовує протокол керування передачею (TCP).
`–dport 22`: Це правило застосовується до TCP-трафіку, який націлений на порт 22 (порт SSH).
`-j REJECT`: Якщо трафік відповідає правилу, він переходить до цілі `REJECT` в брандмауері. Тобто трафік відхиляється і не пропускається через брандмауер.

Нам потрібно запустити демон `netfilter-persistent`, що можна зробити наступною командою:

sudo systemctl start netfilter-persistent

Ми хочемо, щоб `netfilter-persistent` виконував цикл збереження та перезавантаження, щоб він завантажував і контролював правила iptables.

Введіть наступні команди:

sudo netfilter-persistent save

sudo netfilter-persistent reload

Тепер необхідні утиліти встановлені, а порт SSH закритий (сподіваємося, без розриву чийогось з’єднання). Настав час налаштувати секретний стук.

Конфігурація `knockd`

Для налаштування `knockd` потрібно відредагувати два файли. Перший з них – файл конфігурації `knockd`:

sudo gedit /etc/knockd.conf

Відкриється редактор `gedit` з файлом конфігурації `knockd`.

Ми відредагуємо цей файл відповідно до наших потреб. Нас цікавлять розділи `openSSH` і `closeSSH`. Кожен із цих розділів містить чотири параметри:

`sequence`: Послідовність портів, до яких потрібно отримати доступ, щоб відкрити або закрити порт 22. За замовчуванням це порти 7000, 8000 і 9000 для відкриття та 9000, 8000 і 7000 для закриття. Ви можете змінити ці порти або додати більше портів до списку. У нашому випадку ми залишимо значення за замовчуванням.
`seq_timeout`: Проміжок часу, протягом якого потрібно отримати доступ до портів для ініціації їхнього відкриття або закриття.
`command`: Команда, яка надсилається до брандмауера iptables, коли ініціюється дія відкриття або закриття. Ці команди або додають правило до брандмауера (для відкриття порту), або видаляють його (для закриття).
`tcpflags`: Тип пакета, який кожен порт повинен отримати в секретній послідовності. Пакет `SYN` (синхронізація) є першим в TCP-запиті на з’єднання, що називається “тристороннє рукостискання”.

Розділ `openSSH` можна інтерпретувати як: “Потрібно зробити TCP-з’єднання до портів 7000, 8000 і 9000 – у такому порядку та протягом 5 секунд – щоб команда відкриття порту 22 була надіслана до брандмауера”.

Розділ `closeSSH` можна інтерпретувати як: “Потрібно зробити TCP-з’єднання до портів 9000, 8000 і 7000 – у такому порядку та протягом 5 секунд – щоб команда закриття порту 22 була надіслана до брандмауера”.

Правила брандмауера

Параметри `command` у розділах `openSSH` та `closeSSH` залишаються незмінними, за винятком одного параметра. Ось їхній опис:

`-A`: Додати правило в кінець списку правил брандмауера (для команди `openSSH`).
`-D`: Видалити команду зі списку правил брандмауера (для команди `closeSSH`).
`INPUT`: Це правило стосується вхідного мережевого трафіку.
`-s %IP%`: IP-адреса пристрою, який запитує підключення.
`-p`: Мережевий протокол; в даному випадку це TCP.
`–dport`: Порт призначення; у нашому прикладі це порт 22.
`-j ACCEPT`: Перехід до цільового призначення в брандмауері. Тобто дозволити пакету пройти через решту правил без будь-якої дії.

Редагування файлу конфігурації `knockd`

Зміни, які ми внесемо у файл, виділено червоним кольором нижче:

Ми збільшуємо `seq_timeout` до 15 секунд. Це достатній проміжок часу, навіть якщо хтось вручну запускає запити на з’єднання.

У розділі `openSSH` ми змінюємо параметр `-A` (додати) у команді на `-I` (вставити). Ця команда вставляє нове правило брандмауера на початок списку правил брандмауера. Якщо залишити параметр `-A`, він додасть правило в кінець списку.

Вхідний трафік перевіряється на відповідність кожному правилу брандмауера у списку зверху вниз. У нас вже є правило, яке закриває порт 22. Отже, якщо вхідний трафік спочатку перевіряється на відповідність цьому правилу, перед тим, як побачить правило, яке дозволяє трафік, підключення буде відхилено. Якщо ж трафік спочатку бачить нове правило, підключення буде дозволено.

Команда `close` видаляє правило, додане `openSSH`, зі списку правил брандмауера. Трафік SSH знову обробляється існуючим правилом “порт 22 закритий”.

Після внесення цих змін збережіть файл конфігурації.

Редагування файлу керування `knockd`

Файл керування `knockd` простіший. Проте, перед його редагуванням нам потрібно дізнатися внутрішню назву нашого мережевого з’єднання. Для цього введіть наступну команду:

ip addr

З’єднання, яке використовується для дослідження цієї статті, називається `enp0s3`. Запишіть назву свого з’єднання.

Наступна команда відкриває для редагування файл керування `knockd`:

sudo gedit /etc/default/knockd

Ось так виглядає файл `knockd` у `gedit`.

Зміни, які нам потрібно внести, виділено червоним кольором:

Ми змінили значення `START_KNOCKD=` з 0 на 1.

Ми також видалили символ `#` з початку рядка `KNOCKD_OPTS=` та замінили `eth1` на назву нашого мережевого підключення, `enp0s3`. Звичайно, якщо ваше мережеве підключення називається `eth1`, ви не будете його змінювати.

Перевірка працездатності

Настав час перевірити, чи все працює. Запустімо демон `knockd` за допомогою цієї команди:

sudo systemctl start knockd

Тепер ми перейдемо до іншого комп’ютера і спробуємо підключитися. Ми встановили інструмент `knockd` на цьому комп’ютері не тому, що хочемо налаштувати перекриття портів, а тому, що пакет `knockd` містить іншу утиліту під назвою `knock`. Ми будемо використовувати цей комп’ютер для надсилання нашої секретної послідовності.

Скористайтесь наступною командою, щоб надіслати секретну послідовність запитів на підключення до портів на хості з IP-адресою 192.168.4.24:

knock 192.168.4.24 7000 8000 9000 -d 500

Це вказує націлити комп’ютер на IP-адресу 192.168.4.24 і надіслати запити на підключення до портів 7000, 8000 і 9000, по черзі, з затримкою `-d` між ними в 500 мілісекунд.

Потім користувач під ім’ям “dave” надсилає запит SSH до 192.168.4.24:

ssh [email protected]

Його підключення приймається, він вводить свій пароль, і починається його віддалений сеанс. Його командний рядок змінюється з `[email protected]` на `[email protected]` Щоб вийти з віддаленого комп’ютера, він вводить:

exit

Його командний рядок повертається на локальний комп’ютер. Він знову використовує `knock`, і цього разу націлює порти в зворотному порядку, щоб закрити порт SSH на віддаленому комп’ютері.

knock 192.168.4.24 9000 8000 7000 -d 500

Хоча це не був продуктивний віддалений сеанс, він продемонстрував відкриття та закриття порту за допомогою перекриття портів.

Як це виглядало з іншого боку? Системний адміністратор на хості, який виконує перекриття портів, використовує наступну команду, щоб переглянути нові записи в системному журналі:

tail -f /var/log/syslog

Ви бачите три записи `openSSH`, які з’являються, коли кожен порт послідовно націлюється утилітою `knock`.
Коли виконані всі три етапи послідовності, з’являється запис “ВІДКРИТИ СЕЗАМ”.
Надсилається команда для вставки правила у список правил iptables. Це дозволяє доступ через SSH до порту 22 з конкретної IP-адреси комп’ютера, що надіслав правильний “стук” (192.168.4.23).
Користувач “dave” підключається на кілька секунд, а потім відключається.
Ви бачите три записи `closeSSH`, що з’являються, коли кожен порт послідовно націлюється утилітою `knock`. Це повідомляє хосту, що виконує перекриття портів, закрити порт 22.
Після виконання всіх трьох етапів, ми знову отримуємо повідомлення “ВІДКРИТИ СЕЗАМ”. На брандмауер надсилається команда для видалення правила. (Чому не “ЗАКРИТИ СЕЗАМ”, коли закривається порт? Хто знає?).

Тепер єдине правило в списку правил iptables щодо порту 22 – це те, яке ми ввели на початку, щоб закрити цей порт. Отже, порт 22 знову закритий.

Висновок

Перекриття портів – це своєрідний трюк, який слід використовувати з обережністю. Не використовуйте цей метод в реальних сценаріях або, якщо використовуєте, не покладайтеся на нього як на єдину форму захисту.