Deux changement notables : passage de IPF à PF en version 3.0, puis changement des fichiers de conf PF à partir de la version 3.2.
NAT et PF sont désormais concaténés en un seul fichier, /etc/pf.conf. Les règles nat doivent être mises au début, et les rdr doivent bien spécifier les protos utilisés (tcp/udp).
Le fichier /etc/rc.conf active les services au démarrage et permet notamment d'activer les règles NAT et PF. J'ai personnellement désactivé inetd au passage, n'en ayant pas l'utilité..
# /etc/rc.conf pf=YES # Packet filter (+ NAT pour versions > 3.2) pf_rules=/etc/pf.conf # Packet filter rules file nat_rules=/etc/nat.conf # NAT rules file (versions < 3.2 uniquement) inetd=NO # almost always needed
Personnellement je natte toutes mes adresses internes vers l'IP externe de la passerelle (!transparent), et redirrige les requêtes en entrée (ssh et web) vers le serveur linux :
nat on tun0 proto tcp from 192.168.10.0/24 to any -> tun0 rdr on tun0 proto tcp from any to any port 80 -> 192.168.10.1 port 80 rdr on tun0 proto tcp from any to any port 22 -> 192.168.10.1 port 22
ATTENTION : la conf ci dessus est la plus communément rencontrée sur le
net. Toutefois, il m'est souvent arrivé que les règles NAT ne soient pas
chargées au démarrage de la machine, car PPP n'a pas encore négocié la
connection au moment où elles essaient de se charger. Dans le cas d'une IP
fixe on peut régler le problème en remplaçant le 2ème tun0 de première ligne
directement par sa propre IP. Sinon, voir comment lancer tout ça proprement et
surtout dans l'ordre en section 3.2.2.
Une fois nat.conf et pf.conf (ou juste pf.conf pour les versions > 3.2) déposés dans /etc :
#/etc/sysctl.conf net.inet.ip.forwarding=1 # 1=Permit forwarding (routing) of packets
pfctl -e -l tun0 -F all -O agressive -R /etc/pf.conf -N
Pour visualiser les règles PF et NAT :
pfctl -s nat pfctl -s rules pfctl -sr
La dernière fournit un peu l'équivallent de l'ancienne commande ipfstat -ion, très utile pour afficher les numéros de règles et retrouver les matchs éventuels (d'autant plus facile qu'il n'est plus question de groupes avec PF) :
% pfctl -sr @0 scrub in on vr1 all @1 scrub in on tun0 all @2 block out log on tun0 all @3 block in log on tun0 all @4 block return-rst out log on tun0 proto tcp all @5 block return-rst in log on tun0 proto tcp all @6 block return-icmp out log on tun0 proto udp all @7 block return-icmp in log on tun0 proto udp all @8 pass in quick on lo0 all @9 pass out quick on lo0 all [snip]
Pour les flusher : pfctl -F nat, pfctl -s rules ou pfctl -F all
# $OpenBSD: BlitZ pf.conf,v 1.6 2002/06/27 07:00:43 fgsch Exp $
#
#-------------------------------------------------------------------------
# Definitions et options
#-------------------------------------------------------------------------
Ext = "tun0" # External interface
Int = "rl0" # Internal interface
Tun = "gif0" # Tunnel interface (IPv6)
Loop = "lo0" # Loopback interface
Admin = "192.168.10.2"
Gateway = "192.168.10.1"
6gate = "10.1.2.3"
ExtIP = "10.8.9.10"
Residents = "{ liste d'IP, séparées par des virgules, des hôtes identifiés sur MAC address, Cf section DHCP }"
Guests = "{ Liste d'IP pour les invités ou ou les warchalkers de passage :)}"
IntNet = "{ Residents+Guests }"
NoRoute = "{ 127.0.0.1/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, 255.255.255.255/32 }"
InServicesTCP = "{ ssh, auth, http, https, domaine, smtp, uucp-path }"
InServicesUDP = "{ domain, ntp }"
set optimization aggressive # aggressively drop long idle connections
set loginterface vr0 # collect statistics on modem interface
#-------------------------------------------------------------------------
# Normalize: reassemble fragments and resolve or reduce traffic ambiguities
#-------------------------------------------------------------------------
#
scrub in all
#
#-------------------------------------------------------------------------
# NAT et redirections
#-------------------------------------------------------------------------
nat on $Ext from $IntNet to any -> $ExtIP
rdr on $Ext proto tcp from any to any port 80 -> 192.168.10.3 port 80
rdr on $Ext proto tcp from any to any port 443 -> 192.168.10.3 port 443
rdr on $Ext proto tcp from any to any port 22 -> 192.168.10.3 port 22
#-------------------------------------------------------------------------
# Defaults
# block and log everything
#-------------------------------------------------------------------------
block out log all
block in log all
block return-rst out log on $Ext proto tcp all
block return-rst in log on $Ext proto tcp all
block return-icmp out log on $Ext proto udp all
block return-icmp in log on $Ext proto udp all
block in log inet6 all
block out log inet6 all
block in log from no-route to any
block out log quick on $Ext from ! $ExtIP to any
#block in log quick on $Int from ! $IntNet to any
#--------------------------------------------------------------------------
# loopback packets left unmolested, except spoofed
antispoof for $Loop
pass in quick on $Loop all
pass out quick on $Loop all
#-------------------------------------------------------------------------
# Immediate blocks
# fuzz any 'nmap' attempt
block in log quick on $Ext inet proto tcp all flags FUP/FUP
block in log quick on $Ext inet proto tcp all flags SF/SFRA
block in log quick on $Ext inet proto tcp all flags /SFRA
# don't allow anyone to spoof non-routeable addresses
block in log quick on $Ext inet from $NoRoute to any
block out log quick on $Ext inet from any to $NoRoute
#-------------------------------------------------------------------------
# PASS rules : Tout ce que vous voulez !:)
#-------------------------------------------------------------------------
#
# Services provided to the outside world
pass in log on $Ext inet proto icmp all icmp-type 8 code 0 keep state
pass in log on $Ext inet proto tcp from any to any port $InServicesTCP flags S/SA modulate state
pass in log on $Ext inet proto udp from any to any port $InServicesUDP keep state
# Accessible services worlwide
#[snip]
# Internal Traffic to/though firewall :
#[snip]
# Internal traffic from firewall :
#[snip]
#-------------------------------------------------------------------------
# Tunnel IPv6
#-------------------------------------------------------------------------
# [snip] Cf section IPv6
#
# THE END
Je n'ai pas donné plus d'exemples de règles car c'est vraiment trop intime :-*).
C'est juste histoire de donner 2/3 idées. L'essentiel est de poser les variables
qui vont bien, les débuts de fichiers (defaults, loopback etc.) sont à peu près
valable pour n'importe quelle conf. Il reste juste à coller les ``pass in'',
facile avec une syntaxe aussi limpide que celle de Packet Filter. Et
en plus il commence à y avoir plein de docs particulièrement bien faites :
Dans cette partie je détaillerai à l'occasion comment traiter les logs IPF pour avoir un semblant de statistiques à peu près éloquentes et des alertes.
Le format du fichier de log pflog (Cf man pflogd), tout en binaire, est un peu déconcertant :) Pour le visualiser on utilise en fait tcpdump :
% tcpdump -n -e -ttt -r /var/log/pflog -l Mar 08 03:03:28.894779 rule 23/0(match): block in on tun0: 66.7.131.140.2744 > 192.168.10.1.80: S 3839108010:3839108010(0) win 16384 <mss 1452> (DF) Mar 08 03:03:42.055772 rule 23/0(match): block in on tun0: 66.7.131.140.2457 > 192.168.10.1.80: S 3800803218:3800803218(0) win 16384 <mss 1452> (DF) Mar 08 03:03:45.165773 rule 23/0(match): block in on tun0: 66.7.131.140.1126 > 192.168.10.1.80: S 3638025904:3638025904(0) win 16384 <mss 1452> (DF) Mar 08 03:03:56.047309 rule 23/0(match): block in on tun0: 66.7.131.140.1827 > 192.168.10.1.80: S 3724067823:3724067823(0) win 16384 <mss 1452> (DF)
Ou, pour visualiser en direct, par exemple ce qui se passe sur le port 80 (facultatif) :
% tcpdump -n -e -ttt -i pflog0 port 80 tcpdump: WARNING: pflog0: no IPv4 address assigned tcpdump: listening on pflog0 Dec 01 16:58:44.941848 rule 29/0(match): pass in on tun0: 217.146.225.28.2056 > 192.168.10.1.80: S 1145633000:1145633000(0) win 32120 <mss 1420,sackOK,timestamp 1072231481 0,nop,wscale 0> (DF)
pflogd peut également prendre en argument une expression de type tcpdump (port, source, interface etc.) pour logguer certains paquets à part. L'exemple fourni dans le man est le suivant :
pflogd -s 1600 -f suspicious.log port 80 and host relou