Назад | Перейти на главную страницу

iptables отклоняет все, что должен принимать

Всем привет!

Я пытаюсь настроить брандмауэр своего сервера с помощью iptables (должен признать, что последний раз я использовал iptables год назад), но iptables действует вопреки тому, о чем я прошу.

Вот мой тестовый сценарий:

#!/bin/sh
IPT="/sbin/iptables"

echo -n "Loading iptables rules..."

# Flush old rules
$IPT --flush
$IPT --delete-chain

# Allow incoming and outgoing for loopback interfaces
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
# Allow incoming traffic for HTTP(S), SSH and SMTP
$IPT -A INPUT -p tcp --dport 80 -i eth0 -j ACCEPT
$IPT -A INPUT -p tcp --dport 443 -i eth0 -j ACCEPT
$IPT -A INPUT -p tcp --dport 22 -j ACCEPT
$IPT -A INPUT -p tcp --dport 25 -i eth0 -j ACCEPT
# Allow ICMP requests
$IPT -A INPUT -p icmp -i eth0 -j ACCEPT
$IPT -A OUTPUT -p icmp -o eth0 -j ACCEPT
# Allow outgoing traffic for SMTP, DNS, NTP, PgSQL, SolR, and SSH
$IPT -A OUTPUT -p tcp --dport 25 -o eth0 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 53 -o eth0 -j ACCEPT
$IPT -A OUTPUT -p udp --dport 53 -o eth0 -j ACCEPT
$IPT -A OUTPUT -p udp --dport 123 -o eth0 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 5433 -o eth0.2654 -j ACCEPT
$IPT -A OUTPUT -p udp --dport 5433 -o eth0.2654 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 8983 -o eth0.2654 -j ACCEPT
$IPT -A OUTPUT -p udp --dport 8983 -o eth0.2654 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 22 -o eth0 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 22 -o eth0.2654 -j ACCEPT
# Deny web server user outgoing connections
$IPT -A OUTPUT -o eth0 -m owner --uid-owner www-data -j DROP

# Drop everything else
$IPT -A INPUT -j DROP
$IPT -A OUTPUT -j DROP
$IPT -A FORWARD -j DROP

echo "rules loaded."
# Print rules as understood, then flush to avoid lockout
sleep 10
$IPT -L
# Flush old rules
$IPT --flush
$IPT --delete-chain

С помощью этого сценария сервер больше не отвечает ни на один запрос, кроме ping (ICMP), затем, через 10 секунд, печатает следующий текст и завершает работу:

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  100  5920 ACCEPT     all  --  lo     any     anywhere             anywhere            
    0     0 ACCEPT     tcp  --  eth0   any     anywhere             anywhere            tcp dpt:www 
    0     0 ACCEPT     tcp  --  eth0   any     anywhere             anywhere            tcp dpt:https 
    1    52 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:ssh 
    0     0 ACCEPT     tcp  --  eth0   any     anywhere             anywhere            tcp dpt:smtp 
    0     0 ACCEPT     icmp --  eth0   any     anywhere             anywhere            
    0     0 DROP       all  --  any    any     anywhere             anywhere            

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  any    any     anywhere             anywhere            

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  100  5920 ACCEPT     all  --  any    lo      anywhere             anywhere            
    0     0 ACCEPT     icmp --  any    eth0    anywhere             anywhere            
    0     0 ACCEPT     tcp  --  any    eth0    anywhere             anywhere            tcp dpt:smtp 
    0     0 ACCEPT     tcp  --  any    eth0    anywhere             anywhere            tcp dpt:domain 
    0     0 ACCEPT     udp  --  any    eth0    anywhere             anywhere            udp dpt:domain 
    0     0 ACCEPT     udp  --  any    eth0    anywhere             anywhere            udp dpt:ntp 
    0     0 ACCEPT     tcp  --  any    eth0.2654  anywhere             anywhere            tcp dpt:5433 
    0     0 ACCEPT     udp  --  any    eth0.2654  anywhere             anywhere            udp dpt:5433 
    0     0 ACCEPT     tcp  --  any    eth0.2654  anywhere             anywhere            tcp dpt:8983 
    0     0 ACCEPT     udp  --  any    eth0.2654  anywhere             anywhere            udp dpt:8983 
    0     0 ACCEPT     tcp  --  any    eth0    anywhere             anywhere            tcp dpt:ssh 
    0     0 ACCEPT     tcp  --  any    eth0.2654  anywhere             anywhere            tcp dpt:ssh 
    0     0 DROP       all  --  any    eth0    anywhere             anywhere            owner UID match www-data 
   14  2061 DROP       all  --  any    any     anywhere             anywhere            

Первый беспокоящий элемент, я заметил, что первые правила INPUT и OUTPUT - ПРИНЯТЬ все пакеты, тогда как я не просил об этом. Кроме того, я попытался установить политику INPUT и OUTPUT на DROP (используя $IPT -P INPUT DROP и $IPT -P OUTPUT DROP), но это окончательно заблокировало меня, даже после десятисекундного тайм-аута, и сервер тогда отвечает только на ICMP, что заставляет меня жестко перезагружать сервер. Тот же эффект, если я установил параметры политики в начале скрипта.

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

eth0.2654 VLAN, используемая для связи с нашим сервером PgSQL. Что касается ответов HTTP, у меня сложилось впечатление, что они используют соединение, открытое клиентом, что разрешено моим правилом. Я был неправ?

Что касается ответов HTTP, у меня создалось впечатление, что они используют соединение, открытое клиентом, что разрешено моим правилом. Я был неправ?

Да, вы ошибались. Скорее всего, вы захотите принять установленные соединения или связанные с входящими соединениями. Таким образом, можно ответить на все, что принято в правиле ввода. При использовании брандмауэра без сохранения состояния нужно явно открывать исходный порт. Поскольку IPtables отслеживает состояние, вам не нужно этого делать. Он будет отслеживать состояние подключений для вас и автоматически разрешать исходящие подключения, как вы думаете, но только если вы скажете ему об этом. Правило для этого iptables -A INPUT -p ALL -m state --state ESTABLISHED,RELATED -j ACCEPT. Поместите это в начало вашего выходного списка. Если вы хотите быть особенно агрессивным, вы можете привязать это правило к определенным портам.

Если бы вы смотрели на это без сохранения состояния, вам нужно было бы помнить, откуда приходят и куда идут пакеты. В настоящее время ваш сервер настроен, чтобы вы могли подключаться к другому компьютеру по SSH. Поскольку вы не разрешаете трафик с портом 22 в качестве источника, ваш сервер не может отвечать на входящие соединения. Опять же, правило «ESTABLISHED, RELATED» решает эту проблему, разрешая трафику отвечать на входящие соединения, как и разрешая трафик, исходящий из порта 22, но в отличие от открытия 22 на межсетевом экране без сохранения состояния, эта настройка не позволяет запускать новые соединения оттуда.

Ваш подход плохой. Вы разрешаете все входные соединения, а затем останавливаете их на выходе. Это не предотвратит DDoS-атаки. Правильный способ - остановить входные соединения и разрешить выход.

Читая ваш код, я пытался переделать. Вот как, я думаю, это должно выглядеть:

#!/bin/sh

IPT=/usr/sbin/iptables

echo "Clear firewall rules..."
$IPT -F
$IPT -Z
$IPT -t nat -F
$IPT -t nat -Z
$IPT -t mangle -F
$IPT -t mangle -Z
$IPT -X

echo "Setting firewall policy..."
$IPT -P INPUT   DROP    # Deny  all incoming connections
$IPT -P OUTPUT  ACCEPT  # Allow all outgoing connections
$IPT -P FORWARD DROP    # Deny  all forwaring

echo "Allow connections from: lo, eth0, eth0.2654"
$IPT -I INPUT -i lo   -j ACCEPT
$IPT -I INPUT -i eth0 -j ACCEPT

echo "Allow icmp requests from eth0"
$IPT -A INPUT -p icmp -i eth0 -j ACCEPT

echo "Allow traffic for HTTP(S), SSH, SMTP, DNS, NTP, PgSQL, SolR"
$IPT -A INPUT -p tcp --dport 22                 -j ACCEPT
$IPT -A INPUT -p tcp --dport 25   -i eth0       -j ACCEPT
$IPT -A INPUT -p tcp --dport 53   -i eth0       -j ACCEPT
$IPT -A INPUT -p udp --dport 53   -i eth0       -j ACCEPT
$IPT -A INPUT -p tcp --dport 80   -i eth0       -j ACCEPT
$IPT -A INPUT -p udp --dport 123  -i eth0       -j ACCEPT
$IPT -A INPUT -p tcp --dport 443  -i eth0       -j ACCEPT
$IPT -A INPUT -p tcp --dport 5433 -i eth0.2654  -j ACCEPT
$IPT -A INPUT -p udp --dport 5433 -i eth0.2654  -j ACCEPT
$IPT -A INPUT -p tcp --dport 8983 -i eth0.2654  -j ACCEPT
$IPT -A INPUT -p udp --dport 8983 -i eth0.2654  -j ACCEPT

echo "Deny web server user outgoing connections; eth0"
$IPT -A INPUT -o eth0 -m owner --uid-owner www-data -j DROP

echo "Drop everything."
$IPT -A INPUT -s 0/0 -j DROP

echo "Firewall loaded."
sleep 20
$IPT -nvL

echo "Clear firewall rules..."
$IPT -F
$IPT -Z
$IPT -t nat -F
$IPT -t nat -Z
$IPT -t mangle -F
$IPT -t mangle -Z
$IPT -X

Я не тестировал, так что имейте это в виду. Я не уверен, что "-i eth0.2654" будет работать с виртуальными интерфейсами.

Если хотите - попробуйте и дайте мне знать, работает он или нет.