Как да настроите защитна стена на Iptables за защита на трафика между вашите сървъри


Въведение

Разполагането на отделни компоненти в настройката на вашето приложение върху различни възли е обичаен начин за намаляване на натоварването и започване на хоризонтално мащабиране. Типичен пример е конфигуриране на база данни на отделен сървър от вашето приложение. Въпреки че има редица предимства с тази настройка, свързването през мрежа включва нов набор от съображения за сигурност.

В това ръководство ще демонстрираме как да настроите защитна стена на всеки от вашите сървъри в разпределена настройка. Ние ще конфигурираме нашата политика, за да разрешим желания трафик между нашите компоненти, като същевременно откажем друг трафик.

Можете също така да конфигурирате облачните защитни стени на DigitalOcean, които работят като допълнителен външен слой към вашите сървъри в инфраструктурата на DigitalOcean. По този начин не е необходимо да конфигурирате защитна стена на вашите сървъри.

За демонстрацията в това ръководство ще използваме два Ubuntu 22.04 сървъра. Единият ще има уеб приложение, обслужвано с Nginx, а другият ще хоства MySQL базата данни за приложението. Въпреки че ще използваме тази настройка като пример, трябва да можете да екстраполирате използваните техники, за да отговарят на вашите собствени сървърни изисквания.

Предпоставки

За да започнете, ще трябва да имате два нови Ubuntu 22.04 сървъра. Добавете обикновен потребителски акаунт с sudo привилегии за всеки. За да направите това, следвайте нашето ръководство за начална настройка на сървъра Ubuntu 22.04.

Настройката на приложението, която ще осигурим, се основава на това ръководство. Ако искате да следвате този пример, настройте вашите сървъри за приложения и бази данни, както е посочено в този урок. В противен случай можете да използвате тази статия като обща справка.

Стъпка 1 — Настройване на защитна стена

Ще започнете с внедряване на базова конфигурация на защитната стена за всеки от вашите сървъри. Политиката, която ще прилагаме, е на първо място със сигурността. Ще блокираме почти всичко, различно от SSH трафик, и след това ще пробием дупки в защитната стена за нашето конкретно приложение.

Това ръководство следва синтаксиса на iptables. iptables се инсталира автоматично на Ubuntu 22.04 с помощта на nftables бекенд, така че не трябва да инсталирате допълнителни пакети.

Използвайки nano или любимия си текстов редактор, отворете файла /etc/iptables/rules.v4:

  1. sudo nano /etc/iptables/rules.v4

Поставете конфигурацията от ръководството за шаблон на защитната стена:

*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]

# Acceptable UDP traffic

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT

# Acceptable ICMP traffic

# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable

# Commit the changes
COMMIT

*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

Запазете и затворете файла. Ако използвате nano, натиснете Ctrl+X, за да излезете, след това, когато бъдете подканени, Y и след това Enter.

Ако прилагате това в среда на живо, все още не презареждайте правилата на вашата защитна стена. Зареждането на описания тук набор от правила незабавно ще прекъсне връзката между вашето приложение и сървъра на базата данни. Ще трябва да коригирате правилата, за да отразяват нашите оперативни нужди преди презареждане.

Стъпка 2 — Открийте портовете, които се използват от вашите услуги

За да позволите комуникация между вашите компоненти, трябва да знаете кои мрежови портове се използват. Можете да намерите правилните мрежови портове, като прегледате конфигурационните си файлове, но агностичен за приложения метод за намиране на правилните портове е просто да проверите кои услуги слушат за връзки на всяка от нашите машини.

Можете да използвате инструмента netstat, за да разберете това. Тъй като приложението ви комуникира само през IPv4, ние ще добавим аргумента -4, но можете да го премахнете, ако използвате и IPv6. Другите аргументи, от които се нуждаете, за да намерите вашите работещи услуги, са -p, -l, -u, -n и -t, които можете да предоставите като -plunt.

Тези аргументи могат да бъдат разбити по следния начин:

  • p: Показване на PID и името на програмата, към която принадлежи всеки сокет.
  • l: Показване само на слушащи сокети.
  • u: Показване на UDP трафик.
  • n: Показване на цифров изход вместо имена на услуги.
  • t: Показване на TCP трафик.

  1. sudo netstat -4plunt

На вашия уеб сървър резултатът може да изглежда така:

Output
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1058/sshd tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx

Първата маркирана колона показва IP адреса и порта, които услугата, маркирана в края на реда, слуша. Специалният адрес 0.0.0.0 означава, че въпросната услуга слуша всички налични адреси.

На вашия сървър на база данни изходът ви може да изглежда така:

  1. sudo netstat -4plunt
Output
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1097/sshd tcp 0 0 192.0.2.30:3306 0.0.0.0:* LISTEN 3112/mysqld

Можете да прочетете тези колони по абсолютно същия начин. В този пример адресът 192.0.2.30 представлява частния IP адрес на сървъра на базата данни. В предварителния урок вие сте ограничили MySQL до частния интерфейс от съображения за сигурност.

Обърнете внимание на стойностите, които намирате в тази стъпка. Това са подробностите за мрежата, които ще ви трябват, за да коригирате конфигурацията на вашата защитна стена.

На вашия уеб сървър трябва да се уверите, че следните портове са достъпни:

  • Порт 80 на всички адреси
  • Порт 22 на всички адреси (вече отчетен в правилата на защитната стена)

Вашият сървър на база данни ще трябва да гарантира, че следните портове са достъпни:

  • Порт 3306 на адрес 192.0.2.30 (или интерфейсът, свързан с него)
  • Порт 22 на всички адреси (вече отчетен в правилата на защитната стена)

Стъпка 3 — Настройте правилата на защитната стена на уеб сървъра

Сега, след като имате информацията за порта, от която се нуждаете, ще коригирате набора от правила за защитна стена на вашия уеб сървър. Отворете файла с правила във вашия редактор с sudo привилегии:

  1. sudo nano /etc/iptables/rules.v4

На уеб сървъра трябва да добавите порт 80 към вашия списък с приемлив трафик. Тъй като сървърът слуша всички налични адреси - уеб сървърите обикновено се очаква да бъдат достъпни отвсякъде - вие няма да ограничите правилото чрез интерфейс или адрес на дестинация.

Вашите уеб посетители ще използват TCP протокола за свързване. Вашата рамка вече има персонализирана верига, наречена TCP за изключения на TCP приложения. Можете да добавите порт 80 към тази верига, точно под изключението за вашия SSH порт:

*filter
. . .

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 80 -j ACCEPT

. . .

Вашият уеб сървър ще инициира връзката със сървъра на вашата база данни. Вашият изходящ трафик не е ограничен във вашата защитна стена и входящият трафик, свързан с установени връзки, е разрешен, така че не е необходимо да отваряме никакви допълнителни портове на този сървър, за да разрешим тази връзка.

Запазете и затворете файла, когато сте готови. Вашият уеб сървър вече има политика за защитна стена, която ще позволи целия легитимен трафик, докато блокира всичко останало.

Тествайте файла си с правила за синтактични грешки:

  1. sudo iptables-restore -t < /etc/iptables/rules.v4

Ако не се показват синтактични грешки, презаредете защитната стена, за да приложите новия набор от правила:

  1. sudo service iptables-persistent reload

Стъпка 4 — Коригирайте правилата на защитната стена на сървъра на бази данни

На вашия сървър на база данни трябва да разрешите достъп до порт 3306 на частния IP адрес на вашия сървър. В този случай този адрес беше 192.0.2.30. Можете да ограничите достъпа, предназначен специално за този адрес, или можете да ограничите достъпа чрез съпоставяне с интерфейса, на който е присвоен този адрес.

За да намерите мрежовия интерфейс, свързан с този адрес, изпълнете ip -4 addr show scope global:

  1. ip -4 addr show scope global
Output
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 203.0.113.5/24 brd 104.236.113.255 scope global eth0 valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 192.0.2.30/24 brd 192.0.2.255 scope global eth1 valid_lft forever preferred_lft forever

Маркираните области показват, че интерфейсът eth1 е свързан с този адрес.

След това ще коригирате правилата на защитната стена на сървъра на базата данни. Отворете файла с правила с привилегии sudo на вашия сървър на база данни:

  1. sudo nano /etc/iptables/rules.v4

Отново ще добавите правило към нашата TCP верига, за да формирате изключение за връзката между вашия уеб сървър и сървър на база данни.

За да ограничите достъпа въз основа на въпросния действителен адрес, бихте добавили правилото по следния начин:

*filter
. . .

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -d 192.0.2.30 -j ACCEPT

. . .

Ако предпочитате да разрешите изключението въз основа на интерфейса, който съдържа този адрес, можете вместо това да добавите правило, подобно на това:

*filter
. . .

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -i eth1 -j ACCEPT

. . .

Запазете и затворете файла, когато сте готови.

Проверете за синтактични грешки с тази команда:

  1. sudo iptables-restore -t < /etc/iptables/rules.v4

Когато сте готови, презаредете правилата на защитната стена:

  1. sudo service iptables-persistent reload

И двата ви сървъра вече трябва да бъдат защитени, без да се ограничава необходимия поток от данни между тях.

Заключение

Внедряването на подходяща защитна стена винаги трябва да бъде част от вашия план за внедряване, когато настройвате приложение. Въпреки че демонстрирахме тази конфигурация с помощта на два сървъра, работещи с Nginx и MySQL, демонстрираните по-горе техники са приложими независимо от вашите конкретни технологични избори.

За да научите повече за защитните стени и конкретно за iptables, разгледайте следните ръководства:

  • Как да изберете ефективна политика за защитна стена, за да защитите вашите сървъри
  • Задълбочено потапяне в Iptables и архитектурата на Netfilter
  • Как да тествате конфигурацията на вашата защитна стена с Nmap и Tcpdump