iptables rejeita tudo o que deveria aceitar

2

Todos, olá!

Estou tentando configurar o firewall do meu servidor usando o iptables (tenho que admitir que a última vez que usei o iptables foi há um ano), mas o iptables age ao contrário do que eu peço.

Aqui está o meu script de teste:

#!/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

Com este script, o servidor não passa mais para nenhuma solicitação, mas faz ping (ICMP), depois de 10 segundos, imprime o texto a seguir e sai:

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            

Primeiro elemento perturbador, notei que as primeiras regras INPUT e OUTPUT são ACEITAR todos os pacotes, enquanto eu não pedi para fazer isso. Além disso, tentei definir a política de INPUT e OUTPUT para DROP (usando $IPT -P INPUT DROP e $IPT -P OUTPUT DROP ), mas isso definitivamente me bloqueou, mesmo após o tempo limite de dez segundos, e o servidor responde apenas ao ICMP, que me forçar a reiniciar o servidor. O mesmo efeito se eu definir as configurações de política no início do script.

Eu suspeito que meu erro seja óbvio para usuários regulares do iptables, mas eu procurei a solução por horas agora, e, como sempre neste tipo de situações, a resposta só será óbvia para mim quando alguém a apontar. Por favor, qualquer benfeitor para me ajudar?

eth0.2654 é uma VLAN usada para comunicações com nosso servidor PgSQL. Com relação às respostas HTTP, fiquei com a impressão de que eles usam a conexão que o cliente abriu, o que é permitido pela minha regra. Eu estava errado?

    
por Penegal 02.03.2012 / 15:21

2 respostas

3

Concerning HTTP answers, I was under the impression that they use the connection the client opened, which is allowed by my rule. Was I wrong?

Sim, você estava errado. É mais provável que você deseje aceitar conexões estabelecidas ou relacionadas a conexões de entrada. Assim, tudo que é aceito na regra de entrada pode ser respondido. Com um firewall sem estado, seria necessário abrir a porta de origem explicitamente. Como o IPtables é stateful, você não precisa fazer isso. Ele rastreará o estado das conexões para você e permitirá automaticamente conexões de saída da maneira que você está pensando, mas somente se você disser para fazer isso. A regra para isso é iptables -A INPUT -p ALL -m state --state ESTABLISHED,RELATED -j ACCEPT . Coloque isso no topo da sua lista de saída. Se você quer ser particularmente agressivo, pode vincular essa regra a portas específicas.

Se você olhasse para isto de uma forma sem estado, você teria que lembrar de onde os pacotes estão vindo e indo. Você tem seu servidor atualmente configurado para permitir o SSH para outra máquina. Como você não permite tráfego que tenha a porta 22 como origem, seu servidor não pode responder a conexões de entrada. Novamente, a regra "ESTABELECIDO, RELACIONADO" resolve isso para permitir que o tráfego responda às conexões de entrada, permitindo o tráfego proveniente da porta 22, mas, diferentemente da abertura 22 em um firewall sem estado, essa configuração não permitirá novas conexões a partir de lá.

    
por 02.03.2012 / 17:05
0

Sua abordagem é ruim. Você está permitindo todas as conexões de entrada e, em seguida, parando-as na saída. Isso não impedirá ataques DDoS. O caminho certo é parar as conexões de entrada e permitir a saída.

Lendo o código que tentei refazer. Aqui está como eu acho que deveria ser:

#!/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

Eu não testei, então tenha isso em mente. Não tenho certeza se "-i eth0.2654" funcionaria em interfaces virtuais.

Se você quiser, experimente e deixe-me saber se funciona ou não.

    
por 02.03.2012 / 16:41