www.dr-lotz.de

iptables-Skript

System: SuSE Linux 9.1

Der Rechner, auf dem diese Regeln laufen, hat einen DSL-Zugang ins Internet und eine Netzwerkkarte zum lokalen Netz. Das lokale Netz soll gegen das Internet abgeschirmt werden, der Zugriff ins Internet erfolgt nur über Proxies, ssh ins Internet beispielsweise mit Hilfe von Socks. Wenn IPSec gestartet ist, ist der Zugriff vom Notebook auf Ressourcen im lokalen Netz möglich.

Ich habe verschiedene benutzerdefinierte Chains verwendet:

Außerdem habe ich soweit möglich das multiport-Modul verwendet, was die Pflege des Skripts sehr vereinfacht. Neue Dienste müssen nur bei den Ports eingetragen werden. In den einzelnen Chains ist jeweils nur das erste IP-Paket aufgeführt, um die weiteren IP-Pakete kümmert sich das state-Modul.

Da es beim Kernel 2.6.x bei IPSec kein Interface ipsec0 mehr gibt, sind auch die Regeln für IPSec geändert, dort kommt jetzt das mangle-Modul zum Einsatz, das Pakete markiert. Die Markierung wird ausgewertet, um Pakete zu erkennen, die zum IPSec-Tunnel gehören.

#!/bin/bash
# Copyright (c) 2004 Björn Lotz 
# 
# Author: Björn Lotz 
#
# /etc/init.d/ipt_rules
#
#   and symbolic its link
#
# /sbin/rcipt_rules
#
# System startup script for the packet filter
#
### BEGIN INIT INFO
# Provides: packetfilter
# Required-Start: $network $syslog
# Required-Stop:  $network $syslog
# Default-Start:  3 5
# Default-Stop:   0 1 2 4 6
# Description:    Start iptables-Firewall 
### END INIT INFO

. /etc/rc.status

# First reset status of this service
rc_reset

case "$1" in
    start|restart|reload)
	echo  "Die Packet-Filter-Regeln werden gesetzt ..."

	
######### Variablen:
	# Interfaces
	DSL=ppp0
	LAN=eth0

	# Adressen
        LOKALE_IP=192.168.0.15
        LOKALES_NETZ=192.168.0.0/24

	# Nameserver
	NS1=194.25.2.129
        NS2=212.185.252.201
	# Zeitserver
	# T-Online, ntp1.t-online.de
	#TIME1=195.145.119.188
	# Braunschweig
	TIME1=192.53.103.103
	TIME2=192.53.103.104

	# Ports
	UNPRIV="1024:65535"
	TRACEROUTE="33434:33999"

	# Private Adressbereiche
	CLASSA=10.0.0.0/8
	CLASSB=172.16.0.0/12
	CLASSC=192.168.0.0/16
	
######### Kernelparameter (Barth, Firewall-Buch p209)
        # Routing erforderlich für IPSec und für die Port-Umleitung,
        # da aufgrund einer Änderung am SuSE-Kernel 2.6.5, 
	# diese nur funktioniert, wenn Routing eingeschaltet ist |-(
	echo 1 > /proc/sys/net/ipv4/ip_forward
	echo 1 > /proc/sys/net/ipv4/tcp_syncookies
	echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
	echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

        # Schutz vor ICMP-Redirect-Paketen aktivieren
        for f in /proc/sys/net/ipv4/conf/*/accept_redirects 
	do
                echo 0 > $f
        done
 
        # Blocken von Source-Routed-Paketen
        for f in /proc/sys/net/ipv4/conf/*/accept_source_route 
	do
                echo 0 > $f
        done                                                                   

        # Loggen von gespooften Paketen, Source-Routed-Paketen und Redirect-Paketen
        # geht nicht mit IP-Sec
        #for f in /proc/sys/net/ipv4/conf/*/log_martians; do
        #        echo 1 > $f
        #done

        # Schutz vor IP-Spoofing aktivieren
        # geht nicht mit IP-Sec
        #for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
        #       echo 1 > $f
        #done
          
######### Default-Policy setzen und vorhandene Regeln l�chen
	iptables -P INPUT DROP
	iptables -P FORWARD DROP
	iptables -P OUTPUT DROP

	iptables -F
        iptables -t nat -F
	iptables -X


######### fr Stateful Inspection von ftp:
	modprobe ip_conntrack_ftp


######### Lokale Prozesse
	iptables -A OUTPUT -o lo -j ACCEPT
	iptables -A INPUT  -i lo -j ACCEPT



####################################################################################
#                                                                                  #
#       Eigene Chains                                                              #
#                                                                                  #
####################################################################################


######### Logging #######################################
	# Log und Reject, bzw Drop, wenn's viele Pakete sind
	iptables -N my_drop
	# zuerst mal die e-donkey-Pakete und die von verschiedenen Würmern verwerfen, 
	# die anscheinend nicht auf tcp-reset reagieren
	iptables -A my_drop -p TCP  --syn --dport 135:137 \ 
		-m limit --limit 10/hour --limit-burst 2 -j LOG --log-prefix "DROP-TCP-SYN "
	iptables -A my_drop -p TCP  --syn --dport 135:137 \
		-m limit --limit 1/s -j REJECT --reject-with tcp-reset
	iptables -A my_drop -p TCP  --syn --dport 135:137 -j DROP
	iptables -A my_drop -p TCP  --syn --dport 445 \
		-m limit --limit 10/hour --limit-burst 2 -j LOG --log-prefix "DROP-TCP-SYN "
	iptables -A my_drop -p TCP  --syn --dport 445 \
		-m limit --limit 1/s -j REJECT --reject-with tcp-reset
	iptables -A my_drop -p TCP  --syn --dport 445 -j DROP
	iptables -A my_drop -p TCP  --syn --dport 4662 \
		-m limit --limit 10/hour --limit-burst 2 -j LOG --log-prefix "DROP-TCP-SYN "
	iptables -A my_drop -p TCP  --syn --dport 4662 \
		-m limit --limit 1/s -j REJECT --reject-with tcp-reset
	iptables -A my_drop -p TCP  --syn --dport 4662 -j DROP
	iptables -A my_drop -p TCP  --syn -j LOG --log-prefix "DROP-TCP-SYN "
	iptables -A my_drop -p TCP  --syn \
		-m limit --limit 5/s -j REJECT --reject-with tcp-reset
	iptables -A my_drop -p TCP  --syn -j DROP
	iptables -A my_drop -p TCP  	  -j LOG --log-prefix "DROP-TCP "
	iptables -A my_drop -p TCP        \
		-m limit --limit 5/s -j REJECT --reject-with tcp-reset
	iptables -A my_drop -p TCP        -j DROP
	iptables -A my_drop -p UDP  	  -j LOG --log-prefix "DROP-UDP "
	iptables -A my_drop -p UDP  	  \
		-m limit --limit 5/s -j REJECT --reject-with icmp-port-unreachable
	iptables -A my_drop -p UDP  	  -j DROP
	iptables -A my_drop -p ICMP 	  -j LOG --log-prefix "DROP-ICMP "
	iptables -A my_drop -p ICMP	  -j DROP
	iptables -A my_drop 	 	  -j LOG --log-prefix "DROP-PROTO-ETC "
	iptables -A my_drop 	  	  \
		-m limit --limit 5/s -j REJECT --reject-with icmp-proto-unreachable
	iptables -A my_drop 		  -j DROP
 


####################################################################################
#                                                                                  #
#       EXTERNE Verbindungen INTERNET --> Rechner (INPUT-Interface $DSL)           #
#                                                                                  #
####################################################################################


	# In diese Chain kommt alles mit INPUT-Interface $DSL
	iptables -N internet_in
        # TCP, Internet --> Rechner: ###
	#iptables -A internet_in  -m mark --mark 10 -j LOG --log-prefix "MARKIERT--- "
	# ssh - 22 (auch via 443), mit Logging

        iptables -A internet_in  -p TCP --syn  --dport 22    -j LOG --log-prefix ">>> Zugriff
	iptables -A internet_in  -p TCP --syn  --sport $UNPRIV -m multiport --dports 22 \
							-j ACCEPT

        # Nicht erforderlich als eigene Regel, aber der Deutlichkeit halber:
	# Jeglicher sonstige TCP-Verbindungsaufbau von außen ist verboten.
	iptables -A  internet_in -p TCP -i $DSL --syn			-j my_drop

        # Ebenso: Schutz vor IP-Spoofing 
	iptables -A internet_in  	  -s $CLASSA   -j my_drop
	iptables -A internet_in  	  -s $CLASSB   -j my_drop
	#iptables -A internet_in  	  -s $CLASSC   -j my_drop
	
        # UDP, Internet --> Rechner: ###
	# isakmp - 500 
	iptables -A internet_in -p UDP            --sport 500   --dport 500  -j ACCEPT

	
	iptables -A internet_in -j my_drop

####################################################################################
#                                                                                  #
#       EXTERNE Verbindungen Rechner --> INTERNET (OUTPUT-Interface $DSL)          #
#                                                                                  #
####################################################################################

	# In diese chain kommt alles mit OUTPUT-Interface $DSL
	iptables -N internet_out

	### TCP, Rechner --> Internet: ###
	# ftp - 21
	# smtp - 25
	
	iptables -A internet_out -p TCP --syn -m multiport --dports 21,25  --sport $UNPRIV \
							-j ACCEPT

	# FTP-Proxy-Datenkanal, passiv, von hohen Ports zu hohen Ports (von hier ins I-Net)
	# Für FTP bräuchte es das nicht, das wrde ftp-conntrack übernehmen,
        # aber so sind auch Verbindungen von hier z.B. zu pgp-Keyservern möglich.
	iptables -A internet_out -p TCP --syn  --sport $UNPRIV --dport $UNPRIV -j ACCEPT

	### UDP, Rechner --> Internet: ###
	# time - 37, nur zu bestimmten Servern, deshalb eigene Regeln 
	# dns - 53 
	# isakmp - 500 
	# traceroute - Portrange, deshalb eigene Regel 
	 
	iptables -A internet_out -p UDP --sport $UNPRIV -m multiport --dports 53 -j ACCEPT

	iptables -A internet_out -p UDP  -d $TIME1 --sport $UNPRIV --dport 37 -j ACCEPT
	iptables -A internet_out -p UDP  -d $TIME2 --sport $UNPRIV --dport 37 -j ACCEPT
	iptables -A internet_out -p UDP                 --dport $TRACEROUTE   -j ACCEPT
	iptables -A internet_out -p UDP            --sport 500   --dport 500  -j ACCEPT

	iptables -A internet_out -j my_drop

####################################################################################
#                                                                                  #
#      	INTERNE Verbindungen INTRA --> Rechner (INPUT-Interface $LAN)              #
#                                                                                  #
####################################################################################


	# In diese chain kommt alles mit INPUT-Interface $LAN
	iptables -N intra_in

        # TCP, Internes Netz --> Rechner:
	# ftp - 21 
	# smtp - 25    
	# dns - 53    
	# http - 80 
	# http-proxy - 3128

	iptables -A intra_in  -p TCP   --dport 1080   -j my_counter
	iptables -A intra_in  -p TCP --syn --sport $UNPRIV \
		-m multiport --dports 21,22,25,53,80,3128 -j ACCEPT
	
######### UDP, Intranet --> Rechner:
	# time - 37 
	# dns - 53 
	# dhcp - 67 
	
	iptables -A intra_in  -p UDP  --sport $UNPRIV -m multiport --dports 37,53,67 \
							-j ACCEPT
	
	iptables -A intra_in   -j my_drop

####################################################################################
#                                                                                  #
#      	INTERNE Verbindungen Rechner --> INTRA (OUTPUT Interface $LAN)             #
#                                                                                  #
####################################################################################


	# In diese Chain kommt alles mit OUTPUT-Interface $LAN
	iptables -N intra_out

        ### TCP, Rechner --> Internes Netz: ###
	# ssh - 22 
	# ident - 113 

	iptables -A intra_out -p TCP --syn --sport $UNPRIV -m multiport --dports 22,113 \
							-j ACCEPT 

        ### UDP, Rechner --> Internes Netz: ### 
	# dhcp - 67
	# syslog - 514, zum Loghost 

	iptables -A intra_out -p UDP  -d 192.168.0.1  --sport 514 --dport 514	-j ACCEPT
	
        # anscheinend funktioniert bei DHCP das Connection Tracking nicht richtig,
        # da das erste Packet von 0.0.0.0 kommt, die Antwort aber an eine
        # bestimmte IP-Nummer geht. Daher noch folgende Regel:
	iptables -A intra_out -p UDP                  --sport 67  	-j ACCEPT

	iptables -A intra_out  -j my_drop

 
####################################################################################
#                                                                                  #
#       IPSec                                                                      #
#                                                                                  #
####################################################################################

	iptables -N ipsec_for
	# forwarding von Paketen aus dem Tunnel und zurück
	iptables  -A ipsec_for -i $DSL  -o $LAN -m mark --mark 10 -j ACCEPT

	# Oder mit dem Policy-Modul, was den Vorteil hat, dass man auch den
	# Traffic in den Tunnel kontrollieren kann, d.h. Verbindungen vom
	# Gateway zum Roadwarrior möglich sind:
	# iptables -A FORWARD -i $DSL -m policy --dir in  --pol ipsec \
        #            --mode tunnel --proto esp -j ACCEPT
        # iptables -A FORWARD -o $DSL -m policy --dir out --pol ipsec \
        #            --mode tunnel --proto esp -j ACCEPT


	iptables -A ipsec_for -j my_drop


####################################################################################
#                                                                                  #
###                  --- Ende benutzerdefinierte Chains ---                      ###
#                                                                                  #
####################################################################################



####################################################################################
#                                                                                  #
#       Allgemeine Regeln                                                          #
#                                                                                  #
####################################################################################

	# Umleitung auf ftp-Proxy:
        # FTP
	iptables -A PREROUTING -t nat -p tcp -i $LAN -d 0/0 --dport 21   -j REDIRECT 
	
	# IPSec-Pakete markieren:
	# (Kann auch entfallen, siehe bei ipsec-Abschnitt)
        iptables -t mangle -A PREROUTING -p 50 -i $DSL -j MARK --set-mark 10


######### Generelle Regeln für Folgepakete (2. und alle weiteren) ##################
        # INPUT-Chain
	iptables -A INPUT      -m state --state ESTABLISHED,RELATED -j ACCEPT   
        # OUTPUT-Chain
	iptables -A OUTPUT     -m state --state ESTABLISHED,RELATED -j ACCEPT   
        # FORWARD-Chain
        iptables -A FORWARD -i $DSL -o $LAN   -m state --state ESTABLISHED,RELATED -j ACCEPT  
        iptables -A FORWARD -o $DSL -i $LAN   -m state --state ESTABLISHED,RELATED -j ACCEPT 



####################################################################################
#                                                                                  #
#       ICMP                                                                       #
#                                                                                  #
####################################################################################


######### ICMP
	# ICMP ping: 8 und 0 ausgehend erlaubt, alle Interfaces 
	iptables -A OUTPUT -p ICMP 		--icmp-type echo-request -j ACCEPT
	iptables -A INPUT  -p ICMP 		--icmp-type echo-reply   -j ACCEPT

	# ICMP ping: 8 und 0 eingehend auf eth+ erlaubt
	iptables -A INPUT  -p ICMP -i $LAN 	--icmp-type echo-request -j ACCEPT
	iptables -A OUTPUT -p ICMP -o $LAN 	--icmp-type echo-reply   -j ACCEPT


	# ICMP ping: 8 und 0 eingehend auf DSL-Karte in Grenzen erlaubt
	iptables -A INPUT  -p ICMP -i $DSL 	\
		-m limit --limit 5/s --icmp-type echo-request -j ACCEPT
	iptables -A INPUT  -p ICMP -i $DSL 	--icmp-type echo-request -j my_drop
	iptables -A OUTPUT -p ICMP -o $DSL	--icmp-type echo-reply   -j ACCEPT
	
######### Die folgenden Typen sollten eigentlich durch den Parameter RELATED
        # des Modules state abgedeckt sein:
	# ICMP source quench 4
	#iptables -A OUTPUT -p ICMP 		--icmp-type source-quench -j ACCEPT
	#iptables -A INPUT  -p ICMP 		--icmp-type source-quench -j my_drop
	# ICMP time exceeded 11
	#iptables -A OUTPUT -p ICMP 		--icmp-type time-exceeded -j ACCEPT
	#iptables -A INPUT  -p ICMP 		--icmp-type time-exceeded -j ACCEPT
	# ICMP parameter problem 12
	#iptables -A OUTPUT -p ICMP 		--icmp-type parameter-problem -j ACCEPT
	#iptables -A INPUT  -p ICMP 		--icmp-type parameter-problem -j ACCEPT
	# ICMP destination unreachable 3
	#iptables -A OUTPUT -p ICMP 		--icmp-type fragmentation-needed -j ACCEPT
	#iptables -A INPUT  -p ICMP 		--icmp-type fragmentation-needed -j ACCEPT
	#iptables -A OUTPUT -p ICMP 		--icmp-type port-unreachable -j ACCEPT
	#iptables -A INPUT  -p ICMP 		--icmp-type port-unreachable -j ACCEPT

####################################################################################
#                                                                                  #
#       Verteilung auf die jeweiligen benutzerdefinierten Chains                   #
#                                                                                  #
####################################################################################

	iptables -A INPUT  -i $LAN  -j intra_in
	iptables -A INPUT  -i $DSL  -p 50 -j ACCEPT
	iptables -A INPUT  -i $DSL  -j internet_in
	iptables -A OUTPUT -o $DSL  -j internet_out
	iptables -A OUTPUT -o $LAN  -j intra_out

	iptables  -A FORWARD -i $DSL   -m mark --mark 10 -j ipsec_for
	# oder, falls im ipsec-Abschnitt mit -m policy gearbeitet wird:
	# iptables  -A FORWARD -i $DSL   -j ipsec_for
	# iptables  -A FORWARD -o $DSL   -j ipsec_for






######### Alles was bis hierher kam wird gelogged und dann verworfen bzw. nur zurckgewiesen.
	iptables -A INPUT  					-j my_drop
	iptables -A FORWARD 					-j my_drop
	iptables -A OUTPUT  					-j my_drop


	echo -n "Die Packet-Filter-Regeln sind jetzt gesetzt."
	# Remember status and be verbose
	rc_status -v
	;;


    stop)
	echo "Die Packet-Filter-Regeln werden gelöscht ... "

	iptables -F
        iptables -t nat -F
	iptables -X
	iptables -P INPUT ACCEPT
	iptables -P OUTPUT ACCEPT
	iptables -P FORWARD ACCEPT

	echo -n "Die Packet-Filter-Regeln erlauben jetzt wieder alles."
        echo 0 > /proc/sys/net/ipv4/ip_forward
        echo -n "Routing ist ausgeschaltet."
	# Remember status and be verbose
	rc_status -v
	;;
    status)
	echo "Die Filterregeln: "

	iptables -v -n -L
        iptables -v -n -t nat -L   POSTROUTING
        iptables -v -n -t nat -L   PREROUTING
	# Status has a slightly different for the status command:
	# 0 - service running
	# 1 - service dead, but /var/run/  pid  file exists
	# 2 - service dead, but /var/lock/ lock file exists
	# 3 - service not running

	# NOTE: checkproc returns LSB compliant status values.
	#checkproc $FOO_BIN
	#rc_status -v
	;;
    *)
	echo "Usage: $0 {start|restart|reload|stop|status}"
	exit 1
	;;
esac
rc_exit