Einfaches Firewall-Script

Aus DebianforumWiki
Zur Navigation springen Zur Suche springen
Wiki ‹ Internetrouter und Proxies ‹ Einfaches Firewall-Script


Getestet.png Getestet: Dieser Hinweis soll dir dabei helfen, zu entscheiden, ob dieser Artikel auf deinem System funktionieren wird oder nicht. Solltest du feststellen, dass dieser Artikel bei einer ungetestet Version funktioniert, kannst du das gerne hier korrigieren oder im Forum anmerken.




Einfaches Firewall-Script auf iptables-Basis (Fortgeschrittene)

Einleitung

Wenn man Wheezy installiert hat, werden ausgehende- und eingehende Verbindungen durch die Firewall im Linux-Kernel jeglichen Dienstes via Standard-Einstellung zugelassen: Das wollen wir ändern, indem wir eigene Regeln aufstellen und nur noch bestimmte Dienste mit der "Außenwelt" des Servers kommunizieren lassen.

Möglich macht dies das Userspace-Programm "iptables" (siehe Wikipedia iptables). Damit lässt sich die Linux-Firewall verwalten. Die Firewall besteht aus sogenannten Ketten und Regeln.

In der Standardkonfiguration von Wheezy ist die Standardmethode(auch Policy genannt) für alle Ketten "ACCEPT". Das könnt ihr euch selbst mit diesem Befehl anzeigen lassen:

root@debian:~# iptables -L

Die Ausgabe wird so aussehen:

root@wheezy:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Was kann man erkennen? Die Policy für alle Ketten ist ACCEPT und keine einzige Regel wurde definiert. Das ist schlecht, wenn man diesen Server öffentlich im Internet betreibt. So kann jeder Dienst kommunizieren wie er will. Das wollen wir mit einer anderen Policy und eigenen Regeln ändern.

Das Firewall-Script

Ich möchte euch jetzt nicht Regel-für-Regel langweilen, sondern ein fertiges, leicht anpassbares Firewall-Script bieten.

  • Policy: DROP (Pakete generell verwerfen, alle Ketten)
  • SSH via Standard aktiviert (ihr sperrt euch damit definitiv nicht aus!)
  • Bereits einige Standarddienste zugelassen: SSH, DNS, HTTP(S), POP3(S), IMAP, SMTP, FTP, NTP
  • Weitere Dienste: MySQL, SVN, Mumble (auskommentiert) zuschaltbar
  • Anzahl der Regeln: gering (Script im Einsatz auf einem abgespeckten vServer mit begrenzter Regel-Anzahl(siehe NUMIPTENT))
  • NUMIPTENT in /proc/user_beancounters: Deutlich unter 96 (Checken mit "egrep "failcnt|numiptent" /proc/user_beancounters")
  • Ping-Flood wird begrenzt
  • Regeln für ausgehende- und eingehende Verbindungen auf Basis der bestehenden Regeln einfach selbst anlegen
#!/bin/bash

IPTABLES="/sbin/iptables"

# Logging options.
#------------------------------------------------------------------------------
LOG="LOG --log-level debug --log-tcp-sequence --log-tcp-options"
LOG="$LOG --log-ip-options"

# Defaults for rate limiting
#------------------------------------------------------------------------------
RLIMIT="-m limit --limit 3/s --limit-burst 30"

# Default policies.
#------------------------------------------------------------------------------
 
# Drop everything by default.
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -P OUTPUT DROP
 
# Set the nat/mangle/raw tables' chains to ACCEPT
$IPTABLES -t nat -P PREROUTING ACCEPT
$IPTABLES -t nat -P OUTPUT ACCEPT
$IPTABLES -t nat -P POSTROUTING ACCEPT
 
$IPTABLES -t mangle -P PREROUTING ACCEPT
$IPTABLES -t mangle -P INPUT ACCEPT
$IPTABLES -t mangle -P FORWARD ACCEPT
$IPTABLES -t mangle -P OUTPUT ACCEPT
$IPTABLES -t mangle -P POSTROUTING ACCEPT
 
# Cleanup.
#------------------------------------------------------------------------------
 
# Delete all
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -t mangle -F
 
# Delete all
$IPTABLES -X
$IPTABLES -t nat -X
$IPTABLES -t mangle -X
 
# Zero all packets and counters.
$IPTABLES -Z
$IPTABLES -t nat -Z
$IPTABLES -t mangle -Z


# Custom user-defined chains.
#------------------------------------------------------------------------------
 
# LOG packets, then ACCEPT.
$IPTABLES -N ACCEPTLOG
$IPTABLES -A ACCEPTLOG -j $LOG $RLIMIT --log-prefix "ACCEPT "
$IPTABLES -A ACCEPTLOG -j ACCEPT
 
# LOG packets, then DROP.
$IPTABLES -N DROPLOG
$IPTABLES -A DROPLOG -j $LOG $RLIMIT --log-prefix "DROP "
$IPTABLES -A DROPLOG -j DROP
 
# LOG packets, then REJECT.
# TCP packets are rejected with a TCP reset.
$IPTABLES -N REJECTLOG
$IPTABLES -A REJECTLOG -j $LOG $RLIMIT --log-prefix "REJECT "
$IPTABLES -A REJECTLOG -p tcp -j REJECT --reject-with tcp-reset
$IPTABLES -A REJECTLOG -j REJECT
 
# Only allows RELATED ICMP types
# (destination-unreachable, time-exceeded, and parameter-problem).
# TODO: Rate-limit this traffic?
# TODO: Allow fragmentation-needed?
# TODO: Test.
$IPTABLES -N RELATED_ICMP
$IPTABLES -A RELATED_ICMP -p icmp --icmp-type destination-unreachable -j ACCEPT
$IPTABLES -A RELATED_ICMP -p icmp --icmp-type time-exceeded -j ACCEPT
$IPTABLES -A RELATED_ICMP -p icmp --icmp-type parameter-problem -j ACCEPT
$IPTABLES -A RELATED_ICMP -j DROPLOG
 
# Make It Even Harder To Multi-PING
$IPTABLES  -A INPUT -p icmp -m limit --limit 1/s --limit-burst 2 -j ACCEPT
$IPTABLES  -A OUTPUT -p icmp -j ACCEPT
 
# Only allow the minimally required/recommended parts of ICMP. Block the rest.
#------------------------------------------------------------------------------

# Allow all ESTABLISHED ICMP traffic.
$IPTABLES -A INPUT -p icmp -m state --state ESTABLISHED -j ACCEPT $RLIMIT
$IPTABLES -A OUTPUT -p icmp -m state --state ESTABLISHED -j ACCEPT $RLIMIT
 
# Allow some parts of the RELATED ICMP traffic, block the rest.
$IPTABLES -A INPUT -p icmp -m state --state RELATED -j RELATED_ICMP $RLIMIT
$IPTABLES -A OUTPUT -p icmp -m state --state RELATED -j RELATED_ICMP $RLIMIT
 
# Allow incoming ICMP echo requests (ping), but only rate-limited.
$IPTABLES -A INPUT -p icmp --icmp-type echo-request -j ACCEPT $RLIMIT
 
# Allow outgoing ICMP echo requests (ping), but only rate-limited.
$IPTABLES -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT $RLIMIT
 
# Drop any other ICMP traffic.
$IPTABLES -A INPUT -p icmp -j DROPLOG
$IPTABLES -A OUTPUT -p icmp -j DROPLOG
$IPTABLES -A FORWARD -p icmp -j DROPLOG
 
# Selectively allow certain special types of traffic.
#------------------------------------------------------------------------------
 
# Allow loopback interface to do anything.
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A OUTPUT -o lo -j ACCEPT
 
# Allow incoming connections related to existing allowed connections.
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
 
# Allow outgoing connections EXCEPT invalid
$IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
 
# Miscellaneous.
#------------------------------------------------------------------------------

# Explicitly drop invalid incoming traffic
$IPTABLES -A INPUT -m state --state INVALID -j DROP
 
# Drop invalid outgoing traffic, too.
$IPTABLES -A OUTPUT -m state --state INVALID -j DROP
 
# If we would use NAT, INVALID packets would pass - BLOCK them anyways
$IPTABLES -A FORWARD -m state --state INVALID -j DROP
 
# Selectively allow certain outbound connections, block the rest.
#------------------------------------------------------------------------------
 
# Erlaube ausgehende DNS Anfragen. Few things will work without this.
$IPTABLES -A OUTPUT -m state --state NEW -p udp --dport 53 -j ACCEPT
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 53 -j ACCEPT
 
# Erlaube ausgehende HTTP Anfragen.
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT
 
# Erlaube ausgehende HTTPS Anfragen.
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 443 -j ACCEPT

# Erlaube ausgehende SMTP Anfragen.
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 25 -j ACCEPT

# Erlaube ausgehende SMTPS Anfragen.
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 465 -j ACCEPT
 
# Erlaube ausgehende "submission" (RFC 2476) Anfragen.
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 587 -j ACCEPT
 
# Erlaube ausgehende POP3S Anfragen.
#$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 995 -j ACCEPT
 
# Erlaube ausgehende SSH Anfragen.
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 22 -j ACCEPT

# Erlaube ausgehende FTP Anfragen.
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 21 -j ACCEPT

# Erlaube ausgehende NTP Anfragen.
$IPTABLES -A OUTPUT -m state --state NEW -p udp --dport 123 -j ACCEPT

# Erlaube ausgehende WHOIS Anfragen.
$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 43 -j ACCEPT

# Erlaube ausgehende CVS Anfragen.
#$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 2401 -j ACCEPT
 
# Erlaube ausgehende MySQL Anfragen.
#$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 3306 -j ACCEPT
 
# Erlaube ausgehende SVN Anfragen.
# $IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 3690 -j ACCEPT

# Erlaube ausgehende Mumble Anfragen.
#$IPTABLES -A OUTPUT -m state --state NEW -p tcp --dport 64738 -j ACCEPT
#$IPTABLES -A OUTPUT -m state --state NEW -p udp --dport 64738 -j ACCEPT

# Selectively allow certain inbound connections, block the rest.
#------------------------------------------------------------------------------
 
# Erlaube eingehende DNS Anfragen.
$IPTABLES -A INPUT -m state --state NEW -p udp --dport 53 -j ACCEPT
$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 53 -j ACCEPT
 
# Erlaube eingehende HTTP Anfragen.
$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT
 
# Erlaube eingehende HTTPS Anfragen.
$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 443 -j ACCEPT
 
# Erlaube eingehende POP3 Anfragen.
$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 110 -j ACCEPT
 
# Erlaube eingehende IMAP4 Anfragen.
$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 143 -j ACCEPT
 
# Erlaube eingehende POP3S Anfragen.
$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 995 -j ACCEPT
 
# Erlaube eingehende SMTP Anfragen.
$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 25 -j ACCEPT
 
# Erlaube eingehende SSH Anfragen.
$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 22 -j ACCEPT
 
# Erlaube eingehende FTP Anfragen.
$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 21 -j ACCEPT

# Erlaube eingehende Mumble-Anfragen.
#$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 64738 -j ACCEPT
#$IPTABLES -A INPUT -m state --state NEW -p udp --dport 64738 -j ACCEPT

# Erlaube eingehende MySQL Anfragen.
#$IPTABLES -A INPUT -m state --state NEW -p tcp --dport 3306 -j ACCEPT

# Explicitly log and reject everything else.
#------------------------------------------------------------------------------
# Use REJECT instead of REJECTLOG if you don't need/want logging.
$IPTABLES -A INPUT -j REJECT
$IPTABLES -A OUTPUT -j REJECT
$IPTABLES -A FORWARD -j REJECT

# Exit gracefully.
#------------------------------------------------------------------------------
 
    exit 0

Selbstverständlich übernehme ich für das Script keinerlei Haftung und Garantie. Jedoch kann ich euch versichern, dass ich es nach bestem Ermessen zusammengestellt habe. Es läuft auf meinem Ubuntu 10.04 vServer im Praxisbetrieb und unter Wheezy 7.2 habe ich es auch erfolgreich getestet. Relevant sind für euch die Zeilen mit den deutschen Kommentaren (Richtige Experten werden wohl noch viel mehr verändern).

Installation des Scripts

Speichert das Script einfach irgendwo als firewall.sh ab, /etc/init.d/firewall.sh bietet sich an. Macht es im Anschluss mit chmod 755 ausführbar.

Mit dieser einen zusätzlichen Zeile in eurer /etc/crontab wird das Script bei jedem Server-Start geladen:

@reboot root /etc/init.d/firewall.sh

Viel Spaß. (Referenz zum Script[1])