Ein sicherer Standard-Iptables-Regelsatz für einen grundlegenden HTTP-Webserver

15

Ich habe versucht, ein grundlegendes Server-Skript für iptables zusammenzustellen, das für die meisten Sites funktioniert, auf denen nur ein grundlegender Webserver mit HTTP (S) und SSH (Ports 80, 443 und 22) ausgeführt wird. Schließlich benötigen die meisten VPS nur diese Regeln für Startports und können Mail- oder Game-Ports später nach Bedarf hinzufügen.

Bisher habe ich den folgenden Regelsatz und ich habe mich gefragt, ob jemand ein besseres Skript oder Verbesserungen kennt, die hinzugefügt werden könnten.

*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 ist einer der wichtigsten Teile beim Sichern Ihrer Box (siehe auch fail2ban), und dennoch haben viele Leute wie ich Probleme, alles zu verstehen, was dazu beiträgt, eine sichere Basis-Firewall für unsere Server zu erstellen.

Was ist der sicherste Weg, um nur die grundlegenden Ports zu öffnen, die für einen Webserver benötigt werden?

Update: cyberciti.biz hat ein weiteres iptables-Skript , das ziemlich gut aussieht.

Anstatt Denyhosts oder fail2ban zu verwenden, können Sie auch iptables selbst verwenden, um wiederholte Versuche mit SSH zu blockieren .

Xeoncross
quelle
Sie sagen, es ist ein VPS. Ich nehme an, es hat auch eine LAN-IP, oder? Vertrauen Sie jedem Computer in Ihrem Subnetz? Wie paranoid Sie hier sein möchten, können Sie mit der OUTPUT-Filterung Ihre Maschine weiter schützen. Lassen Sie es mich wissen und ich kann mit dem antworten, was ich Ihnen empfehlen würde.
Hobodave
Ein guter Punkt, da sich die meisten VPS in einer VM befinden, auf die möglicherweise über LAN zugegriffen werden kann. Ich würde sagen, dass das Nichtvertrauen der intelligente Ausgangspunkt wäre. Wenn Sie zusätzliche VPS haben, können Sie später Regeln hinzufügen, um darauf zuzugreifen (dh Webserver zur Datenbank).
Xeoncross,
1
WARNUNG: Wenn Sie das erwähnte cyberciti.biz-Skript ausführen und modprobees nicht installiert ist (oder ein anderer Fehler auftritt, bevor Sie Port 22 öffnen), sperren Sie sich selbst aus dem Server aus.
EoghanM

Antworten:

14

Die sicherste Art, mit iptables zu arbeiten, ist, alles zu schließen und nur das zu öffnen, was Sie benötigen. Ich bin irgendwie abgelenkt, also versuche ich immer, so faul wie möglich zu sein, damit ich keine Fehler mache, die dazu führen können, dass der Server unsicher wird.

Ich benutze dieses, es muss nur ein bisschen eine variable Zuweisung gemacht werden, damit es funktioniert.

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

Ich benutze es seit einiger Zeit, und jede Art von Änderung wird sehr geschätzt, wenn es die Verwaltung erleichtert.

marc.riera
quelle
Können beliebte Tools, die SNMP (161) über TCP verwenden? Ich denke, diese Regeln sollten UDP / 161 sein.
Kubanczyk
1

Das sieht ganz gut aus, aber man könnte es ein bisschen enger machen. Das Flag -s ist die Quell-IP oder der Domain-Name, und Sie fügen "-s 198.23.12.32" hinzu, oder wie auch immer Ihre IP-Adresse lautet, um nur SSH von Ihrer Quell-IP zuzulassen. Sie können auch einen Bereich von Quell-IPs mithilfe der CIDR- Notation auswählen .

Sie sollten vorsichtig sein, wenn Sie abgelehnte Anrufe protokollieren. Die IP-Adresse Ihres Servers wird von Bots, Script-Kiddies usw. gescannt, und die Protokolldatei kann ziemlich schnell groß werden. Sofern Sie nicht versuchen, ein bestimmtes Problem zu diagnostizieren, von dem Sie glauben, dass es mit jemandem zusammenhängt, der versucht, Ihre Firewall zu beschädigen, würde ich diese Option entfernen.

Sie können für ein Pseudo-IDS auch fail2ban mit iptables verknüpfen. fail2ban scannt Ihre Protokolldateien und kann eine IP-Adresse blockieren, wenn diese versucht, sich in Ihr System zu drängen. Wenn sich eine bestimmte IP-Adresse beispielsweise fünfmal nicht bei SSH anmeldet, können Sie sie für einen ganzen Tag sperren. Es funktioniert auch mit FTP und vielen anderen (einschließlich Bots, die Apache treffen). Ich verwende es auf allen meinen Servern, um ein bisschen mehr Schutz vor Brute-Force-Angriffen zu bieten.

Alan Ivey
quelle
Ich benutze eigentlich DenyHosts, da es 15 MB oder so über fail2ban spart. Allerdings ist fail2ban leistungsfähiger und funktioniert mit vielen Anwendungen (nicht nur mit SSH wie DenyHosts). Sollte ich mir angesichts der Tatsache, dass Angreifer gesperrt sind, noch Sorgen machen, dass die Protokolldateien zu schnell gefüllt werden? Gibt es eine Möglichkeit, Dateien zu drehen, wenn sie voll sind? Wenn ich die Anmeldung bei fail2ban deaktiviere, müssen bei Denyhosts / Fail2ban noch Protokolleinträge gescannt werden? Auch die Quelloption wäre für einige Leute gut - aber da ich auf einen Standardregelsatz abziele, können Leute wie ich, die sich viel bewegen, diese Option nicht verwenden.
Xeoncross
@Xeoncross: DenyHosts ist ein dampfender Haufen imo. Ich hatte es auf einer Maschine laufen, die ständig Eindringversuche von den Chinesen bekam. Innerhalb weniger Monate wuchs /etc/hosts.deny auf einige Tausend IPs an. Zu diesem Zeitpunkt war sshd in der Lage, Ressourcen auf der Box zu verbrauchen und die Last auf einem einzelnen CPU-Rechner auf über 60 zu erhöhen. Ich bin auf fail2ban umgestiegen und habe nie zurückgeschaut.
Hobodave
@hobodave Ich habe gerade mit DenyHosts angefangen, daher werde ich diese Einstellung als erstes ändern, wenn dies zu einem Problem wird.
Xeoncross,
1
@Xeoncross Wenn Sie das iptables-Protokoll drehen möchten, können Sie Ihr eigenes logrotate.d-Skript dafür schreiben. Schauen Sie sich /etc/logrotate.d an, kopieren Sie eine andere Datei und ändern Sie den Namen der Protokolldatei. Die Datei wird dann mit anderen Protokolldateien gedreht. Die Manpage für logrotate erklärt die verschiedenen Optionen.
Alan Ivey
1

Schauen Sie sich Shorewall an. Die Standardkonfiguration für eine einzelne Schnittstelle wäre ein guter Ausgangspunkt. Es ist einfach zu konfigurieren und verfügt über Makros für Dinge wie SSH und Webzugriff. Es kann so konfiguriert werden, dass der Server beim Herunterfahren der Firewall auf die gewünschte Stufe gesperrt wird. Mit Shorewall-lite können Sie einen Firewall-Build auf einem anderen Server ausführen. Die Protokollierung kann einfach auf die gewünschte Ebene konfiguriert werden.

Für einen einfachen HTTP-Server möchten Sie den eingehenden Zugriff auf Port 80 und Port 443 öffnen, wenn Sie HTTPS verwenden. Ein SSH-eingehender Zugriff von wenigen eingeschränkten Adressen ist normalerweise erwünscht. Möglicherweise möchten Sie auch den ausgehenden Zugriff sperren. Öffnen Sie die Firewall nur für die erforderlichen Server und Dienste. Es sollten NTP und DNS sowie ein Kanal zum Abrufen von Patches geöffnet werden.

BillThor
quelle
1

Ich würde sagen, dass dies eine ziemlich gute Firewall ist, mit der Ausnahme, dass sie darauf abzielt, eingehenden Verkehr zu stoppen, und sich nicht auf ausgehenden oder ausgehenden Verkehr konzentriert. In vielen Fällen ist es genauso wichtig, sich auf ausgehende Verbindungen zu konzentrieren wie auf eingehende. In dem unglücklichen Fall, dass die Maschine tatsächlich ausgenutzt wird, wäre es schön zu verhindern, dass zusätzliche Root-Kits heruntergeladen oder eine Verbindung zu Befehls- und Steuerknoten oder was auch immer hergestellt wird.

BillThor fing an, darüber zu sprechen, aber ich antworte nur mit konkreten Beispielen. Eines der schönen Dinge an iptables ist, dass es sich an den Verbindungsstatus erinnern kann. Dies kann Auswirkungen auf die Leistung von stark frequentierten Sites haben. Sie können jedoch den eingehenden Zugriff auf http / https ändern, um beispielsweise nur Antworten auf bestehende Verbindungen zuzulassen, oder bestimmte unprivilegierte Verbindungen speziell einschränken Benutzer haben überhaupt keinen ausgehenden Zugriff. Dann hätten Ihre ausgehenden Regeln RELATED, ESTABLISHED-Klauseln, die eine ganze Reihe von Nebenangriffen verhindern und diejenigen verlangsamen würden, die eine Sekundärstufe erfordern, um eine Box tatsächlich auszunutzen, was sehr häufig ist.

Schließlich würde ich sagen, dass es besser ist, die iptables-Richtlinie -P DROP festzulegen, als am Ende ein angefügtes REJECT zu haben. Dies ist meistens eine Frage der Präferenz, kann jedoch Fehler beim Anhängen an Ketten mit vorhandenen Regeln verringern, anstatt sie einzufügen oder zu löschen / zurückzusetzen.

Matty B
quelle
Also sollte ich wechseln -A INPUT -j REJECTzu -A INPUT -P DROP?
Xeoncross