Iptables + Layer7
Este artigo tem o objetivo de apresentar a ferramenta Iptables, explicando um pouco sobre seu funcionamento e mostrando alguns exemplos da utilização deste firewall, bem como alguns de seus módulos. Em seguida detalharemos a importância, a instalação e mostraremos alguns exemplos de uso de um dos módulos existentes para o Iptables: o Layer7.
Parte 2: Utilização do Iptables
Agora que os conceitos principais já foram apresentados, vamos a alguns exemplos práticos. Lembrando que são necessários privilégios de superusuário para utilizar o Iptables.
Suponhamos que você queira bloquear qualquer pacote TCP destinado à porta 80 de sua máquina. Bastaria que fosse utilizado o seguinte comando:
# iptables -A OUTPUT -p tcp --dport 80 -j DROP
Na regra acima, adicionamos (-A) a regra à chain OUTPUT (pois é pra lá que vão os pacotes cuja origem é a máquina local). Em seguida a opção -p especifica o protocolo do pacote (tcp, udp, icmp etc. Neste caso, tcp). A opção --dport especifica a porta de destino do pacote (no caso, a porta 80). Finalmente, a opção -j indica a ação a ser tomada em relação a um pacote que atenda a essa regra (cujo protocolo seja o tcp, e a porta de destino seja a 80) quando este chega à chain especificada pela opção -A (neste caso, DROP, ou seja, descartar).
Vamos a mais um exemplo: queremos descartar qualquer pacote enviado à máquina local pela máquina de endereço 200.156.12.3, por exemplo. O comando neste caso seria:
# iptables -A INPUT -s 200.156.12.3 -j DROP
Nesta última regra adicionamos (-A) a regra à chain INPUT (pra onde vão os pacotes cujo destino é a máquina local). A opção -s especifica o endereço de origem do pacote que está sendo analisado.
Temos ainda as opções -d (que, ao contrário da opção -s, especifica o endereço IP de destino do pacote), --sport (que, ao contrário da opção --dport, especifica a porta de origem do pacote), -i que especifica a interface de entrada, por exemplo, eth0 (esta opção não pode ser utilizada na chain OUTPUT, obviamente) e -o que especifica a interface de saída, por exemplo, eth1 (esta opção não deve ser utilizada com a chain INPUT, obviamente).
A ação a ser tomada em relação a um determinado pacote também varia, mas em geral são utilizados (na tabela filter) os alvos (nome que se dá a essas ações) DROP (descartar), ACCEPT (aceitar) e REJECT (rejeitar). A diferença entre DROP e REJECT é que o alvo DROP apenas descarta o pacote, ao passo que o alvo REJECT pode retornar uma mensagem de erro qualquer.
Vamos agora adicionar regras às chains da tabela Nat. Queremos alterar o endereço de origem de qualquer pacote proveniente da rede 192.168.0.0 e que esteja saindo pela interface eth2, para o endereço 100.25.1.3. Utilizamos para isso a regra:
# iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -o eth2 -j SNAT --to 100.25.1.3
Há uma série de observações a serem feitas aqui. Primeiramente, utilizamos a opção -t para especificar a tabela Nat. Anteriormente, poderíamos ter utilizado esta opção para especificar a tabela Filter; no entanto, sempre que esta opção estiver ausente, por padrão a regra é aplicada à tabela Filter.
Em segundo lugar, o endereço IP (seja ele de origem ou destino) pode ser especificado com a máscara de rede; assim, podemos nos referir a toda uma rede, utilizando apenas uma regra. Uma terceira observação é o alvo utilizado (SNAT); isso indica que faremos "source Nat", ou seja, alteraremos o endereço de origem do pacote.
Poderíamos utilizar também o alvo DNAT ("destination nat"), para alterar o endereço de destino do pacote. Claro que, neste caso, deveríamos adicionar a regra à chain PREROUTING. Essa "associação" chain-alvo é bem lógica: se queremos alterar o endereço de origem de um pacote (SNAT), este deve ser o último passo antes do pacote ser enviado. Logo, a chain POSTROUTING é usada.
Se quisermos alterar o endereço de destino de um pacote (DNAT), este deve ser o primeiro passo a ser realizado quando o pacote chega à máquina local. Logo, usamos a chain PREROUTING. Por último, observamos que a opção --to especifica qual será o novo endereço de origem/destino.
Vamos então alterar o endereço de destino de qualquer pacote que chegar à máquina local pela interface eth0, para o endereço 192.168.156.3.
# iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 192.168.156.3
Conforme citamos na introdução, a opção de realizar roteamento vem desabilitada por padrão no kernel. Para verificarmos se a opção está ou não habilitada, podemos utilizar o comando:
# cat /proc/sys/net/ipv4/ip_forward
Se a saída for 0, esta opção está desabilitada. Se for 1, está habilitada. Para habilitar esta opção utilizamos o comando (como superusuário):
# sysctl net.ipv4.ip_forward=1
Para desabilitá-la, basta substituir o 1 por 0 no comando acima.
Para utilizarmos as chains PREROUTING, POSTROUTING E FORWARD, a opção acima deve estar habilitada.
Voltando aos exemplos do iptables, podemos listar as regras de uma determinada chain com a opção -L.
Cabe ainda uma última observação: a opção -A adiciona uma regra NO FINAL da lista de regras de uma chain. O Iptables utilizará A PRIMEIRA regra da lista que "casar" com a descrição do pacote, ignorando todas as próximas regras. Portanto, a ordem das regras em uma lista faz muita diferença. Com isso, seu sistema ficará mais eficiente se as regras mais restritivas (mais abrangentes) forem as primeiras.
O Iptables fornece opções para inserir e remover regras em qualquer posição da lista, que são facilmente encontradas no manual do Iptables. No entanto, caso você possa reiniciar o serviço de firewall, é mais prático manter um arquivo texto com sua configuração de firewall.
Assim, quando tiver que inserir uma regra um uma determinada posição, basta parar o firewall, adicionar a regra no arquivo texto e recarregar o firewall.
Existem ainda os programas iptables-save (iptables-save > <arquivo_destino>) e iptables-restore (iptables-restore < <arquivo_origem>), para gravar as regras carregadas em suas chains em um arquivo, e para carregar regras de um determinado arquivo, respectivamente. Isso é útil, pois toda vez que a máquina for reiniciada, as regras carregadas são perdidas.
Citamos ainda duas opções: a opção -F, utilizada para apagar todas as regras de uma chain e a opção -P que define a política padrão de uma chain. A política padrão diz o que deve ser feito com um pacote que não "case" com nenhuma das regras da chain. Por exemplo, para descartar todos os pacotes que não atendem nenhuma das regras da chain FORWARD, utilizamos o comando:
# iptables -P FORWARD DROP
Suponhamos que você queira bloquear qualquer pacote TCP destinado à porta 80 de sua máquina. Bastaria que fosse utilizado o seguinte comando:
# iptables -A OUTPUT -p tcp --dport 80 -j DROP
Na regra acima, adicionamos (-A) a regra à chain OUTPUT (pois é pra lá que vão os pacotes cuja origem é a máquina local). Em seguida a opção -p especifica o protocolo do pacote (tcp, udp, icmp etc. Neste caso, tcp). A opção --dport especifica a porta de destino do pacote (no caso, a porta 80). Finalmente, a opção -j indica a ação a ser tomada em relação a um pacote que atenda a essa regra (cujo protocolo seja o tcp, e a porta de destino seja a 80) quando este chega à chain especificada pela opção -A (neste caso, DROP, ou seja, descartar).
Vamos a mais um exemplo: queremos descartar qualquer pacote enviado à máquina local pela máquina de endereço 200.156.12.3, por exemplo. O comando neste caso seria:
# iptables -A INPUT -s 200.156.12.3 -j DROP
Nesta última regra adicionamos (-A) a regra à chain INPUT (pra onde vão os pacotes cujo destino é a máquina local). A opção -s especifica o endereço de origem do pacote que está sendo analisado.
Temos ainda as opções -d (que, ao contrário da opção -s, especifica o endereço IP de destino do pacote), --sport (que, ao contrário da opção --dport, especifica a porta de origem do pacote), -i que especifica a interface de entrada, por exemplo, eth0 (esta opção não pode ser utilizada na chain OUTPUT, obviamente) e -o que especifica a interface de saída, por exemplo, eth1 (esta opção não deve ser utilizada com a chain INPUT, obviamente).
A ação a ser tomada em relação a um determinado pacote também varia, mas em geral são utilizados (na tabela filter) os alvos (nome que se dá a essas ações) DROP (descartar), ACCEPT (aceitar) e REJECT (rejeitar). A diferença entre DROP e REJECT é que o alvo DROP apenas descarta o pacote, ao passo que o alvo REJECT pode retornar uma mensagem de erro qualquer.
Vamos agora adicionar regras às chains da tabela Nat. Queremos alterar o endereço de origem de qualquer pacote proveniente da rede 192.168.0.0 e que esteja saindo pela interface eth2, para o endereço 100.25.1.3. Utilizamos para isso a regra:
# iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -o eth2 -j SNAT --to 100.25.1.3
Há uma série de observações a serem feitas aqui. Primeiramente, utilizamos a opção -t para especificar a tabela Nat. Anteriormente, poderíamos ter utilizado esta opção para especificar a tabela Filter; no entanto, sempre que esta opção estiver ausente, por padrão a regra é aplicada à tabela Filter.
Em segundo lugar, o endereço IP (seja ele de origem ou destino) pode ser especificado com a máscara de rede; assim, podemos nos referir a toda uma rede, utilizando apenas uma regra. Uma terceira observação é o alvo utilizado (SNAT); isso indica que faremos "source Nat", ou seja, alteraremos o endereço de origem do pacote.
Poderíamos utilizar também o alvo DNAT ("destination nat"), para alterar o endereço de destino do pacote. Claro que, neste caso, deveríamos adicionar a regra à chain PREROUTING. Essa "associação" chain-alvo é bem lógica: se queremos alterar o endereço de origem de um pacote (SNAT), este deve ser o último passo antes do pacote ser enviado. Logo, a chain POSTROUTING é usada.
Se quisermos alterar o endereço de destino de um pacote (DNAT), este deve ser o primeiro passo a ser realizado quando o pacote chega à máquina local. Logo, usamos a chain PREROUTING. Por último, observamos que a opção --to especifica qual será o novo endereço de origem/destino.
Vamos então alterar o endereço de destino de qualquer pacote que chegar à máquina local pela interface eth0, para o endereço 192.168.156.3.
# iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 192.168.156.3
Conforme citamos na introdução, a opção de realizar roteamento vem desabilitada por padrão no kernel. Para verificarmos se a opção está ou não habilitada, podemos utilizar o comando:
# cat /proc/sys/net/ipv4/ip_forward
Se a saída for 0, esta opção está desabilitada. Se for 1, está habilitada. Para habilitar esta opção utilizamos o comando (como superusuário):
# sysctl net.ipv4.ip_forward=1
Para desabilitá-la, basta substituir o 1 por 0 no comando acima.
Para utilizarmos as chains PREROUTING, POSTROUTING E FORWARD, a opção acima deve estar habilitada.
Voltando aos exemplos do iptables, podemos listar as regras de uma determinada chain com a opção -L.
Cabe ainda uma última observação: a opção -A adiciona uma regra NO FINAL da lista de regras de uma chain. O Iptables utilizará A PRIMEIRA regra da lista que "casar" com a descrição do pacote, ignorando todas as próximas regras. Portanto, a ordem das regras em uma lista faz muita diferença. Com isso, seu sistema ficará mais eficiente se as regras mais restritivas (mais abrangentes) forem as primeiras.
O Iptables fornece opções para inserir e remover regras em qualquer posição da lista, que são facilmente encontradas no manual do Iptables. No entanto, caso você possa reiniciar o serviço de firewall, é mais prático manter um arquivo texto com sua configuração de firewall.
Assim, quando tiver que inserir uma regra um uma determinada posição, basta parar o firewall, adicionar a regra no arquivo texto e recarregar o firewall.
Existem ainda os programas iptables-save (iptables-save > <arquivo_destino>) e iptables-restore (iptables-restore < <arquivo_origem>), para gravar as regras carregadas em suas chains em um arquivo, e para carregar regras de um determinado arquivo, respectivamente. Isso é útil, pois toda vez que a máquina for reiniciada, as regras carregadas são perdidas.
Citamos ainda duas opções: a opção -F, utilizada para apagar todas as regras de uma chain e a opção -P que define a política padrão de uma chain. A política padrão diz o que deve ser feito com um pacote que não "case" com nenhuma das regras da chain. Por exemplo, para descartar todos os pacotes que não atendem nenhuma das regras da chain FORWARD, utilizamos o comando:
# iptables -P FORWARD DROP