Ganz wichtig: Dieser Text ist nicht fehlerfrei. Und damit meine
ich keine Rechtschreibfehler. Ich uebernehme keine Gewaehr.
Wichtig ist: jede neue Kommando wird hinten an die ACL angehängt.
im Zweifelsfalls heißt also die Lösung "wegwerfen und neu machen",
oder rcp nehmen. Wobei Wegwerfen, wenn man die Änderung remote macht,
riskant ist (hint: nicht vorhandene ACLs, die irgendwo noch angesprochen
werden, wirken wie "DENY alles"). rcp funktioniert ganz gut.
Im Zweifelsfall legt man eine neue ACL an, trägt die anstelle der
Alten in den Interfaces ein, und löscht dann die alte ACL.
Die Syntax ist:
access-list [permit|deny] NNN PROTOCOL SOURCE [PORTSPEC] \
DEST [PORTSPEC] [established] [log|log-input]
Darin bedeutet:
interface bri0 ip access-group NNN in|out(in oder out aus Sicht des Ciscos).
ipchains ist ein Kommando zur Verwaltung der ACLs im Kernel. Im Normalfall hängt es eine Zeile an, oder löscht eine Zeile oder fügt eine Zeile ein. Anders gesagt - an dieser Stelle ist es flexibler als cisco-IOS. Ich benutze das aber so nicht, da ich es vorziehe immer mit ganzen Listen zu hantieren und nicht einzelne Kommandos auszuprobieren (aber das ist nur meine Arbeitsweise, nicht prinzipiell besser).
Es gibt drei globale ACL - input, output und forward.
I/o dürfte klar sein, forward bestimmt das Weiterleiten von
Paketen (I+O zusammen leisten nicht das was F leistet, und
F leistet nichts von dem was I oder O leisten).
In diese globalen ACLs kann man noch weitere Einhängen.
Die Defaultpolicy stellt man mit "ipchains -P" ein, für
jede ACL extra. Beispiel siehe unten.
Außer ACCEPT (paket ist OK) gibt es noch DENY (laß es verschwinden) und REJECT (sende Host unreachable). DENY ist ein guter Default für input Rules.
Bei meiner Vorgehensweise - Configdatei verändern und dann ACL aktivieren, gibt es ein Problem - wenn ich die ACL zwischen- zeitlich löschen würde um sie neu aufzubauen hätte ich einen Moment lang keine. Deshalb habe ich ein Script um die eigentliche ACL gemacht, es setzt die Defaults, legt eine temporäre ACL an, macht sie zur aktiven ACL, loescht die Alte, legt die Alte wieder an, macht sie aktiv, löscht die Temporäre wieder.
Vorteil bei diese Vorgehensweise: der Name ist die allermeiste Zeit identisch - das hilft bei Scripten die die ACL auswerten, ungemein.
Syntax:
Bei ICMP-Paketen ist der Sourceport der ICMP-Typ, und der Destination-Port die genauere Spezifizierung ("unreachable" + "host unreachable").
Nichtsdestotrotz ist 2.0.33 natürlich um etliches stabiler als 2.1.102.
Die Syntax ist recht ähnlich der des ipchains-Kommandos, nur
ein paar Optionen heissen anders, und accept,deny,reject wollen
kleingeschrieben werden.
Es wird grundsätzlich an die Liste angehängt (von denen es auch
hier drei gibt, allerdings ohne die Möglichkeit auf andere ACLs
zu verweisen.
Ich spare mir hier die detaillierte Auffuehrung der Optionen. Die Syntax ist hinreichend aehnlich der der ipchains, allerdings muss man auf gross/kleinschreibung achten. Ein Beispiel:
ipfwadm -I -a accept -b -P udp -S 0.0.0.0/0 53 \
-D 194.245.80.2/32 53
Ascend-Data-Filter="ip [in|out] [forward|drop] \
[dstip DESTIP/MASKBITS] [srcip SRCIP/MASKBITS] \
[PROTO [dstport CMP DESTPORT] \
[srcport CMP SRCPORT] [EST]]"
Kurze Legende:
Will man ICMP oder andere Protokolle filtern, die keine Ports kennen, wird es umstaendlicher - dann muß man zu sog. generischen Filtern greifen, die schwieriger zu konfigurieren sind und mit denen man einzelne Bits im IP-Paket untersuchen kann.
Was tun wenn man nur einen Cisco hat? You lose, dafuer ist der Router ungeeignet.
Wie entkommt man diesem Dilemma, wenn man selbst FTP-Server sein will
und selbst FTP nutzen koennen will?
# ftp
ipchains -A $i -p tcp -y \
-d 194.245.80.2 21 -j ACCEPT
# ftp-data -> NFS
ipchains -A $i -p tcp -y -s 0/0 20 \
-d 194.245.80.2 2049 -j REJECT
# ftp-data -> X
ipchains -A $i -p tcp -y -s 0/0 20 \
-d 194.245.80.2 6000:6010 -j REJECT
# ftp-data -> andere Port >1024: OK.
ipchains -A $i -p tcp -y -s 0/0 20 \
-d 194.245.80.2 1024: -j ACCEPT
Man erlaubt also den Zugriff auf gewisse Ports von port 20 aus - das
kann zwar ein FTP-Server sitzen, _aber_ das muss nicht. Das kann auch
der böse Einbrecher sein. In jedem Fall sollte man andere kritische
Ports auch sperren - siehe unten unter RPC.
Prinzipiell ist das nicht wesentlich sicherer als diese Zeile, die nebenbei
auch incoming passive mode ftp erlaubt:
ipchains -A $i -p tcp -y -s 0/0 1024: \
-d 194.245.80.2 1024: -j ACCEPT
Sie macht es nur einfacher zu sehen dass da noch andere Sachen sind ...
Fazit: ftp ist ein Problem, daß sich mit den Mitteln eines
Paketfilters nicht lösen läßt. man müßte hier
schon mehr Möglichkeiten haben - aber das setzt Überwachung
der FTP-Control-Connection voraus und ähnelt damit mehr einem
richtigen Firewall.
Bei manchen FTP-Servern kann man die Fähigkeit zum passive
mode abschalten, die mir bekannten Clients gehen dann automatisch zum
active mode über (falls der Firewall auf der Seite des Clients das
zuläßt. Katze, Schwanz, Biß).
In jedem Fall sollte man tunlichst darauf achten daß man, wenn man
den Zugriff von Port 20 auf Port X (X>1023) oder von überall auf
Port X freigibt, alle Port noch absichert die oberhalb von 1023 liegen
und in Benutzung sind, z.B. X, NFS, Datenbankapplikationen. Leider ist
das nicht einfach, siehe unten unter RPC (dasselbe kann aber auch
fuer ganz andere Dienste gelten, nicht nur fuer RPC).
Das heißt: wenn man DNS-Server ist muß man auch beliebige TCP-Verbindungen von aussen auf port 53 erlauben _oder_ dafür Sorge tragen daß der Fall nicht auftreten kann (keine überlangen TXT-Pakete).
Andererseits sind icmps beliebte Träger für Attacken (jolt).
Was also tun? Hat man eine Linuxmachine zur Verfuegung kann man diese alle Pakete defragmentieren lassen. Ansonsten kann man versuchen nur die wichtigsten ICMPs durchzulassen - dazu zaehlt insbesondere Typ 3, die "unreachables".
Normalerweise funktioniert RPC so, daß man den Portmapper fragt "hey du, auf welchem Port ist lockd?". Wenn Portmapper geblockt ist kommt halt keine Antwort, aber das macht nichts, mit strobe oder nmap findet man den Port ja trotzdem - man weiß zwar nicht _was_ das ist, aber offen ist er dennoch - was mir nicht schmeckt, da SUNs RPC-Code eine eher unsichere Angelegenheit ist.
Eine Moeglichkeit waere, diesen Muell nicht zu starten. Dummerweise
gibt es Systeme die RPC-Dienste von sich aus starten wenn andere
Dienste gestartet werden (so startet der Linux-knfsd auch lockd und
rpciod).
Die Andere ist, das Zeug absolut gar nicht zu starten. Also auch nfsd
nicht. Das ist natuerlich manchmal unpraktisch.
Die Letzte und Beste ist, Verbindungen von aussen nur auf bestimmte Ports
zu erlauben - was allerdings der Tod fuer passive-mode-FTP-Zugriff auf
den FTP-Server hinter dem Firewall ist. Im Zweifelsfall ist das die
sinnvollste Alternative.
Gruende dafuer:
# ACL erst mal löschen
if grep -w $i /proc/net/ip_fwnames >/dev/null ; then
ipchains -L -vn |head
ipchains -F $i
ipchains -X $i
fi
neue ACL anlegen.
ipchains -N $i
# IP-Spoofing? Aber nicht doch!
ipchains -A $i -s 194.245.80.2/28 -l -j DENY
# remote redirects? Hm?
# das ist zwar etwas, mit dem der Kernel fertigwerden _sollte_,
# aber gleichzeitig sind remote redirects _so_ gefaehrlich
# daß sich der Mehraufwand rechtfertigen läßt.
ipchains -A $i -p icmp -s 0/0 redirect -l -j DENY
# und icmp-Typen über 12 sind nicht allzu wichtig.
ipchains -A $i -p icmp -s 0/0 12: -l -j DENY
# traceroute bis zum Gateway erlauben
# "erlauben" ist relativ ... hier heißt es "unreachable zuruecksenden".
# Über das "-l" läßt sich streiten.
ipchains -A $i -p udp -s 0/0 \
-d 194.245.80.0/28 30000: -l -j REJECT
# soweit die globalen Sachen. Jetzt die einzelnen Kisten:
# hurd. Nach außen unsichtbar.
ipchains -A $i -d 194.245.80.1 -l -j DENY
# tirka. der Router. Loggt, aber akzeptiert pings. Akzeptiert alle anderen
# icmps.
#
# echo-request
ipchains -A $i -p icmp -s 0/0 8 \
-d 194.245.80.2 -l -j ACCEPT
# andere ICMPs
ipchains -A $i -p icmp -s 0/0 \
-d 194.245.80.2 -j ACCEPT
# nfs, X sperren
ipchains -A $i -p tcp -y \
-d 194.245.80.2 2049 -l -j DENY
ipchains -A $i -p tcp -y \
-d 194.245.80.2 6000:6010 -l -j DENY
# ftp-data (actice mode FTP, bei dem der Client auf dieser Maschine sitzt)
ipchains -A $i -p tcp -y -s 0/0 20 \
-d 194.245.80.2 1024: -j ACCEPT
# zugriffe auf lokalen FTP-Server
ipchains -A $i -p tcp -y \
-d 194.245.80.2 21 -j ACCEPT
# ssh
ipchains -A $i -p tcp -y \
-d 194.245.80.2 22 -j ACCEPT
# smtp
ipchains -A $i -p tcp -y \
-d 194.245.80.2 25 -j ACCEPT
# http
ipchains -A $i -p tcp -y \
-d 194.245.80.2 80 -j ACCEPT
# auth
ipchains -A $i -p tcp -y \
-d 194.245.80.2 113 -j ACCEPT
# nntp fuer zwei Maschinen
ipchains -A $i -p tcp -y -s 194.245.99.18 \
-d 194.245.80.2 119 -j ACCEPT
ipchains -A $i -p tcp -y -s 194.245.103.2 \
-d 194.245.80.2 119 -j ACCEPT
# alle anderen SYN-Pakete wegwerfen
ipchains -A $i -p tcp -y \
-d 194.245.80.2 -l -j DENY
# alle TCP-Pakete ohne SYN sind OK.
ipchains -A $i -p tcp ! -y \
-d 194.245.80.2 -j ACCEPT
# DNS-Austausch zwischen den Servern
# das kann man auch einschraenken wenn der DNS-Server nur forwarder benutzt,
# was meiner aber, wenn mich der Spieltrieb befaellt, nicht tut.
ipchains -A $i -p udp -s 0/0 53 \
-d 194.245.80.2 53 -j ACCEPT
# DNS-Lookups von dieser Kiste aus erlauben (bzw. die Antworten darauf)
ipchains -A $i -p udp -s 0/0 53 \
-d 194.245.80.2 1024: -j ACCEPT
# für jemanden talk/ntalk freigeben.
# nicht für jedermann, dazu ist talk viel zu nervig.
ipchains -A $i -p udp -s 193.141.108.34 \
-d 194.245.80.2 517:518 -j ACCEPT
ipchains -A $i -p udp -s 193.141.108.34 517:518 \
-d 194.245.80.2 -j ACCEPT
# Rest entsorgen
ipchains -A $i \
-d 194.245.80.2 -l -j DENY
#
# fjoras, BeOS. Outgoing OK, incoming nicht. Kein UDP.
# braucht keine ping-Echos.
ipchains -A $i -p tcp ! -y \
-d 194.245.80.3 -j ACCEPT
ipchains -A $i -p tcp \
-d 194.245.80.3 -l -j DENY
# unreachables
ipchains -A $i -p icmp -s 0/0 3 \
-d 194.245.80.3 -j ACCEPT
ipchains -A $i \
-d 194.245.80.3 -l -j DENY
# serak, DOSe. Nach aussen unsichtbar
ipchains -A $i \
-d 194.245.80.4 -l -j DENY
# apollo, HPUX. Outgoing OK, incoming nicht.
# der tcp/ip-Stack hat eine extrem aggressive path mtu discovery, scheint
# mir. Deshalb auch source-quench durchlassen.
# Anderseits ist die Kiste so steinalt daß sie garantiert Löcher hat.
# "comp.sys.hpux: how many root holes do you want to see today"?
ipchains -A $i -p tcp ! -y \
-d 194.245.80.5 -j ACCEPT
# unreachables
ipchains -A $i -p icmp -s 0/0 3 \
-d 194.245.80.5 -j ACCEPT
# source-quech
ipchains -A $i -p icmp -s 0/0 4 \
-d 194.245.80.5 -j ACCEPT
ipchains -A $i \
-d 194.245.80.5 -l -j DENY
# peter. DOS. Nach aussen unsichtbar.
ipchains -A $i \
-d 194.245.80.6 -l -j DENY
# DU3 bietet ftp,telnet,whois
# wenn auf der Kiste sonst nichts liefe hätte man es sehr einfach,
# man koennte einfach den Zugriff auf alle Ports >1023 freigeben und
# hätte dann überhaupt keine Probleme mehr. Da die Praemisse
# "hier laeuft nur das und das" auf meinen Spielzeugrechnern nicht
# besonders lange stimmt bin ich hier paranoider:
ipchains -A $i -p tcp -y \
-d 194.245.80.7 21 -j ACCEPT
ipchains -A $i -p tcp -y \
-d 194.245.80.7 23 -j ACCEPT
ipchains -A $i -p tcp -y \
-d 194.245.80.7 43 -j ACCEPT
ipchains -A $i -p tcp ! -y \
-d 194.245.80.7 -j ACCEPT
# unreachables
ipchains -A $i -p icmp -s 0/0 3 \
-d 194.245.80.7 -j ACCEPT
# source-quench
ipchains -A $i -p icmp -s 0/0 4 \
-d 194.245.80.7 -j ACCEPT
# time exceeded (von der Kiste aus sind traceroutes manchmal sinnvoll)
ipchains -A $i -p icmp -s 0/0 11 \
-d 194.245.80.7 -j ACCEPT
ipchains -A $i \
-d 194.245.80.7 -l -j REJECT
# und die letzte Regel: _bye_.
ipchains -A $i -l -j DENY
In die Bootscripte koennte etwa das kommen:
ipchains -P input DENY ipchains -P forward ACCEPT ipchains -P output ACCEPT ipchains -N cslin ...oben genannter code... mit $i == cslin ipchains -A input -i eth0 -j ACCEPT ipchains -I input -i lo -j ACCEPTip-up koennte dann etwa dies tun:ipchains -A input -i $1 -j cslinund ip-down:ipchains -D input -i $1 -j cslin
Fazit
Copyright (C) 1998 Uwe Ohse.
Verbatim copying and distribution is permitted in any medium, provided this notice is preserved.