Firewall

Einerseits um das System abzudichten, und um andererseits den Traffic an die korrekten Stellen weiterzuleiten setze ich pf ein.

Hier meine /etc/pf.conf. Diese enthält mehr als nur für die Jails benötigt wird, aber ich finde, so werden alle Zusamenhänge besser ersichtlich:

# interfaces
if_ext = "em0"
if_lo0 = "lo0"
if_lo1 = "lo1"

# externe Adressen des Hosts
ip_ext4 = "11.22.33.44"
ip_ext6 = "2a11:22:33:44::1"

# interne Adressen der Reverse-Proxy Jail
ip_jailproxy4 = "10.23.42.2"
ip_jailproxy6 = "fd10:23:42:23::2"

# Dienste die am Host laufen (ssh & mosh)
inbound_tcp = "{ ssh }"
inbound_udp = "{ 60000:60010 }"

# Dienste die in den Jails laufen (web)
j_inbound_tcp = "{ http, https }"
#j_inbound_udp = "{}"

# Dienste die der Host erreichen darf
outbound_tcp = "{ ssh, domain, http, https, ftp }"
outbound_udp = "{ domain, ntp }"

# ICMP Konfiguration
icmp4_types = "{ echoreq, unreach }"
icmp6_types = "{ echoreq, echorep, unreach, toobig, timex, routersol, routeradv, neighbrsol, neighbradv, redir }"

# Jeglichen Traffic auf den Loopbacks erlauben
set skip on $if_lo0
set skip on $if_lo1

# Kein Reject schicken, nur Droppen
set block-policy drop

# Einkommenden Traffic defragmentieren und normalisieren
scrub in on $if_ext all fragment reassemble

# Traffic aus den Jails raus geht durch ein NAT
nat pass on $if_ext inet from $if_lo1:network to any -> $ip_ext4
nat pass on $if_ext inet6 from $if_lo1:network to any -> $ip_ext6

# Traffic in die Jails rein weiterleiten
rdr pass on $if_ext inet proto tcp from any to $if_ext:network port $j_inbound_tcp -> $ip_jailproxy4
#rdr pass on $if_ext inet proto udp from any to $if_ext:network port $j_inbound_udp -> $ip_jailproxy4
rdr pass on $if_ext inet6 proto tcp from any to $if_ext:network port $j_inbound_tcp -> $ip_jailproxy6
#rdr pass on $if_ext inet6 proto udp from any to $if_ext:network port $j_inbound_udp -> $ip_jailproxy6

# Default - Alles blockieren
block log all

# Ping Pong
pass inet proto icmp all icmp-type $icmp4_types keep state
pase inet6 proto icmp6 al icmp6-type $icmp6_types keep state

# Der Host darf Dienste außerhalb erreichen
pass out proto tcp to any port $outbound_tcp keep state
pass out proto udp to any port $outbound_udp keep state

# Dienste auf dem Host dürfen von außen erreicht werden
pass in log proto tcp to any port $inbound_tcp keep state
pass in log proto udp to any port $inbound_udp keep state

Mit dem schönen Kommando pfctl -vnf /etc/pf.conf kann man überprüfen, ob das Config-File korrekt ist.

Zum neustarten von pf empfiehlt sich folgender Trick:

service pf restart ; sleep 120 && service pf stop

Sollte man sich beim Starten vom Host aussperren, dann wird nach 2 Minuten die Firewall wieder abgeschalten - Somit kann man sich dann noch wenigstens wieder einloggen, um den Fehler zu beheben…

Vor dem Starten von pf in der /etc/rc.conf diese aktivieren:

pf_enable="YES"
pf_rules="/etc/pf.conf"
pf_flags=""
pflog_enable="YES"
pflog_logfile="/var/log/pflog"
pflog_flags=""

Weil wir schon dabei sind am Netzwerk zu frickeln, sollten wir uns jetzt darum kümmern, dass alle Dienste nicht global auf Wildcard Adressen lauschen. Ein immer wiederkehrender Kandidat ist z.B. NTP.

Und nun geht es endlich daran, die ersten Jails zu erstellen: Eine Webserver Jail und die Reverse-Proxy Jail.