Um conjunto de regras padrão seguro do iptables para um servidor Web HTTP (s) básico

15

Eu tenho tentado montar um script básico do iptables do servidor que funcione para a maioria dos sites executando apenas um servidor da Web básico usando HTTP (S) e SSH (portas 80, 443 e 22). Afinal, a maioria dos VPS só precisa dessas regras de portas iniciais e pode adicionar portas de correio ou de jogo posteriormente, conforme necessário.

Até agora, tenho o seguinte conjunto de regras e fiquei pensando se alguém sabe de um script melhor ou de alguma melhoria que possa ser adicionada.

*filter

#  Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

#  Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#  Allows all outbound traffic
#  You can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT

# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

#  Allows SSH connections (only 4 attempts by an IP every 3 minutes, drop the rest)
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource
-A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j DROP
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT

COMMIT

O iptables é uma das partes mais importantes da segurança de sua caixa (veja também fail2ban) e, no entanto, existem muitas pessoas como eu que têm problemas para entender tudo o que é necessário para criar um firewall básico seguro para nossos servidores.

Qual é a maneira mais segura de abrir apenas as portas básicas necessárias para um servidor da web?

Atualização: cyberciti.biz possui outro script iptables que parece muito bom.

Além disso, em vez de usar Denyhosts ou fail2ban, você pode usar o próprio iptables para bloquear tentativas repetidas incorretas de SSH .

Xeoncross
fonte
Você diz que é um VPS. Eu suponho que ele tenha um IP da LAN, certo? Você confia em todas as máquinas da sua sub-rede? Quão paranóico você quer estar aqui, pode usar a filtragem OUTPUT para proteger ainda mais sua máquina. Deixe-me saber e eu posso responder com o que eu sugiro que você use.
hobodave
Bom ponto, considerando que a maioria dos VPS está em uma VM com outras possivelmente acessíveis pela LAN, eu diria que não confiar neles seria o ponto de partida inteligente. Se você tiver um VPS adicional, poderá adicionar regras posteriormente para acessá-las (por exemplo, servidor da web no banco de dados).
Xeoncross
1
AVISO: se você executar o script cyberciti.biz mencionado e modprobenão estiver instalado (ou houver outro erro antes de abrir a porta 22), você ficará fora do servidor.
EoghanM

Respostas:

14

A maneira mais segura de trabalhar com o iptables é fechar tudo e abrir apenas o que você precisa. Estou meio distraído, por isso sempre tento ser o mais preguiçoso possível, para não cometer erros que possam levar o servidor a ficar inseguro.

Eu uso este, apenas um pouco de atribuição variável deve ser feito para que ele funcione.

  #!/bin/bash +x

  # first author: marcos de vera
  # second: joan marc riera

  ip=/sbin/iptables
  mriera="xx.xx.xx.xx"
  nsancho="yy.yy.yy.yy"
  admins="$mriera $nsancho "
  sshers=""
  mysqlrs="zz.zz.zz.zz/23"
  snmprs="uu.uu.uu.uu"
  tcpservices="80 443 22"
  udpservices=""

  # Firewall script for servername

  echo -n ">> Applying iptables rules... "

  ## flushing...
  $ip -F
  $ip -X
  $ip -Z
  $ip -t nat -F

  # default: DROP!
  $ip -P INPUT DROP
  $ip -P OUTPUT DROP
  $ip -P FORWARD DROP

  # filtering...

  # localhost: free pass!
  $ip -A INPUT -i lo -j ACCEPT
  $ip -A OUTPUT -o lo -j ACCEPT

  # administration ips: free pass!
  for admin in $admins ; do
      $ip -A INPUT -s $admin -j ACCEPT
      $ip -A OUTPUT -d $admin -j ACCEPT
  done

  # allow ssh access to sshers
  for ssher in $sshers ; do
      $ip -A INPUT -s $ssher -p tcp -m tcp --dport 22 -j ACCEPT
      $ip -A OUTPUT -d $ssher -p tcp -m tcp --sport 22 -j ACCEPT
  done

  # allow access to mysql port to iReport on sugar

  for mysql in $mysqlrs ; do
      $ip -A INPUT -s $mysql -p tcp -m tcp --dport 3306 -j ACCEPT
      $ip -A OUTPUT -d $mysql -p tcp -m tcp --sport 3306 -j ACCEPT
      $ip -A INPUT -s $mysql -p udp -m udp --dport 3306 -j ACCEPT
      $ip -A OUTPUT -d $mysql -p udp -m udp --sport 3306 -j ACCEPT
  done


  # allowed services
  for service in $tcpservices ; do
      $ip -A INPUT -p tcp -m tcp --dport $service -j ACCEPT
      $ip -A OUTPUT -p tcp -m tcp --sport $service -m state --state RELATED,ESTABLISHED -j ACCEPT
  done
  for service in $udpservices ; do
      $ip -A INPUT -p udp -m udp --dport $service -j ACCEPT
      $ip -A OUTPUT -p udp -m udp --sport $service -m state --state RELATED,ESTABLISHED -j ACCEPT
  done

  $ip -A INPUT -j LOG --log-level 4
  # VAS and VGP
  #88 tcp udp
  #389 tcp ldap queries , udp ldap ping
  #464 tcp upd kerberos
  #3268 tcp global catalog access
  for dc in ip.ip.ip.ip ; do # our dc servers for some ldap auth
      vas=88
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $vas -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $vas -j ACCEPT
      $ip -A INPUT -s $dc -p udp -m udp --dport $vas -j ACCEPT
      $ip -A OUTPUT -d $dc -p udp -m udp --dport $vas -j ACCEPT
      ldap=389
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $ldap -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $ldap -j ACCEPT
      $ip -A INPUT -s $dc -p udp -m udp --dport $ldap -j ACCEPT
      $ip -A OUTPUT -d $dc -p udp -m udp --dport $ldap -j ACCEPT
      kpasswd=464
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $kpasswd -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $kpasswd -j ACCEPT
      $ip -A INPUT -s $dc -p udp -m udp --dport $kpasswd -j ACCEPT
      $ip -A OUTPUT -d $dc -p udp -m udp --dport $kpasswd -j ACCEPT
      gca=3268
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $gca -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $gca -j ACCEPT
      vgp=445
      $ip -A INPUT -s $dc -p tcp -m tcp --dport $vgp -j ACCEPT
      $ip -A OUTPUT -d $dc -p tcp -m tcp --dport $vgp -j ACCEPT
  done


  # allow the machine to browse the internet
  $ip -A INPUT -p tcp -m tcp --sport 80 -m state --state RELATED,ESTABLISHED -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
  $ip -A INPUT -p tcp -m tcp --sport 443 -m state --state RELATED,ESTABLISHED -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT

  $ip -A INPUT -p tcp -m tcp --sport 8080 -m state --state RELATED,ESTABLISHED -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 8080 -j ACCEPT


  # don't forget the dns...
  $ip -A INPUT -p udp -m udp --sport 53 -j ACCEPT
  $ip -A OUTPUT -p udp -m udp --dport 53 -j ACCEPT
  $ip -A INPUT -p tcp -m tcp --sport 53 -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 53 -j ACCEPT

  # ... neither the ntp... (hora.rediris.es)
  #$ip -A INPUT -s 130.206.3.166 -p udp -m udp --dport 123 -j ACCEPT
  #$ip -A OUTPUT -d 130.206.3.166 -p udp -m udp --sport 123 -j ACCEPT

  $ip -A INPUT -p udp -m udp --dport 123 -j ACCEPT
  $ip -A OUTPUT -p udp -m udp --sport 123 -j ACCEPT


  # and last but not least, the snmp access
  for monitor in $snmprs ; do
      $ip -A INPUT -s $monitor -p tcp -m tcp --sport 161 -j ACCEPT   # monitoring service
      $ip -A OUTPUT -d $monitor -p tcp -m tcp --dport 161 -j ACCEPT  # monitoring service
  end
  # outgoing SMTP
  $ip -A INPUT -p tcp -m tcp --sport 25 -j ACCEPT
  $ip -A OUTPUT -p tcp -m tcp --dport 25 -j ACCEPT


  # temporary backup if we change from DROP to ACCEPT policies
  $ip -A INPUT -p tcp -m tcp --dport 1:1024 -j DROP
  $ip -A INPUT -p udp -m udp --dport 1:1024 -j DROP


  echo "OK. Check rules with iptables -L -n"

  # end :)

Eu o uso há algum tempo, e qualquer tipo de modificação será muito apreciada se facilitar a administração.

marc.riera
fonte
Existem ferramentas populares que usam SNMP (161) sobre TCP? Eu acho que essas regras devem ser UDP / 161.
Kubanczyk
1

Parece bom, mas você pode apertar um pouco mais as coisas. O sinalizador -s é o IP de origem ou o nome de domínio e você adiciona "-s 198.23.12.32" ou qualquer que seja o seu endereço IP para permitir apenas o SSH do seu IP de origem. Você também pode escolher um intervalo de IPs de origem usando a notação de estilo CIDR .

Você deve ter cuidado ao registrar chamadas negadas. O endereço IP do seu servidor será verificado por bots, scripts de crianças, etc., e o arquivo de log poderá ficar grande rapidamente. A menos que você esteja tentando diagnosticar um problema específico que você acha que pode estar relacionado a alguém tentando quebrar seu firewall, eu removeria essa opção.

Você também pode vincular o fail2ban ao iptables para um pseudo-IDS. O fail2ban verificará seus arquivos de log e poderá bloquear um IP se tentarem entrar no sistema. Por exemplo, se um determinado endereço IP falhar ao efetuar login no SSH 5 vezes, você poderá bloqueá-lo por um dia inteiro. Ele também funciona em FTP e em muitos outros (incluindo bots ruins atingindo o Apache). Eu o uso em todos os meus servidores para fornecer uma proteção extra contra ataques de força bruta.

Alan Ivey
fonte
Na verdade, eu uso o DenyHosts, pois economiza 15 MB ou mais em fail2ban. No entanto, o fail2ban é mais poderoso e funciona com muitos aplicativos (não apenas o SSH como o DenyHosts). Dado que os invasores são proibidos, ainda devo me preocupar com o rápido preenchimento dos arquivos de log? Existe uma maneira de girar os arquivos quando eles chegarem ao máximo? Se eu desativar o log do fail2ban, o Denyhosts / Fail2ban ainda terá entradas de log para verificar? Além disso, a opção de origem seria boa para algumas pessoas - mas como eu estou buscando um conjunto de regras padrão, pessoas como eu, que se movimentam muito, não podem usar essa opção.
Xeoncross
@Xeoncross: DenyHosts é uma imo de pilha fumegante. Eu o rodava em uma máquina que estava constantemente recebendo tentativas de invasão dos chineses. Durante o período de alguns meses, o /etc/hosts.deny cresceu para ter alguns milhares de IPs, momento em que fez com que o sshd esgotasse os recursos na caixa, aumentando a carga para mais de 60 em uma única máquina com CPU. Eu mudei para fail2ban e nunca olhei para trás.
hobodave
@hobodave Acabei de começar com DenyHosts, por isso vou manter essa mente como a primeira coisa a mudar quando isso se tornar um problema.
Xeoncross
1
@Xeoncross se você quiser girar o log do iptables, você pode escrever seu próprio script logrotate.d. Dê uma olhada em /etc/logrotate.d e copie outro e altere o nome do arquivo de log e ele será rotacionado com outros arquivos de log. A página do manual para logrotate explica as várias opções.
Alan Ivey
1

Dê uma olhada no Shorewall. A configuração padrão da interface única seria um bom ponto de partida. É fácil de configurar e possui macros para coisas como SSH e acesso à Web. Pode ser configurado para bloquear o servidor no nível desejado quando o firewall é desligado. Com o Shorewall-lite, você pode executar uma compilação de firewall em outro servidor. É fácil configurar o registro no nível desejado.

Para um servidor HTTP básico, você deseja abrir o acesso recebido às portas 80 e 443 se usar HTTPS. O acesso SSH de alguns endereços restritos é geralmente desejado. Você também pode bloquear o acesso de saída. Abra o firewall apenas para servidores e serviços necessários. NTP e DNS devem ser abertos, bem como um canal para buscar patches.

BillThor
fonte
1

Eu diria que esse é um firewall muito bom, exceto que ele é voltado para interromper o tráfego de entrada e não se concentra no tráfego de saída ou de saída. Em muitos casos, é tão importante se concentrar nas conexões de saída de uma caixa quanto nas de entrada. No infeliz caso em que a máquina é realmente explorada, seria bom impedir o download de kits raiz adicionais ou a conexão com nós de comando e controle, ou o que seja.

BillThor começou a falar sobre isso acima, mas estou apenas respondendo com exemplos específicos. Uma das coisas boas do iptables é que ele pode se lembrar do estado da conexão, isso pode ter implicações no desempenho em sites com tráfego intenso, mas você pode alterar seu acesso de entrada no http / https para permitir apenas respostas em conexões estabelecidas, por exemplo, ou limitar especificamente certos privilégios não privilegiados usuários de ter acesso de saída. Então, suas regras de saída teriam cláusulas RELACIONADAS, ESTABELECIDAS, que impediriam toda uma série de ataques auxiliares e retardariam os que exigem um estágio secundário para realmente explorar uma caixa, o que é muito comum.

Finalmente, eu diria que é melhor definir a política do iptables -P DROP em vez de ter um REJECT anexado no final. É principalmente uma questão de preferência, mas pode reduzir erros ao anexar a cadeias com regras existentes em vez de inserir ou liberar / reiniciar.

Matty B
fonte
Então eu deveria mudar -A INPUT -j REJECTpara -A INPUT -P DROP?
Xeoncross