Un set di regole iptables standard e sicuro per un server web HTTP (s) di base


15

Ho cercato di mettere insieme uno script iptables del server di base che funzionerà per la maggior parte dei siti che eseguono un server Web di base utilizzando HTTP (S) e SSH (porte 80, 443 e 22). Dopotutto, la maggior parte dei VPS necessita solo di queste regole per le porte iniziali e può aggiungere porte di posta o di gioco in un secondo momento.

Finora ho il seguente set di regole e mi chiedevo se qualcuno fosse a conoscenza di uno script migliore o di eventuali miglioramenti da aggiungere.

*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

iptables è una delle parti più importanti per proteggere la tua scatola (vedi anche fail2ban) eppure ci sono molte persone come me che hanno difficoltà a comprendere tutto ciò che serve per creare un firewall di base sicuro per i nostri server.

Qual è il modo più sicuro per aprire solo le porte di base necessarie per un server web?

Aggiornamento: cyberciti.biz ha un altro script iptables che sembra abbastanza buono.

Inoltre, anziché utilizzare Denyhosts o fail2ban, è possibile utilizzare iptables stesso per bloccare i ripetuti tentativi errati di SSH .


Dici che è un VPS. Presumo che abbia anche un IP LAN, giusto? Ti fidi di ogni macchina sulla tua sottorete? Quanto paranoico vuoi essere qui, puoi usare il filtro OUTPUT per proteggere ulteriormente la tua macchina. Fammi sapere e posso rispondere con quello che ti suggerirei di usare.
hobodave,

Un buon punto, dato che la maggior parte dei VPS sono in una VM con altri eventualmente accessibili dalla LAN, direi che non fidarsi di loro sarebbe il punto di partenza intelligente. Se si dispone di un VPS aggiuntivo, è possibile aggiungere regole in seguito per accedervi (ad es. Server web nel database).
Xeoncross,

1
ATTENZIONE: se esegui lo script cyberciti.biz menzionato e modprobenon è installato (o c'è qualche altro errore prima di aprire la porta 22), ti bloccherai fuori dal server.
EoghanM,

Risposte:


14

Il modo più sicuro di lavorare con iptables è chiudere tutto e aprire solo ciò di cui hai bisogno. Sono un po 'distratto, quindi cerco sempre di essere il più pigro possibile, quindi non commetto errori che possono portare il server a essere insicuro.

Uso questo, solo un po 'di assegnazione variabile deve essere fatto per farlo funzionare.

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

Lo sto usando da un po 'di tempo e qualsiasi tipo di modifica sarà molto apprezzata se semplifica la gestione.


Esistono strumenti popolari che utilizzano SNMP (161) su TCP? Penso che queste regole dovrebbero essere UDP / 161.
Kubanczyk,

1

Sembra abbastanza buono, ma potresti stringere un po 'di più le cose. Il flag -s è l'IP di origine o il nome di dominio e aggiungi "-s 198.23.12.32" o qualunque sia il tuo indirizzo IP per consentire solo SSH dal tuo IP di origine. Puoi anche scegliere un intervallo di IP di origine utilizzando la notazione di stile CIDR .

È necessario prestare attenzione quando si registrano le chiamate negate. L'indirizzo IP del tuo server verrà scansionato da bot, script kiddie, ecc. E il file di registro potrebbe ingrandirsi piuttosto rapidamente. A meno che tu non stia provando a diagnosticare un problema specifico che ritieni possa essere correlato a qualcuno che tenta di violare il firewall, rimuoverei questa opzione.

È inoltre possibile associare fail2ban a iptables per uno pseudo-IDS. fail2ban eseguirà la scansione dei file di registro e può bloccare un IP se tentano di farsi strada nel sistema. Ad esempio, se un determinato indirizzo IP non riesce ad accedere a SSH 5 volte, è possibile bloccarlo per un giorno intero. Funziona anche su FTP e molti altri (compresi i bot dannosi che colpiscono Apache). Lo uso su tutti i miei server per fornire un ulteriore cuscinetto dagli attacchi di forza bruta.


In realtà utilizzo DenyHosts poiché consente di risparmiare circa 15 MB su fail2ban. Tuttavia, fail2ban è più potente e funziona con molte applicazioni (non solo SSH come DenyHosts). Dato che gli aggressori sono vietati, dovrei ancora preoccuparmi che i file di registro si riempiano velocemente? C'è un modo per ruotare i file quando diventano pieni? Se disabilito l'accesso in fail2ban Denyhosts / Fail2ban avrà ancora voci di registro da sottoporre a scansione? Inoltre, l'opzione sorgente sarebbe buona per alcune persone, ma dal momento che sto puntando a un set di regole predefinito le persone come me che si muovono molto non possono usare quell'opzione.
Xeoncross,

@Xeoncross: DenyHosts è una pila fumante. L'ho fatto funzionare su una macchina che riceveva costantemente tentativi di intrusione dai cinesi. Nel corso di alcuni mesi /etc/hosts.deny è cresciuto con qualche migliaio di IP, a quel punto ha causato a sshd di esaurire le risorse sulla scatola, aumentando il carico fino a 60+ su una singola macchina CPU. Sono passato a fail2ban e non ho mai guardato indietro.
hobodave,

@hobodave Ho appena iniziato con DenyHosts, quindi terrò questa mente come la prima cosa da cambiare quando questo diventa un problema.
Xeoncross,

1
@Xeoncross se si desidera ruotare il registro iptables, è possibile scrivere il proprio script logrotate.d per esso. Dai un'occhiata a /etc/logrotate.d e copia un altro e modifica il nome del file di registro e verrà ruotato con altri file di registro. La pagina man di logrotate spiega le varie opzioni.
Alan Ivey,

1

Dai un'occhiata a Shorewall. La configurazione predefinita della singola interfaccia sarebbe un buon punto di partenza. È facile da configurare e ha macro per cose come SSH e l'accesso al Web. Può essere configurato per bloccare il server al livello desiderato all'arresto del firewall. Con Shorewall-lite, puoi eseguire una build firewall su un altro server. La registrazione è facile da configurare al livello desiderato.

Per un server HTTP di base si desidera aprire l'accesso in entrata alla porta 80 e alla porta 443 se si utilizza HTTPS. L'accesso SSH in entrata da pochi indirizzi riservati è generalmente desiderato. Potresti voler bloccare anche l'accesso in uscita. Aprire il firewall solo ai server e ai servizi richiesti. È necessario aprire NTP e DNS, nonché un canale per recuperare le patch.


1

Direi che questo è un firewall abbastanza buono, tranne per il fatto che è orientato all'arresto del traffico in entrata e non focalizzato sul traffico in uscita o in uscita. In molti casi è altrettanto importante concentrarsi sulle connessioni in uscita da una scatola come quelle in entrata. Nel malaugurato caso in cui la macchina venga effettivamente sfruttata, sarebbe bello essere in grado di impedire il download di kit root aggiuntivi o la connessione a nodi di comando e controllo, o altro.

BillThor ha iniziato a parlarne sopra, ma sto solo rispondendo con esempi specifici. Una delle cose belle di iptables è che può ricordare lo stato della connessione, questo può avere conseguenze sulle prestazioni su siti pesantemente trafficati, ma è possibile modificare l'accesso in entrata su http / https per consentire solo la risposta su connessioni stabilite, ad esempio, o limitare in modo specifico alcuni non privilegiati gli utenti non hanno affatto accesso in uscita. Quindi le tue regole in uscita avrebbero clausole CORRELATE, STABILITE che impedirebbero una serie di attacchi ausiliari e rallenterebbero quelli che richiedono uno stadio secondario per sfruttare effettivamente un box, il che è molto comune.

Infine, direi che è meglio impostare la politica di iptables -P DROP piuttosto che avere un REJECT aggiunto alla fine. È principalmente una questione di preferenza, ma può ridurre gli errori quando si aggiunge a catene con regole esistenti invece di inserire o svuotare / ripristinare.


Quindi dovrei passare -A INPUT -j REJECTa -A INPUT -P DROP?
Xeoncross
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.