Firewall mit OpenBSD 3.4
Technischer Stand: Jahr 2001. Dieser Artikel wird nicht mehr aktualisiert.
Ab Version 3 ist in OpenBSD eine neue Variante von Firewall enthalten. Die hier gezeigten Konfigurationsdateien gelten nicht für frühere Versionen 2.x. Sie werden nicht um das Studium der Regelsprache herumkommen, wenn Sie die Regeln an Ihre Bedürfnisse anpassen.
Die Einstellungen, die Sie zum Betrieb eines
öffentlichen
Hotspots benötigen, sind hier bereits berücksichtigt.
DHCP
DHCP ist so konfiguriert, daß Rechner, die immer dieselbe IP-Adresse haben sollen (alle im WLAN, die Server im Festsegment), nach ihrer MAC-Adresse unterschieden werden. Alle "Gäste" bekommen eine Adresse aus dem Bereich "range ..." zugewiesen.
$ cat /etc/dhcpd.conf
option domain-name "intra.barnim.net"; option domain-name-servers 192.168.1.11, 192.168.1.12; option netbios-name-servers 192.168.1.13, 192.168.1.14;
Das feste Teilnetz:
subnet 192.168.1.0 netmask 255.255.255.0 {
option routers 192.168.1.1;
default-lease-time 14400;
range 192.168.1.64 192.168.1.255;
host server1 {
hardware ethernet 01:23:45:67:89:AB;
fixed-address 192.168.1.2;
}
host server2 {
hardware ethernet 12:34:56:78:9A:BC;
fixed-address 192.168.1.3;
}
}
Das private WLAN: (Dynamische IP-Adressen sind hier nicht erlaubt.)
subnet 192.168.2.0 netmask 255.255.255.0 {
option routers 192.168.2.1;
default-lease-time 7200;
range 192.168.2.0 192.168.2.0;
host esther {
hardware ethernet 23:45:67:89:AB:CD;
fixed-address 192.168.2.2;
default-lease-time 86400;
}
host client1 {
hardware ethernet 34:56:78:9A:BC:DE;
fixed-address 192.168.2.15;
}
}
Der öffentliche Hotspot: (Unerwünschte MAC-Adressen lassen sich explizit aussperren.)
subnet 192.168.3.0 netmask 255.255.255.0 {
option routers 192.168.3.1;
default-lease-time 7200;
range 192.168.3.64 192.168.3.255;
host tobit {
hardware ethernet 45:67:89:AB:CD:EF;
fixed-address 192.168.3.2;
default-lease-time 86400;
}
host verboten {
hardware ethernet FE:DC:BA:98:76:54;
fixed-address 192.168.3.0;
default-lease-time 86400;
}
}
Filterregeln
$ cat /etc/pf-all.conf
# pf-all.conf for OpenBSD 3.4 # (c) Thomas Bez 2003 # http://www.bez.tedesca.net
Nach Aufbau der Verbindung ins Internet bzw. nach Verbindungsende werden die Firewallregeln jeweils neu geladen. Mit dem Makroprozessor m4 werden beide Regelsätze (mit/ohne externe Verbindung) aus derselben Quelle erzeugt.
# define these on the commandline # EXTERN with internet connection define(EXTERN) # use e.g. in /etc/ppp/ppp.linkup: # m4 -DEXTERN=1 </etc/pf-all.conf >/etc/pf.conf # /sbin/pfctl -f /etc/pf.conf # in /etc/ppp/ppp.linkdown: # m4 -DEXTERN=0 </etc/pf-all.conf >/etc/pf.conf # /sbin/pfctl -f /etc/pf.conf # these options switched on # WLAN secured WLAN # HOTSPOT public hotspot with internet access define(WLAN,1) define(HOTSPOT,1) # these options switched off # PUBLICSERVICE is for fallback, to provide HTTP and SMTP service if Hiob is out of order define(PUBLICSERVICE,0)
Es beginnt mit einigen Definitionen. Die Segmente sind über unterschiedliche Schnittstellen angeschlossen, was zwar nicht unbedingt erforderlich, aber sehr empfehlenswert ist. Die verschiedenen Netzwerkkarten können selbstverständlich typgleich sein.
################################################################################# # common ################################################################################# #=== interfaces =========================================================== loopback = "lo0" intern = "if1" ifelse(WLAN,1,` wlan = "if2" ') ifelse(HOTSPOT,1,` hotspot = "if3" ') ifelse(EXTERN,1,` extern = "tun0" ') #=== segments =========================================================== # it is not really like this ;-) my_privatenet = "192.168.0.0/16" other_privatenet = "10.0.0.0/8, 172.16.0.0/12" fixed_segment = "192.168.1.0/24" wlan_segment = "192.168.2.0/24" hotspot_segment = "192.168.3.0/24" office2_segment = "192.168.4.0/24" dialin_segment = "192.168.5.0/24" fixed_broadcast = "192.168.1.255/32" wlan_broadcast = "192.168.2.255/32" hotspot_broadcast = "192.168.3.255/32" office2_broadcast = "192.168.4.255/32" dialin_broadcast = "192.168.5.255/32"
Die hier angegebenen DHCP-Adreßbereiche müssen natürlich zu denen in dhcpd.conf passen.
# addresses assigned by dhcp for free access; only registered clients in wlan fixed_dhcp_free = "192.168.1.0/24, ! 192.168.1.0/26" wlan_dhcp_free = "192.168.2.0/32" hotspot_dhcp_free = "192.168.3.0/24, ! 192.168.3.0/26" localhost = "127.0.0.1/32" localhost_segment = "127.0.0.0/8" broadcast = "255.255.255.255/32" allhosts_multicast = "224.0.0.1/32" #=== stations =========================================================== # jona = firewall (this machine) jona = "192.168.1.1/32" fixed_gateway = "192.168.1.1/32" wlan_gateway = "192.168.2.1/32" hotspot_gateway = "192.168.3.1/32" # fixed segment servers server1 = "192.168.1.2/32" server2 = "192.168.1.3/32" dialin_server = "192.168.1.4/32" # access points (wlan & hotspot) esther = "192.168.2.2/32" tobit = "192.168.3.2/32" # office 2 segment with wl router maleachi = "192.168.2.3/32" office2_gateway = "192.168.4.1/32" # dialin interfaces (analog, ISDN) dialin_server = "192.168.5.1/32" dialin_client = "192.168.5.2/32"
Alle Sammlungen von Adressen werden in Form von Tabellen angelegt. "Office2" ist ein abgesetztes Segment hinter einem WLAN-Router, das einer separaten Verwaltung seiner IP-Adressen 192.168.4.0/24 unterworfen ist.
#=== address collections ===========================================================
table <privatenet> const { $my_privatenet, $other_privatenet }
table <dialin_universe> const { $dialin_segment }
table <firewall> const { $fixed_gateway, $wlan_gateway, $hotspot_gateway }
table <wlan_ap> const { $esther }
table <hotspot_ap> const { $tobit }
table <wlan_universe> const { $wlan_segment, $office2_segment }
table <wlan_broadcast> const { $wlan_broadcast, $office2_broadcast }
table <dhcpservers> const { $secret }
table <nameservers> const { $secret }
table <squidproxy> const { $secret }
table <intern_permitted> const { $secret }
table <dialin_permitted> const { $secret }
table <wlan_permitted> const { $secret }
table <hotspot_permitted> const { $secret }
Adreßsammlungen, die den Firewallrechner ("Jona") selbst beinhalten, müssen um die externe IP-Adresse erweitert werden, sobald eine Verbindung zum Internet besteht.
ifelse(EXTERN,1,`
# with internet access
# define to cover also our temporary official ip address (tun0)
table <intranet> { $fixed_segment, $office2_segment, $wlan_segment, \
$hotspot_gateway, $dialin_segment, tun0 }
table <protected_networks> { $localhost_segment, $fixed_segment, $office2_segment, \
$wlan_segment, $hotspot_segment, $dialin_segment, \
$other_privatenet, tun0 }
table <internal_addrspace> { $my_privatenet, $other_privatenet, tun0 }
table <ftp_proxy> { $jona, tun0 }
table <tunnel> { tun0 }
',`
# without internet access
table <intranet> { $fixed_segment, $office2_segment, $wlan_segment,
$hotspot_gateway, $dialin_segment }
table <protected_networks> { $localhost_segment, $fixed_segment, $office2_segment, \
$wlan_segment, $hotspot_segment, $dialin_egment, \
$other_privatenet }
table <internal_addrspace> { $my_privatenet, $other_privatenet }
table <ftp_proxy> { $jona }
table <tunnel> { }
')
Wenn die externe IP-Adresse ("tun0") hier nicht mit ausgeschlossen wird, eröffnet das phantastische Zugriffsmöglichkeiten aus dem Hotspot auf das eigentlich zu schützende Netz.
# very important: our official IP address (tun0) must be excluded here, too
internet = "! <internal_addrspace>"
#=== miscellaneous ===========================================================
# normally we do no portscans; if we want, we have to alter this table before
# (standard policy is to block even some destination ports)
table <portscanned> { 0.0.0.0/32 }
# flags S actually equates to flags S/AUPRFS and matches against only the SYN packet
# out of all six possible flags, while flags S/SA will allow packets that may
# or may not have the URG, PSH, FIN, or RST flags set. Some protocols demand the
# URG or PSH flags, and flags S/SAFR would be a better choice for these.
# this is also a measure against SYN/FIN attacks.
syn_only = "S/SAFR"
# inetd: /usr/libexec/ftp-proxy -m 20000 -M 30000
ftp_range = "19999><30001"
# never log events on these ports
netbios_quiet = "netbios-ns, netbios-dgm, netbios-ssn"
# traffic going out on these ports is common, do not log
# 370=Back web agent
uncrit_udp_out = "domain, ntp, socks, 370"
uncrit_tcp_out = "www, 81, 8079, 8080, 8081, https, ftp, ssh, smtp, pop3, pop3s"
hotspot_uncrit_udp_out = "ntp"
hotspot_uncrit_tcp_out = "www, https, ftp, smtp, pop3, pop3s"
# allow these but log
allow_udp_out = "socks"
allow_tcp_out = "0><135, 135><65535, 65535"
hotspot_allow_udp_out = "0><65535, 65535"
hotspot_via_squid = "www, https, ftp"
hotspot_deny_tcp_out = "www, https, ftp, 135"
hotspot_allow_tcp_out = "0><65535, 65535"
# if we want to be more conservative on allowed tcp destination ports:
# 1214=Kazaa 2703=razor 5999=cvsup 6346,6347,666x=gnucleus 11370f=PGP
#allow_tcp_out = "auth, whois, finger, nntp, socks, 1214, 2703, 5999, 6346, 6347, 6659><6670, 11370, 11371"
# remaining destination ports will be blocked
# tcp 135 is blocked because this is a common virus attack (if we got this virus, we do not want to spread it)
# may be also set to empty string
tcp_source_port_restriction = "port > 1023"
Der FTP-Proxy erlaubt vollen FTP-Zugriff (aktives und passives FTP) durch Firewalls.
ftpproxy_host = "127.0.0.1/32" ftpproxy_port = "8021"
Wenn Hotspot-Benutzer einen Webzugriff ohne Squid-Proxy versuchen, werden sie hierher umgeleitet. Im Fall von Barnim.Net ist das diese Seite.
# information for hotspot users hotspot_ihost = "1.2.3.4/32" hotspot_iport = "8080"
Unerlaubte TCP- oder UDP-Zugriffe werden explizit zurückgewiesen. Schweigend unterdrückte Zugriffe zeigen sofort, daß hier eine Firewall am Werk ist.
################################################################################# # policy ################################################################################# set block-policy return
Fragmentierte IP-Pakete werden an den kritischen Schnittstellen erst komplett zusammengesetzt, bevor sie weitergereicht werden.
################################################################################# # normalise packets ################################################################################# ifelse(HOTSPOT,1,` scrub in on $hotspot all random-id fragment reassemble scrub on $hotspot proto tcp all reassemble tcp ') ifelse(EXTERN,1,` scrub in on $extern all random-id fragment reassemble scrub on $extern proto tcp all reassemble tcp ') ################################################################################# # NAT ################################################################################# # redirect FTP to ftp-proxy: rdr on $intern proto tcp from any to any port ftp -> $ftpproxy_host port $ftpproxy_port ifelse(WLAN,1,`rdr on $wlan proto tcp from any to any port ftp -> $ftpproxy_host port $ftpproxy_port')
Umleitung von Hotspotbenutzern, die einen direkten WWW-Zugriff versuchen.
ifelse(HOTSPOT,1,`rdr on $hotspot proto tcp from any to any port www -> $hotspot_ihost port $hotspot_iport')
Einige wenige Zugriffe von außen sind erlaubt.
ifelse(EXTERN,1,`
rdr on $extern proto tcp from any to $extern port ssh -> $server1 port ssh
ifelse(PUBLICSERVICE,1,`
rdr on $extern proto tcp from any to $extern port http -> $server2 port http
')
')
ifelse(EXTERN,1,`
nat on $extern from $my_privatenet to any -> $extern
')
#################################################################################
# filtering
#################################################################################
Diese Regeln fangen allen nicht explizit spezifizierten Verkehr auf.
# block all by default block out log all block in log all #=== LOOPBACK =========================================================== pass out quick on $loopback all pass in quick on $loopback all #=== DIALIN ===============================================================
Ein eingewählter Rechner hat freien Zugriff auf das Internet und kann die internen Nameserver nutzen. Es gibt freilich noch weitere Möglichkeiten, die hier aber nicht gezeigt sind. (Leichte Übung, dies zu ergänzen.)
pass in quick proto udp from $dialin_client to <nameservers> port domain keep state pass in quick proto udp from $dialin_client to $internet keep state tag "dialin" pass in quick proto tcp from $dialin_client to $internet keep state tag "dialin" block in quick proto udp from $dialin_segment to any port domain block in log quick from $dialin_segment to any block out log quick from any to $dialin_segment #=== INTERN ===========================================================
Diese Regeln ermöglichen den Rechnern im Segment, sich um eine IP-Adresse zu bewerben.
# DHCP pass in log quick on $intern proto udp from any port bootpc to $broadcast port bootps pass out log quick on $intern proto udp from <dhcpservers> port bootps to $broadcast port bootpc pass in log quick on $intern proto udp from $hotspot_segment port bootpc to <dhcpservers> port bootps pass out log quick on $intern proto udp from <dhcpservers> port bootps to $hotspot_segment port bootpc pass out quick on $intern from any to <intern_permitted> pass in quick on $intern from <intern_permitted> to any #=== HOTSPOT =========================================================== ifelse(HOTSPOT,1,`
Diese Regeln ermöglichen dem Hotspot-Benutzer, sich um eine IP-Adresse zu bewerben.
# DHCP pass in log quick on $hotspot proto udp from any port bootpc to $broadcast port bootps pass out log quick on $hotspot proto udp from <dhcpservers> port bootps to $broadcast port bootpc pass in log quick on $hotspot proto udp from $hotspot_segment port bootpc to <dhcpservers> port bootps pass out log quick on $hotspot proto udp from <dhcpservers> port bootps to $hotspot_segment port bootpc # anti-spoofing block in log quick on $hotspot from ! $hotspot_segment to any # special attacks # FIN, URG, and PSH flags are used for nmap OS fingerprinting attempt block in log quick on $hotspot inet proto tcp from any to any flags FUP/FUP # allow from intranet to hotspot member pass out quick on $hotspot inet proto icmp from <intranet> to $hotspot_segment icmp-type echoreq keep state
Squid-Proxy und DNS sind die einzigen Dienste, die wir dem Hotspotbenutzer zur Verfügung stellen.
# allow from hotspot to intranet pass in quick on $hotspot proto tcp from <hotspot_permitted> to <squidproxy> port 3128 keep state pass in quick on $hotspot proto udp from <hotspot_permitted> to <nameservers> port domain keep state
Datenpakete, die aus dem Hotspot in das Internet fließen sollen, werden markiert. Im Teil "EXTERN" werden wir diese später (fast) alle ungehindert durchlassen. Aktivitäten auf ungewöhnlichen Ports werden aber geloggt.
# allow from hotspot to internet
# let it in, tag it, let it out on $extern with (virtually) no further checks
pass in quick on $hotspot inet proto icmp from <hotspot_permitted> to $internet keep state tag "hotspot"
pass in quick on $hotspot proto udp from <hotspot_permitted> to $internet port { $hotspot_uncrit_udp_out } \
keep state tag "hotspot"
pass in log quick on $hotspot proto udp from <hotspot_permitted> to $internet keep state tag "hotspot"
pass in log quick on $hotspot proto tcp from <hotspot_permitted> to $hotspot_ihost port $hotspot_iport \
modulate state tag "hotspot"
block in log quick on $hotspot proto tcp from any to $internet port { $hotspot_deny_tcp_out }
pass in quick on $hotspot proto tcp from <hotspot_permitted> to $internet port { $hotspot_uncrit_tcp_out } \
flags $syn_only modulate state tag "hotspot"
pass in log quick on $hotspot proto tcp from <hotspot_permitted> to $internet port { $hotspot_allow_tcp_out } \
flags $syn_only modulate state tag "hotspot"
# catch quiet
block out quick on $hotspot proto udp from any port { $netbios_quiet, route } to $hotspot_segment
block in quick on $hotspot proto udp from $hotspot_segment to any port { $netbios_quiet, route, domain }
# catch all
block out log quick on $hotspot all
block in log quick on $hotspot all
')
#=== WLAN ===========================================================
ifelse(WLAN,1,`
Dynamische Adressen werden im WLAN nicht vergeben. Wenn das Logfile eine Aktivität dieser Regeln verzeichnet, wird es höchste Zeit, den WiFi-Schlüssel zu ändern.
# lock & monitor "free" wlan dhcp segment block in log quick on $wlan from any to $wlan_dhcp_free block out log quick on $wlan from $wlan_dhcp_free to any # DHCP pass in log quick on $wlan proto udp from any port bootpc to $broadcast port bootps pass out log quick on $wlan proto udp from <dhcpservers> port bootps to $broadcast port bootpc pass in log quick on $wlan proto udp from <wlan_universe> port bootpc to <dhcpservers> port bootps pass out log quick on $wlan proto udp from <dhcpservers> port bootps to <wlan_universe> port bootpc # anti-spoofing block in log quick on $wlan from ! <wlan_universe> to any # special attacks # FIN, URG, and PSH flags are used for nmap OS fingerprinting attempt block in log quick on $wlan inet proto tcp from any to any flags FUP/FUP
So schlicht sind die Regeln natürlich in Wirklichkeit nicht.
# allow
# it is not really like this ;-)
pass out quick on $wlan all
pass in quick on $wlan all
# catch quiet
block out quick on $wlan proto udp from any port { $netbios_quiet, route } to <wlan_universe>
block in quick on $wlan proto udp from <wlan_universe> to any port { $netbios_quiet, route, domain }
# catch all
block out log quick on $wlan all
block in log quick on $wlan all
')
#=== EXTERN ===========================================================
ifelse(EXTERN,1,`
Solange dieser Regelsatz nicht aktiv ist, wird aller Verkehr auf $extern durch die Regeln unter "block all by default" blockiert.
# block outgoing packets that do not have my address as source. "never happens", something should be wrong block out log quick on $extern from ! tun0 to any # anti-spoofing block in quick on $extern from any to $broadcast block in log quick on $extern from $broadcast to any block in log quick on $extern from <privatenet> to any block in log quick on $extern from $localhost_segment to any block in log quick on $extern from <intranet> to any block out quick on $extern from any to $broadcast block out quick on $extern from any to <privatenet> block out quick on $extern from any to $localhost_segment # special attacks # FIN, URG, and PSH flags are used for nmap OS fingerprinting attempt block in log quick on $extern inet proto tcp from any to any flags FUP/FUP # open for scanning pass out quick on $extern proto tcp from any to <portscan> flags $syn_only keep state pass out quick on $extern proto udp from any to <portscan> keep state
Ein klitzekleines "Ping" wollen wir uns schon gönnen. Was die Nutzer des Hotspots treiben, soll uns hier nichts angehen. Wenn wir den Hotspot um Sicherheitsmerkmale verfeinern wollten, könnten wir das unter anderem hier tun.
#----- icmp -------------------------------------------------------------------------------------------------------- pass in quick on $extern inet proto icmp from any to <firewall> icmp-type echoreq keep state pass out quick on $extern inet proto icmp from <intranet> to any icmp-type echoreq keep state
Gekennzeichnete Datenpakete vom Hotspot oder einem eingewählten Rechner dürfen passieren.
pass out quick on $extern inet proto icmp all tagged "hotspot" keep state
pass out quick on $extern inet proto icmp all tagged "dialin" keep state
# catch all ICMP
block in log quick on $extern proto icmp all
block out log quick on $extern proto icmp all
#----- udp ---------------------------------------------------------------------------------------------------------
# ignore cable modem noise and do not log:
block in quick on $extern proto udp from any to $broadcast
pass out quick on $extern proto udp from <intranet> to any port { $uncrit_udp_out } keep state
pass out log quick on $extern proto udp from <intranet> to any port { $allow_udp_out } keep state
pass out quick on $extern proto udp all tagged "hotspot" keep state
# catch quiet
block in quick on $extern proto udp from any to any port { $netbios_quiet, route, 4660><4666 }
block out quick on $extern proto udp from any port { $netbios_quiet, route } to any# catch all UDP
block in log quick on $extern proto udp all
block out log quick on $extern proto udp all
#----- tcp ---------------------------------------------------------------------------------------------------------
# services to the public
pass in quick on $extern proto tcp from any to $server1 port ssh flags $syn_only synproxy state
ifelse(PUBLICSERVICE,1,`
pass in quick on $extern proto tcp from any to $server2 port http flags $syn_only synproxy state
')
# active FTP traffic is going via ftp-proxy
pass in quick on $extern proto tcp from any port ftp-data to <ftp_proxy> port $ftp_range \
flags $syn_only synproxy state
pass out quick on $extern proto tcp from <intranet> to any port { $uncrit_tcp_out } flags $syn_only modulate state
pass out quick on $extern proto tcp all tagged "hotspot" keep state
# passive FTP
pass out quick on $extern proto tcp from <intranet> port $ftp_range to any port > 1023 flags $syn_only modulate state
# allow anything out
pass out log quick on $extern proto tcp from <intranet> $tcp_source_port_restriction to any port { $allow_tcp_out } \
flags $syn_only modulate state
# catch quiet
block in quick on $extern proto tcp from any to any port { auth, $netbios_quiet, 1214, 4462, 4660><4666 }
# any other SYN combination is disallowed:
block in log quick on $extern proto tcp all flags S/S
# catch all TCP
block in log quick on $extern proto tcp all
block out log quick on $extern proto tcp all
# other protocols
# none
')
Ja, etwas Arbeit steckt schon darin. Sie kriegen es geschenkt. Viel Spaß damit.
IDS
Wer sich mit Firewall noch unsicher fühlt, kann Eingang wie Ausgang mit einem Intrusion Detection System (IDS) bewachen. Die Software dafür gibt es unter www.snort.org, sie ist problemlos zu installieren. Das Auswerten ist nicht mehr ganz so einfach. Am Ausgang (Innenseite der Firewall) ist nur viel los, wenn Sie sich ein Trojanisches Pferd eingefangen haben. Am Eingang können Sie beobachten, wie schlecht die Welt doch ist.
Auch dabei viel Spaß.