Как настроить брандмауэр Iptables для защиты трафика между вашими серверами

Вступление

Развертывание отдельных компонентов в настройках вашего приложения на разных узлах - это распространенный способ уменьшить нагрузку и начать горизонтальное масштабирование. Типичным примером является настройка базы данных на отдельном сервере от вашего приложения. Несмотря на то, что у этой настройки есть множество преимуществ, подключение по сети связано с новым набором проблем безопасности.

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

Для демонстрации в этом руководстве мы будем использовать два сервера Ubuntu 14.04. Один будет иметь экземпляр WordPress, обслуживаемый Nginx, а другой будет содержать базу данных MySQL для приложения. Хотя мы будем использовать эту настройку в качестве примера, вы сможете экстраполировать используемые методы в соответствии с вашими требованиями к серверу.

Предпосылки

Для начала вам понадобятся два свежих сервера Ubuntu 14.04. Добавьте учетную запись обычного пользователя с привилегиямиsudo для каждого. Чтобы узнать, как это сделать правильно, следуйте нашимUbuntu 14.04 initial server setup guide.

Настройка приложения, которую мы будем защищать, основана наthis guide. Если вы хотите следовать, настройте серверы приложений и баз данных, как указано в этом руководстве.

Настройка базового брандмауэра

Мы начнем с реализации базовой конфигурации брандмауэра для каждого из наших серверов. Политика, которую мы будем внедрять, основывается на принципе безопасности. Мы будем блокировать почти все, кроме трафика SSH, а затем пробивать дыры в брандмауэре для нашего конкретного приложения.

Брандмауэр вthis guide обеспечивает необходимую нам базовую настройку. Установите пакетiptables-persistent и вставьте основные правила в файл/etc/iptables/rules.v4:

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]
:POSTROUTING ACCEPT [0:0]
COMMIT

Если вы реализуете это в живой средеdo not reload your firewall rules yet. Загрузка описанного здесь базового правила немедленно обрывает соединение между вашим приложением и сервером базы данных. Нам нужно будет скорректировать правила, чтобы отразить наши оперативные потребности перед перезагрузкой.

Узнайте, какие порты используются вашими службами

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

Мы можем использовать инструментnetstat, чтобы выяснить это. Поскольку наше приложение обменивается данными только по IPv4, мы добавим аргумент-4, но вы можете удалить его, если также используете IPv6. Другие аргументы, которые нам нужны, чтобы найти наши работающие службы, - это-plunt.

На вашем веб-сервере мы увидим нечто подобное:

sudo netstat -4plunt
OutputActive 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
OutputActive 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:

/etc/iptables/rules.v4

*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
Output2: eth0:  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:  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, чтобы сформировать исключение для соединения между нашим веб-сервером и сервером базы данных.

Если вы хотите ограничить доступ на основе фактического рассматриваемого адреса, вы бы добавили правило следующим образом:

/etc/iptables/rules.v4

*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

. . .

Если вы предпочитаете разрешить исключение на основе интерфейса, в котором находится этот адрес, вы можете вместо этого добавить правило, подобное этому:

/etc/iptables/rules.v4

*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, описанные выше методы применимы независимо от вашего конкретного выбора технологии.

Чтобы узнать больше о межсетевых экранах и, в частности, оiptables, ознакомьтесь со следующими руководствами:

Related