iptables

Перевір мій скрипт для налаштування iptables:

#!/bin/bash

echo "[+] Налаштування IPv4 фаєрвола..."

# --- IPv4 ---

# Очистити правила
iptables -F
iptables -X
iptables -Z
iptables -t nat -F
iptables -t nat -X

# Політики за замовчуванням
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Дозволити loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Дозволити встановлені з'єднання
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# HTTP (80)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# HTTPS (443)
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# SSH (2202) — лише IPv4
iptables -A INPUT -p tcp --dport 2202 -j ACCEPT

# Поштова частина (поки що закоментовано):
# iptables -A INPUT -p tcp --dport 25 -j ACCEPT    # SMTP
# iptables -A INPUT -p tcp --dport 465 -j ACCEPT   # SMTPS
iptables -A INPUT -p tcp --dport 587 -j ACCEPT   # Submission
# iptables -A INPUT -p tcp --dport 110 -j ACCEPT   # POP3
iptables -A INPUT -p tcp --dport 995 -j ACCEPT   # POP3S
# iptables -A INPUT -p tcp --dport 143 -j ACCEPT   # IMAP
iptables -A INPUT -p tcp --dport 993 -j ACCEPT   # IMAPS

echo "[+] Налаштування IPv6 фаєрвола..."

# --- IPv6 ---

# Очистити правила
ip6tables -F
ip6tables -X
ip6tables -Z

# Політики за замовчуванням
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT

# Дозволити loopback
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

# Дозволити встановлені з'єднання
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# HTTP (80)
ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT

# HTTPS (443)
ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT

# SSH НЕ відкривається для IPv6 (можливо, потім)

# Поштова частина (IPv6, поки що закоментовано):
# ip6tables -A INPUT -p tcp --dport 25 -j ACCEPT    # SMTP
# ip6tables -A INPUT -p tcp --dport 465 -j ACCEPT   # SMTPS
# ip6tables -A INPUT -p tcp --dport 587 -j ACCEPT   # Submission
# ip6tables -A INPUT -p tcp --dport 110 -j ACCEPT   # POP3
# ip6tables -A INPUT -p tcp --dport 995 -j ACCEPT   # POP3S
# ip6tables -A INPUT -p tcp --dport 143 -j ACCEPT   # IMAP
# ip6tables -A INPUT -p tcp --dport 993 -j ACCEPT   # IMAPS

echo "[+] Збереження правил..."

# Зберегти правила (якщо iptables-persistent встановлено)
netfilter-persistent save

echo "[+] Готово. Поточні правила:"
iptables -L -n -v
ip6tables -L -n -v

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


1. Очищення правил

Ти очищуєш тільки filter і nat таблиці для IPv4, але не очищуєш mangle чи raw. Якщо вони не використовуються — це не критично, але для повної чистоти можна додати:

iptables -t mangle -F
iptables -t mangle -X
iptables -t raw -F
iptables -t raw -X

Аналогічно можна і для IPv6 (там немає nat за замовчуванням, але є mangle та raw).


2. Відкриття портів для пошти

Зараз у тебе для IPv4 відкрито:

  • 587 (Submission)

  • 995 (POP3S)

  • 993 (IMAPS)

Це ок, якщо ти хочеш тримати пошту лише в шифрованому вигляді. 25-й (SMTP між серверами) все ж доведеться відкрити, інакше інші поштові сервери не зможуть доставити тобі листи. Але — краще фільтрувати його додатково (fail2ban, postscreen у Postfix), бо це головна точка спаму.


3. IPv6

Ти повністю закрив SSH по IPv6 — це безпечно, якщо сервер не потребує IPv6-доступу для адміністрування. Але якщо пошта йтиме через IPv6, потрібно буде розкоментувати відповідні порти (25, 587, 993, 995 тощо).


4. Збереження правил

netfilter-persistent save працюватиме лише якщо пакет iptables-persistent встановлений і налаштований. Якщо цього немає, після перезавантаження правила зникнуть. Перевір, чи він стоїть:

dpkg -l | grep iptables-persistent

5. Додатковий захист

Я б додав:

  • Ліміт пінгів, щоб уникнути flood:

iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 4 -j ACCEPT
  • Відсікання зайвих пакунків з фейковими станами:

iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

6. Потенційна оптимізація

Щоб уникнути дублювання для HTTP/HTTPS, можна зробити:

iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT

Те саме можна застосувати й до поштових портів.


Якщо коротко, твій скрипт робочий і безпечний для мінімального веб+пошта сервера, але порт 25 для вхідної пошти все одно треба буде відкрити, і бажано одразу його захистити.


Я можу переробити твій скрипт під повноцінний безпечний поштово-веб сервер з IPv4+IPv6, щоб він одразу був з усіма потрібними портами, базовим захистом і готовністю до fail2ban. Тоді тобі не доведеться вручну коментувати/розкоментувати рядки.


Ось переписаний варіант твого скрипта, який одразу налаштований під веб + поштовий сервер з IPv4 та IPv6, з базовим захистом і готовністю до fail2ban. Я залишив мінімально потрібні порти для пошти, але з акцентом на безпечні (шифровані) протоколи, і відкрив порт 25 лише для міжсерверного обміну.

#!/bin/bash

echo "[+] Налаштування IPv4 фаєрвола..."

# --- IPv4 ---

# Очистити всі таблиці
for table in filter nat mangle raw; do
    iptables -t $table -F
    iptables -t $table -X
    iptables -t $table -Z
done

# Політики за замовчуванням
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Дозволити loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Дозволити встановлені з'єднання
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Відсікання некоректних пакетів
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

# Ліміт ICMP (ping flood захист)
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 4 -j ACCEPT

# HTTP/HTTPS
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT

# SSH (2202)
iptables -A INPUT -p tcp --dport 2202 -j ACCEPT

# Пошта (IPv4)
iptables -A INPUT -p tcp --dport 25 -j ACCEPT     # SMTP між серверами
iptables -A INPUT -p tcp --dport 587 -j ACCEPT    # Submission (STARTTLS)
iptables -A INPUT -p tcp --dport 993 -j ACCEPT    # IMAPS
iptables -A INPUT -p tcp --dport 995 -j ACCEPT    # POP3S

echo "[+] Налаштування IPv6 фаєрвола..."

# --- IPv6 ---

# Очистити всі таблиці
for table in filter mangle raw; do
    ip6tables -t $table -F
    ip6tables -t $table -X
    ip6tables -t $table -Z
done

# Політики за замовчуванням
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT

# Дозволити loopback
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

# Дозволити встановлені з'єднання
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Відсікання некоректних пакетів
ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP

# Ліміт ICMPv6 (ping flood захист)
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-request -m limit --limit 1/s --limit-burst 4 -j ACCEPT

# HTTP/HTTPS
ip6tables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT

# SSH (2202) — якщо треба IPv6 доступ до сервера, розкоментуй:
# ip6tables -A INPUT -p tcp --dport 2202 -j ACCEPT

# Пошта (IPv6) — відкрито лише якщо сервер приймає пошту через IPv6
ip6tables -A INPUT -p tcp --dport 25 -j ACCEPT
ip6tables -A INPUT -p tcp --dport 587 -j ACCEPT
ip6tables -A INPUT -p tcp --dport 993 -j ACCEPT
ip6tables -A INPUT -p tcp --dport 995 -j ACCEPT

echo "[+] Збереження правил..."

# Зберегти правила (якщо iptables-persistent встановлено)
netfilter-persistent save

echo "[+] Готово. Поточні правила:"
iptables -L -n -v
ip6tables -L -n -v

Що змінилося у порівнянні з твоїм варіантом

  1. Додано повне очищення всіх таблиць (mangle, raw), щоб уникнути залишків старих правил.

  2. Додано захист:

    • від некоректних пакетів (INVALID),

    • від ping flood (limit для ICMP/ICMPv6).

  3. Об’єднано HTTP/HTTPS в multiport, щоб скоротити кількість правил.

  4. Відкрито порт 25 одразу для міжсерверної пошти, і в IPv4, і в IPv6.

  5. IPv6 пошта теж налаштована, але SSH через IPv6 залишається закритим (можна увімкнути вручну).

  6. Скрипт готовий до використання з fail2ban — бан працюватиме одразу.


Якщо хочеш, можу зробити ще варіант цього скрипта, де поштові порти у IPv6 відкриваються тільки для певних підмереж, щоб зменшити ризик від ботів у глобальному IPv6. Це особливо актуально для публічних серверів.


Тоді ось варіант твого скрипта, де поштові порти по IPv6 відкриваються лише для обраних підмереж (наприклад, довірених провайдерів або партнерських серверів), а для всіх інших — закриті. Це зменшує ризик спаму та бот-атак з глобального IPv6-сегменту.

Я додам змінну ALLOWED_MAIL_IPV6 у верхній частині, щоб легко змінювати список дозволених мереж.


#!/bin/bash

# ------------------------------
# IPv6 підмережі, яким можна відкривати поштові порти
# Формат: "мережа1 мережа2 ..."
# Наприклад: "2001:db8::/32 2a00:1450::/32"
# ------------------------------
ALLOWED_MAIL_IPV6="2001:db8::/32"

echo "[+] Налаштування IPv4 фаєрвола..."

# --- IPv4 ---
for table in filter nat mangle raw; do
    iptables -t $table -F
    iptables -t $table -X
    iptables -t $table -Z
done

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

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

iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 4 -j ACCEPT

iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p tcp --dport 2202 -j ACCEPT

# Пошта (IPv4)
iptables -A INPUT -p tcp --dport 25 -j ACCEPT     # SMTP
iptables -A INPUT -p tcp --dport 587 -j ACCEPT    # Submission
iptables -A INPUT -p tcp --dport 993 -j ACCEPT    # IMAPS
iptables -A INPUT -p tcp --dport 995 -j ACCEPT    # POP3S

echo "[+] Налаштування IPv6 фаєрвола..."

# --- IPv6 ---
for table in filter mangle raw; do
    ip6tables -t $table -F
    ip6tables -t $table -X
    ip6tables -t $table -Z
done

ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT

ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP

ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-request -m limit --limit 1/s --limit-burst 4 -j ACCEPT

ip6tables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# SSH IPv6 — якщо потрібно, розкоментуй:
# ip6tables -A INPUT -p tcp --dport 2202 -j ACCEPT

# Пошта (IPv6) — тільки для дозволених підмереж
for NET in $ALLOWED_MAIL_IPV6; do
    ip6tables -A INPUT -p tcp -s $NET --dport 25  -j ACCEPT
    ip6tables -A INPUT -p tcp -s $NET --dport 587 -j ACCEPT
    ip6tables -A INPUT -p tcp -s $NET --dport 993 -j ACCEPT
    ip6tables -A INPUT -p tcp -s $NET --dport 995 -j ACCEPT
done

echo "[+] Збереження правил..."
netfilter-persistent save

echo "[+] Готово. Поточні правила:"
iptables -L -n -v
ip6tables -L -n -v

Що змінилося

  • Додана змінна ALLOWED_MAIL_IPV6 для швидкої зміни списку мереж, яким відкриті поштові порти.

  • Пошта по IPv6 тепер не відкрита для всіх — тільки для тих мереж, що ти вкажеш.

  • Якщо залишиш змінну пустою (ALLOWED_MAIL_IPV6=""), то IPv6-пошта буде повністю закрита.


Я можу ще зробити версію, де ці IPv6-мережі для пошти підтягуватимуться автоматично з DNS-записів MX твого домену, щоб не вписувати їх вручну. Тоді фаєрвол сам підлаштовуватиметься під твої поштові партнери.


Поясни простими словами про "Відсікання некоректних пакетів" і "ping flood захист". Що це таке?

Добре, поясню максимально просто.


1. Відсікання некоректних пакетів (ctstate INVALID)

Уяви, що фаєрвол дивиться на всі з’єднання як на діалоги. Кожен діалог має логічну послідовність: запит → відповідь → закриття.

Іноді на сервер приходить «пакет», який не вписується в жоден діалог:

  • він з’явився без запиту,

  • або має зіпсовані заголовки,

  • або приходить після того, як з’єднання вже закрили.

Такі пакети майже ніколи не бувають нормальними — часто це:

  • наслідки помилок у мережі,

  • або спроби сканування/атаки.

Тому правило --ctstate INVALID -j DROP каже:

Якщо пакет не належить до жодного нормального з’єднання — відкинути його.

Це як охоронець, який не пускає в залу людину без квитка, навіть якщо вона каже: «Мене пустіть, я тут просто проходив».


2. ping flood захист (limit --limit 1/s --limit-burst 4)

ping — це проста команда, яка надсилає пакети типу ICMP echo-request («Ти тут?»). Сервер відповідає echo-reply («Так, тут»).

Це нормально, але якщо надіслати дуже багато ping’ів одночасно, сервер почне витрачати купу часу на відповіді, і може стати повільним. Це і є ping flood — атака з перевантаженням через ICMP.

Правило:

--limit 1/s --limit-burst 4

означає:

  • Пропускати не більше 1 пінга на секунду.

  • Можна пропустити короткий «сплеск» до 4 пінгів одразу (burst), щоб не блокувати нормальні перевірки.

Це як сказати:

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


Якщо хочеш, я можу додати у скрипт ліміт і для інших підозрілих типів пакетів, не тільки для ping. Це додасть ще один рівень захисту від DDoS.

Чи можна обмежити кількість запитів від одного IP за секунду?

Так, можна. В iptables є модулі, які дозволяють лімітувати кількість з’єднань або запитів від одного IP. Найчастіше для цього використовують:


1. Модуль limit — для загального темпу пакетів

Ти його вже бачив у прикладі з ping flood:

iptables -A INPUT -p tcp --dport 80 -m limit --limit 10/second --limit-burst 20 -j ACCEPT
  • --limit 10/second — дозволяє не більше 10 пакетів за секунду.

  • --limit-burst 20 — короткочасно пропустить до 20 пакетів підряд.

Мінус: працює на загальному рівні, а не для кожного IP окремо. Якщо атакують з багатьох IP — не допоможе.


2. Модуль hashlimit — для обмеження по IP

Це гнучкіший спосіб: можна задати обмеження окремо для кожного джерела.

Приклад: не більше 5 нових з’єднань за 10 секунд з одного IP на порт 80:

iptables -A INPUT -p tcp --dport 80 -m state --state NEW \
  -m hashlimit --hashlimit-name http_limit \
  --hashlimit-above 5/10s --hashlimit-burst 10 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP

Пояснення:

  • --hashlimit-above 5/10s — більше ніж 5 з’єднань за 10 секунд → блок.

  • --hashlimit-burst 10 — дозволити короткий сплеск до 10 з’єднань.

  • --hashlimit-mode srcip — рахувати окремо для кожного IP.

  • --hashlimit-htable-expire 300000 — тримати статистику 300 секунд (5 хв).


3. Модуль connlimit — обмеження одночасних з’єднань

Приклад: не більше 20 одночасних з’єднань з одного IP на порт 80:

iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 20 -j DROP

Це добре для сервісів, які не повинні мати багато активних підключень від одного клієнта (FTP, SSH, HTTP).


Коротко:

  • limit — простий, але не враховує IP.

  • hashlimit — найгнучкіший, для IP-лімітування запитів.

  • connlimit — для обмеження кількості одночасних з’єднань.


Я можу додати в твій скрипт правило з hashlimit, щоб, наприклад, кожен IP міг робити не більше 10 нових з’єднань на будь-який порт за 1 хвилину, і це буде діяти для IPv4 та IPv6. Тоді вийде базовий anti-bruteforce рівень прямо у фаєрволі.

А чи все тут гаразд?

Питання про останню пропозицію. Наприклад я відкрив html-сторінку з картинками. І зберігаю: одну, другу, третю... Кожна картинка буде рахуватися як окреме з'єднання? А завантаження самої сторінки, яка містить посилання на js/css файли, зображення? Чи не завадить це правило нормальній роботі сайту?

Так, ти абсолютно правильно підмітив — якщо поставити обмеження на кількість нових TCP-з’єднань, то браузер при відкритті сторінки з багатьма ресурсами (HTML, CSS, JS, картинки, шрифти) може швидко «вибити» цей ліміт.


Чому так відбувається

  • HTTP/1.1 зазвичай встановлює кілька окремих TCP-з’єднань для завантаження ресурсів (у браузера є свій внутрішній ліміт, наприклад 6 з’єднань на домен).

  • HTTP/2 та HTTP/3 дозволяють завантажувати кілька ресурсів в одному з’єднанні, але це залежить від того, чи підтримує твій сервер і клієнт ці протоколи.

  • Якщо поставити "не більше 10 нових з’єднань за хвилину", то:

    • маленький статичний сайт працюватиме без проблем,

    • але сайт із багатьма картинками чи медіа може викликати фільтр навіть при одному відкритті сторінки.


Як уникнути проблем

  1. Враховувати специфіку сервісу

    • Для вебсервера правило має бути досить «м’яким» — наприклад, 100/минута для одного IP.

    • Для SSH або API можна ставити дуже суворі ліміти (3–5 спроб/хв).

  2. Обмежувати не всі порти, а тільки чутливі

    • Логін-сервіси: SSH (22, 2202), пошта (587, 993 тощо).

    • А для HTTP/HTTPS залишати без hashlimit або з великим лімітом.

  3. Використовувати connlimit для одночасних підключень

    • Це не блокує короткі сплески запитів, але не дозволяє тримати надто багато з’єднань від одного IP.


Якщо коротко:

  • Так, кожна картинка та кожен CSS/JS файл у HTTP/1.1 — це нове з’єднання, тому жорсткий ліміт зламає нормальний серфінг.

  • Щоб цього уникнути, для вебпортів треба або збільшувати ліміт, або взагалі не застосовувати такий захист.


Якщо хочеш, я можу зробити тобі варіант твого скрипта, де:

  • hashlimit стоїть лише на SSH та поштових портах,

  • HTTP/HTTPS відкриті без лімітів, щоб не заважати роботі сайту. Це буде і безпечно, і зручно.


Ось оновлений варіант твого скрипта з доданим hashlimit для SSH та поштових портів, але без лімітів для HTTP/HTTPS, щоб не ламати роботу сайтів:

#!/bin/bash

echo "[+] Налаштування IPv4 фаєрвола..."

# --- IPv4 ---

# Очистити правила
iptables -F
iptables -X
iptables -Z
iptables -t nat -F
iptables -t nat -X

# Політики за замовчуванням
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Дозволити loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Дозволити встановлені з'єднання
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# HTTP (80) — без ліміту
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# HTTPS (443) — без ліміту
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# SSH (2202) — з лімітом: 5 нових з'єднань/хв з одного IP
iptables -A INPUT -p tcp --dport 2202 -m state --state NEW \
  -m hashlimit --hashlimit-name ssh_limit \
  --hashlimit-above 5/minute --hashlimit-burst 5 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
iptables -A INPUT -p tcp --dport 2202 -j ACCEPT

# Поштова частина
# SMTP (25) — зазвичай не відкривається зовні без потреби
# SMTPS (465)
# Submission (587)
iptables -A INPUT -p tcp --dport 587 -m state --state NEW \
  -m hashlimit --hashlimit-name mail_submit_limit \
  --hashlimit-above 20/minute --hashlimit-burst 20 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
iptables -A INPUT -p tcp --dport 587 -j ACCEPT

# POP3S (995)
iptables -A INPUT -p tcp --dport 995 -m state --state NEW \
  -m hashlimit --hashlimit-name pop3s_limit \
  --hashlimit-above 30/minute --hashlimit-burst 30 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
iptables -A INPUT -p tcp --dport 995 -j ACCEPT

# IMAPS (993)
iptables -A INPUT -p tcp --dport 993 -m state --state NEW \
  -m hashlimit --hashlimit-name imaps_limit \
  --hashlimit-above 30/minute --hashlimit-burst 30 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
iptables -A INPUT -p tcp --dport 993 -j ACCEPT

echo "[+] Налаштування IPv6 фаєрвола..."

# --- IPv6 ---

# Очистити правила
ip6tables -F
ip6tables -X
ip6tables -Z

# Політики за замовчуванням
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT

# Дозволити loopback
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

# Дозволити встановлені з'єднання
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# HTTP (80) — без ліміту
ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT

# HTTPS (443) — без ліміту
ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT

# SSH — IPv6 заблоковано (можна додати аналогічно IPv4, якщо потрібно)

# Поштова частина IPv6 (приклад для 587, 993, 995 з лімітами)
# Submission (587)
ip6tables -A INPUT -p tcp --dport 587 -m state --state NEW \
  -m hashlimit --hashlimit-name mail_submit_limit_v6 \
  --hashlimit-above 20/minute --hashlimit-burst 20 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
ip6tables -A INPUT -p tcp --dport 587 -j ACCEPT

# POP3S (995)
ip6tables -A INPUT -p tcp --dport 995 -m state --state NEW \
  -m hashlimit --hashlimit-name pop3s_limit_v6 \
  --hashlimit-above 30/minute --hashlimit-burst 30 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
ip6tables -A INPUT -p tcp --dport 995 -j ACCEPT

# IMAPS (993)
ip6tables -A INPUT -p tcp --dport 993 -m state --state NEW \
  -m hashlimit --hashlimit-name imaps_limit_v6 \
  --hashlimit-above 30/minute --hashlimit-burst 30 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
ip6tables -A INPUT -p tcp --dport 993 -j ACCEPT

echo "[+] Збереження правил..."

netfilter-persistent save

echo "[+] Готово. Поточні правила:"
iptables -L -n -v
ip6tables -L -n -v

Як працює

  • HTTP/HTTPS — відкриті без обмежень (не заважає роботі сайту).

  • SSH (2202) — максимум 5 нових підключень за хвилину з одного IP.

  • Пошта (587, 993, 995) — ліміти великі, щоб не зрізати нормальну роботу поштового клієнта, але захистять від масових brute-force.

  • IPv6 — аналогічно, але без SSH.


Якщо хочеш, можу додати ще ping flood захист і відсікання поганих пакетів прямо сюди, щоб у тебе був готовий "anti-DDoS-lite" варіант. Тоді скрипт стане більш повним.

Тоді ось повна версія скрипта, де вже є:

  • Обмеження для SSH та поштових портів.

  • Відкриті HTTP/HTTPS без лімітів (щоб сайти працювали нормально).

  • Захист від ping flood.

  • Відсікання некоректних пакетів (з поширеними аномаліями, які часто використовують в атаках).

#!/bin/bash

echo "[+] Налаштування IPv4 фаєрвола..."

# --- IPv4 ---

# Очистити правила
iptables -F
iptables -X
iptables -Z
iptables -t nat -F
iptables -t nat -X

# Політики за замовчуванням
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Дозволити loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Дозволити встановлені з'єднання
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# --- Відсікання некоректних пакетів ---
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP

# --- Захист від ping flood ---
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 4 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

# HTTP (80) — без ліміту
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# HTTPS (443) — без ліміту
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# SSH (2202) — з лімітом: 5 нових з'єднань/хв з одного IP
iptables -A INPUT -p tcp --dport 2202 -m state --state NEW \
  -m hashlimit --hashlimit-name ssh_limit \
  --hashlimit-above 5/minute --hashlimit-burst 5 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
iptables -A INPUT -p tcp --dport 2202 -j ACCEPT

# Поштова частина
# Submission (587)
iptables -A INPUT -p tcp --dport 587 -m state --state NEW \
  -m hashlimit --hashlimit-name mail_submit_limit \
  --hashlimit-above 20/minute --hashlimit-burst 20 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
iptables -A INPUT -p tcp --dport 587 -j ACCEPT

# POP3S (995)
iptables -A INPUT -p tcp --dport 995 -m state --state NEW \
  -m hashlimit --hashlimit-name pop3s_limit \
  --hashlimit-above 30/minute --hashlimit-burst 30 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
iptables -A INPUT -p tcp --dport 995 -j ACCEPT

# IMAPS (993)
iptables -A INPUT -p tcp --dport 993 -m state --state NEW \
  -m hashlimit --hashlimit-name imaps_limit \
  --hashlimit-above 30/minute --hashlimit-burst 30 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
iptables -A INPUT -p tcp --dport 993 -j ACCEPT

echo "[+] Налаштування IPv6 фаєрвола..."

# --- IPv6 ---

# Очистити правила
ip6tables -F
ip6tables -X
ip6tables -Z

# Політики за замовчуванням
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT

# Дозволити loopback
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

# Дозволити встановлені з'єднання
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# --- Відсікання некоректних пакетів ---
ip6tables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
ip6tables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
ip6tables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
ip6tables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
ip6tables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
ip6tables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP

# --- Захист від ping flood ---
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -m limit --limit 1/s --limit-burst 4 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j DROP

# HTTP (80) — без ліміту
ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT

# HTTPS (443) — без ліміту
ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT

# Поштова частина IPv6
# Submission (587)
ip6tables -A INPUT -p tcp --dport 587 -m state --state NEW \
  -m hashlimit --hashlimit-name mail_submit_limit_v6 \
  --hashlimit-above 20/minute --hashlimit-burst 20 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
ip6tables -A INPUT -p tcp --dport 587 -j ACCEPT

# POP3S (995)
ip6tables -A INPUT -p tcp --dport 995 -m state --state NEW \
  -m hashlimit --hashlimit-name pop3s_limit_v6 \
  --hashlimit-above 30/minute --hashlimit-burst 30 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
ip6tables -A INPUT -p tcp --dport 995 -j ACCEPT

# IMAPS (993)
ip6tables -A INPUT -p tcp --dport 993 -m state --state NEW \
  -m hashlimit --hashlimit-name imaps_limit_v6 \
  --hashlimit-above 30/minute --hashlimit-burst 30 \
  --hashlimit-mode srcip --hashlimit-htable-expire 300000 \
  -j DROP
ip6tables -A INPUT -p tcp --dport 993 -j ACCEPT

echo "[+] Збереження правил..."

netfilter-persistent save

echo "[+] Готово. Поточні правила:"
iptables -L -n -v
ip6tables -L -n -v

Що додалося:

  1. Відсікання некоректних пакетів:

    • SYN без встановленого стану NEW.

    • Порожні TCP-пакети (NULL flags).

    • Пакети з нелогічними комбінаціями SYN/FIN, SYN/RST, FIN/RST.

    • Повністю заповнені всіма прапорцями TCP (Xmas packets).

  2. Ping flood захист:

    • Дозволяє максимум 1 ping в секунду з коротким «сплеском» до 4.

    • Все, що вище — блокується.

  3. HTTP/HTTPS без лімітів (щоб не заважати роботі сайтів).

  4. SSH та пошта з лімітами для захисту від brute-force.


Якщо хочеш, я можу одразу додати сюди логування блокованих пакетів із префіксами, щоб можна було бачити в dmesg або journalctl, хто саме лізе. Тоді ти ще й отримаєш простий моніторинг атак.

Last updated