Поиск по сайту:

Как настроить брандмауэр 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