Tags

bluetooth cu ipfw shell unbound

Powered by

blOg
maRkdown
awK
shEll

21/11/2020

[ ipfw shell ]

202011211200 ipfw shell

ipfw: modern FreeBSD (reloaded)

Après plusieurs mois de production, petit retour sur mon script de mur de feu.

Rappels

Ma configuration générale se trouve dans /etc/rc.conf.d et je n'ai pas de /etc/rc.conf. La configuration du mur de feu se trouve donc dans le répertoire /etc/rc.conf.d/ipfw. Jouer à distance avec un mur de feu peut vite devenir périlleux: une typo, une mauvaise règle et patatra le mur s'écroule, emportant avec lui la connexion ssh. Pour éviter ces désagréments:

Plus d'explication dans mon premier billet où on trouvera aussi le pourquoi du modern FreeBSD. Attention, ce script ne convient pas à un hôte de type routeur.

Le script

Après quelques évolutions, j'arrive à ce résultat http://download.bsdsx.fr/rc.firewall:

$ cat -n /etc/rc.conf.d/rc.firewall
 1	set -e
 2	
 3	table_create() {
 4		$fwcmd table $1 create type ${2:-addr} ${3:-}
 5	}
 6	
 7	table_load_addr() {
 8		local table=$1
 9		local files=""
10		local addrs=""
11	
12		for arg in $@; do
13			case $arg in
14				/*)
15					[ -f $arg ] || continue
16					files="$files $arg"
17					;;
18				[0-9a-fA-F]*)
19					addrs="$addrs $arg";;
20			esac
21		done
22		(echo $addrs; cat ${files:-/dev/null}) | sed -E -n -e 's/#.*//' -e 's/([[:xdigit:]:\.\/]+)/\1 0/gp' | tr ',' "\n" | sort --unique --ignore-leading-blanks | xargs $fwcmd table $table atomic add
23	}
24	
25	set_31() {
26		[ ${firewall_debug} = 'NO' -a $($fwcmd set 31 list | wc -l) -gt 1 ] && return
27	
28		table_create t_pouilleux
29		table_create t_ssh
30	
31		table_load_addr t_ssh ${firewall_ssh6:-} ${firewall_ssh4:-} ${firewall_t_ssh:-}
32		table_load_addr t_pouilleux ${firewall_t_pouilleux:-}
33	
34		$add set 31 check-state :KS
35		if $fwcmd table t_ssh info | grep -q 'items: 0'; then
36			$add set 31 deny in lookup src-ip t_pouilleux
37			$add set 31 pass { dst-port ssh or src-port ssh }
38		else
39			$add set 31 pass src-port ssh
40			$add set 31 pass in dst-port ssh lookup src-ip t_ssh
41			$add set 31 deny in dst-port ssh
42			$add set 31 deny in lookup src-ip t_pouilleux
43		fi
44		$add set 31 pass { proto ipv6-icmp or proto icmp }
45	}
46	. /etc/rc.subr
47	load_rc_config ipfw
48	
49	set -u
50	
51	[ $# -eq 1 ] && [ $1 = "-d" ] && firewall_debug=YES
52	
53	fwcmd=/sbin/ipfw
54	case ${firewall_quiet:-} in
55		[Yy][Ee][Ss]) fwcmd="$fwcmd -q";;
56	esac
57	
58	case ${firewall_debug:-NO} in
59		[Yy][Ee][Ss]) fwcmd="echo $fwcmd";;
60		*) firewall_debug='NO';;
61	esac
62	
63	add="$fwcmd add"
64	
65	set_31
66	
67	KS="keep-state :KS"
68	
69	$fwcmd -f flush
70	
71	$add pass via lo*
72	
73	[ -f $0.$(hostname) ] && . $0.$(hostname)
74	
75	$add pass out $KS // after NAT
76	case ${firewall_logging:-} in
77	    [Yy][Ee][Ss])
78			for ports in ${firewall_nologports:-}; do
79				$add deny in dst-port $ports
80			done
81			;;
82	esac
83	$add deny log in
84	
85	# vim: set sw=4 sts=4 ts=4 ft=sh:

Avec ce script et sans configuration je ne peux pas perdre l'accès ssh mais ce service est ouvert à tous les pouilleux, rabouins, peignes-cul et autres pénibles du nain ternet.

La configuration de base

$ cat -n /etc/rc.conf.d/ipfw/ipfw
 1  firewall_enable="YES"
 2  firewall_script="/etc/rc.conf.d/rc.firewall"
 3
 4  # logging == syslogd, logif == tcpdump
 5  #firewall_logging="YES"
 6  firewall_logif="YES"
 7
 8  ip6_dead="2001:db8:dead::/48"
 9  ip6_beef="2001:db8:beef::/48"
10  ip6_cafe="2001:db8:cafe:cafe::/64"
11
12  ip4_maison="192.168.42.0/24 192.168.84.0/24, 10.10.0.0/16"
13
14  firewall_ssh6="$ip6_dead, $ip6_beef $ip6_cafe"
15  firewall_ssh4="$ip4_maison"

Pour tester et vérifier (ne pas hésiter à faire volontairement des typos dans les adresses et observer le résultat):

$ /bin/sh /etc/rc.conf.d/rc.firewall -d
/sbin/ipfw table t_pouilleux create type addr
/sbin/ipfw table t_ssh create type addr
/sbin/ipfw table t_ssh atomic add 10.10.0.0/16 0 2001:db8:beef::/48 0 2001:db8:cafe:cafe::/64 0 192.168.42.0/24 0 192.168.84.0/24 0 2001:db8:dead::/48 0
/sbin/ipfw add set 31 check-state :KS
/sbin/ipfw add set 31 pass src-port ssh
/sbin/ipfw add set 31 pass in dst-port ssh lookup src-ip t_ssh
/sbin/ipfw add set 31 deny in dst-port ssh
/sbin/ipfw add set 31 deny in lookup src-ip t_pouilleux
/sbin/ipfw add set 31 pass { proto ipv6-icmp or proto icmp }
/sbin/ipfw -f flush
/sbin/ipfw add pass via lo*
/sbin/ipfw add pass out keep-state :KS // after NAT
/sbin/ipfw add deny log in

Une configuration xen (non finalisée)

$ cat /etc/rc.conf.d/rc.firewall.xen.bsdsx.fr
table_create t_unbound addr or-flush && table_load_addr t_unbound ${firewall_unbound6:-} ${firewall_unbound4:-} ${firewall_t_unbound:-}

$add pass in dst-port domain lookup src-ip t_unbound $KS
$add pass in dst-port http $KS

$add pass in src-port bootpc via xnb*
$add pass in dst-port ntp,syslog,546 via xnb*
$add pass in src-port bootps via vlan22

Cette machine fournit un service dns à accès restreint, un service http non restreint et laisse passer du traffic en provenance/destination des domU (j'y reviendrais certainement dans un autre billet).

A venir

J'ai abandonné l'idée de mur de feu entièrement pilotable à coup de variables, le code nécessaire pour définir un service était beaucoup trop volumineux. L'utilisation d'un script local à l'hôte me parait plus simple. La prochaine évolution concernera le nat et des règles qui, je l'espère, sortiront des sentiers battus.

Commentaires: https://github.com/bsdsx/blog_posts/issues/6


Lien vers ce billet