Развертывание дискретных компонентов в настройках приложения на разных нодах является распространенным способом уменьшения нагрузки и горизонтального масштабирования сервера. Типичный пример такой конфигурации – настройка базы данных на отдельном сервере. У такой настойки большое количество преимуществ, но подключение серверов по сети влечёт за собой ряд проблем безопасности.
В этом руководстве показано, как создать простой брандмауэр на каждом из серверов распределенной установки. Это позволяет настроить политику для разрешения трафика между компонентами установки и запрещения другого трафика.
Для демонстрации примеров используется два сервера Ubuntu 14.04; на одном из них установлены WordPress и Nginx, а на другом СУБД MySQL. Используйте эти примеры, чтобы настроить свои серверы, учитывая их индивидуальные потребности.
Требования
Для начала нужно выполнить предварительную настройку двух свежих серверов Ubuntu 14.04. Создайте аккаунт пользователя с правами sudo на каждом сервере. Подробные инструкции можно получить в этой статье.
Базовая настройка фаервола
Сначала нужно определить базовые конфигурации брандмауэра для каждого сервера. Для этого рекомендуется заблокировать весь трафик, кроме SSH-трафика, а затем открыть нужные порты в брандмауэре.
Установите пакет iptables-persistent:
sudo apt-get update
sudo apt-get install iptables-persistent
sudo nano /etc/iptables/rules.v4
Вставьте базовые правила в файл /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]
:POSTRUTING ACCEPT [0:0]
COMMIT
Внимание! При использовании этого кода в реальной среде разработки пока что не нужно перезагружать правила брандмауэра. Активация этого базового набора правил сразу прервёт соединение между сервером приложения и сервером базы данных. Сначала нужно отладить правила.
Открытие портов сервисов
Чтобы добавить исключения в правила фаервола и обеспечить взаимодействие между серверами, нужно узнать, какие сетевые порты используются для этого.
Номера сетевых портов можно узнать в конфигурационных файлах; но есть и метод, независимый от приложения: нужно просто проверить, какие сервисы прослушивают подключения на каждом сервере.
Для этого можно использовать инструмент netstat. Поскольку приложение работает только по IPv4, используйте аргумент -4.
Примечание: Если приложение работает по IPv6, не используйте этот аргумент.
Также для поиска сервисов понадобится аргумент –plunt.
На веб-сервере можно увидеть следующее:
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. значит, что запрашиваемый сервис прослушивает все доступные адреса.
На сервере БД появится:
sudo netstat -4plunt
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 для всех адресов (уже учтено правилами фаервола).
Отладка правил фаервола
Итак, теперь вы знаете, какие порты должны быть открыты. Приступайте к редактированию правил фаервола. Откройте файл, хранящий правила, в редакторе с правами sudo:
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
. . .
Веб-сервер инициирует соединение с сервером базы данных. Теперь брандмауэр не ограничивает исходящий трафик и входящий трафик, связанный с взаимодействующими серверами; таким образом, теперь не нужно открывать дополнительные порты на этом сервере, чтобы разрешить это соединение.
Сохраните и закройте файл. Теперь веб-сервер защищён политикой фаервола, которая блокирует любой трафик, неразрешённый правилами.
Проверьте синтаксис на наличие ошибок:
sudo iptables-restore -t < /etc/iptables/rules.v4
Если ошибок не обнаружено, перезапустите фаервол, чтобы активировать новый набор правил.
sudo service iptables-persistent reload
Редактирование правил на сервере БД
На сервере БД нужно открыть порт 3306 для внутреннего IP-адреса сервера. В данном случае это 192.0.2.30. Можно ограничить трафик, предназначенный для этого адреса, индивидуально или через интерфейс, которому присвоен этот адрес.
Чтобы найти сетевой интерфейс, связанный с этим адресом, введите:
ip -4 addr show scope global
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:
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
. . .
Сохраните и закройте файл.
Проверьте синтаксис на ошибки:
sudo iptables-restore -t < /etc/iptables/rules.v4
Если ошибок в синтаксисе нет, перезапустите правила фаервола:
sudo service iptables-persistent reload
Теперь оба сервера защищены от вредоносного трафика, но при этом могут обмениваться важными данными и взаимодействовать.
Заключение
Надёжный брандмауэр – неотъемлемая часть развертывания приложения. В данном руководстве конфигурация включает в себя два сервера, – для Nginx и для MySQL, – при помощи которых работает приложение WordPress; однако этот метод работает вне зависимости от выбора программного обеспечения.