Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Nov 2009 00:13:54 +0900
From:      Hajimu UMEMOTO <ume@FreeBSD.org>
To:        Doug Barton <dougb@FreeBSD.org>
Cc:        current@FreeBSD.org, net@FreeBSD.org
Subject:   Re: [CFR] unified rc.firewall
Message-ID:  <ygek4xhjmtp.wl%ume@mahoroba.org>
In-Reply-To: <4B098D21.4040607@FreeBSD.org>
References:  <ygeljhyk1qg.wl%ume@mahoroba.org> <4B098D21.4040607@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
--Multipart_Tue_Nov_24_00:13:53_2009-1
Content-Type: text/plain; charset=US-ASCII

Hi,

>>>>> On Sun, 22 Nov 2009 11:12:33 -0800
>>>>> Doug Barton <dougb@FreeBSD.org> said:

dougb> In rc.firewall you seem to have copied afexists() from network.subr.
dougb> Is there a reason that you did not simply source that file? That would
dougb> be the preferred method. Also in that file you call "if afexists
dougb> inet6" quite a few times. My preference from a performance standpoint
dougb> would be to call it once, perhaps in a start_precmd then cache the value.

Thank you for the comments.
Ah, yes, afexists() is only in 9-CURRENT, and is not MFC'ed into 8,
yet.  So, I thought the patch should be able to work on both 9 and 8,
for review.  I've changed to source network.subr for afexists().
Calling afexists() several times was not good idea.  So, I've changed
to call afexists() just once.
The new patch is attached.

dougb> And of course, you have regression tested this thoroughly, yes? :)
dougb> Please include scenarios where there is no INET6 in the kernel as well.

Okay, I've tested it on INET6-less kernel, as well.

Sincerely,


--Multipart_Tue_Nov_24_00:13:53_2009-1
Content-Type: text/x-patch; type=patch; charset=US-ASCII
Content-Disposition: attachment; filename="ipfw-unify.diff"
Content-Transfer-Encoding: 7bit

Index: etc/Makefile
diff -u etc/Makefile.orig etc/Makefile
--- etc/Makefile.orig	2009-10-25 10:10:29.000000000 +0900
+++ etc/Makefile	2009-11-22 22:07:19.840275808 +0900
@@ -15,7 +15,7 @@
 	inetd.conf libalias.conf login.access login.conf mac.conf motd \
 	netconfig network.subr networks newsyslog.conf nsswitch.conf \
 	phones profile protocols \
-	rc rc.bsdextended rc.firewall rc.firewall6 rc.initdiskless \
+	rc rc.bsdextended rc.firewall rc.initdiskless \
 	rc.sendmail rc.shutdown \
 	rc.subr remote rpc services shells \
 	sysctl.conf syslog.conf \
Index: etc/defaults/rc.conf
diff -u etc/defaults/rc.conf.orig etc/defaults/rc.conf
--- etc/defaults/rc.conf.orig	2009-10-25 10:10:29.000000000 +0900
+++ etc/defaults/rc.conf	2009-11-22 21:25:22.343296205 +0900
@@ -118,7 +118,10 @@
 firewall_quiet="NO"		# Set to YES to suppress rule display
 firewall_logging="NO"		# Set to YES to enable events logging
 firewall_flags=""		# Flags passed to ipfw when type is a file
-firewall_client_net="192.0.2.0/24" # Network address for "client" firewall.
+firewall_client_net="192.0.2.0/24" # IPv4 Network address for "client"
+				# firewall.
+#firewall_client_net_ipv6="2001:db8:2:1::/64" # IPv6 network prefix for
+				# "client" firewall.
 firewall_simple_iif="ed1"	# Inside network interface for "simple"
 				# firewall.
 firewall_simple_inet="192.0.2.16/28" # Inside network address for "simple"
@@ -127,12 +130,22 @@
 				# firewall.
 firewall_simple_onet="192.0.2.0/28" # Outside network address for "simple"
 				# firewall.
+#firewall_simple_iif_ipv6="ed1"	# Inside IPv6 network interface for "simple"
+				# firewall.
+#firewall_simple_inet_ipv6="2001:db8:2:800::/56" # Inside IPv6 network prefix
+				# for "simple" firewall.
+#firewall_simple_oif_ipv6="ed0"	# Outside IPv6 network interface for "simple"
+				# firewall.
+#firewall_simple_onet_ipv6="2001:db8:2:0::/56" # Outside IPv6 network prefix
+				# for "simple" firewall.
 firewall_myservices=""		# List of TCP ports on which this host
 				# offers services for "workstation" firewall.
 firewall_allowservices=""	# List of IPs which have access to
 				# $firewall_myservices for "workstation"
 				# firewall.
-firewall_trusted=""		# List of IPs which have full access to this
+firewall_trusted=""		# List of IPv4s which have full access to this
+				# host for "workstation" firewall.
+firewall_trusted_ipv6=""	# List of IPv6s which have full access to this
 				# host for "workstation" firewall.
 firewall_logdeny="NO"		# Set to YES to log default denied incoming
 				# packets for "workstation" firewall.
@@ -470,13 +483,18 @@
 				# faithd(8) setup.
 ipv6_ipv4mapping="NO"		# Set to "YES" to enable IPv4 mapped IPv6 addr
 				# communication. (like ::ffff:a.b.c.d)
-ipv6_firewall_enable="NO"	# Set to YES to enable IPv6 firewall
-				# functionality
-ipv6_firewall_script="/etc/rc.firewall6" # Which script to run to set up the IPv6 firewall
-ipv6_firewall_type="UNKNOWN"	# IPv6 Firewall type (see /etc/rc.firewall6)
-ipv6_firewall_quiet="NO"	# Set to YES to suppress rule display
-ipv6_firewall_logging="NO"	# Set to YES to enable events logging
-ipv6_firewall_flags=""		# Flags passed to ip6fw when type is a file
+#ipv6_firewall_enable="NO"	# Set to YES to enable IPv6 firewall
+				# functionality (DEPRECAED)
+#ipv6_firewall_script="/etc/rc.firewall6" # Which script to run to set up the
+				# IPv6 firewall (DEPRECAED)
+#ipv6_firewall_type="UNKNOWN"	# IPv6 Firewall type (see /etc/rc.firewall6)
+				# (DEPRECAED)
+#ipv6_firewall_quiet="NO"	# Set to YES to suppress rule display
+				# (DEPRECAED)
+#ipv6_firewall_logging="NO"	# Set to YES to enable events logging
+				# (DEPRECAED)
+#ipv6_firewall_flags=""		# Flags passed to ip6fw when type is a file
+				# (DEPRECAED)
 ipv6_ipfilter_rules="/etc/ipf6.rules"	# rules definition file for ipfilter,
 					# see /usr/src/contrib/ipfilter/rules
 					# for examples
Index: etc/rc.d/Makefile
diff -u etc/rc.d/Makefile.orig etc/rc.d/Makefile
--- etc/rc.d/Makefile.orig	2009-10-25 10:10:29.000000000 +0900
+++ etc/rc.d/Makefile	2009-11-22 20:42:16.398311126 +0900
@@ -15,7 +15,7 @@
 	hcsecd \
 	hostapd hostid hostid_save hostname \
 	inetd initrandom \
-	ip6addrctl ip6fw ipfilter ipfs ipfw ipmon \
+	ip6addrctl ipfilter ipfs ipfw ipmon \
 	ipnat ipsec ipxrouted \
 	jail \
 	kadmind kerberos keyserv kldxref kpasswdd \
Index: etc/rc.d/ipfw
diff -u etc/rc.d/ipfw.orig etc/rc.d/ipfw
--- etc/rc.d/ipfw.orig	2009-11-22 20:43:59.000000000 +0900
+++ etc/rc.d/ipfw	2009-11-23 19:29:05.426333161 +0900
@@ -61,7 +61,13 @@
 	# Enable the firewall
 	#
 	if ! ${SYSCTL_W} net.inet.ip.fw.enable=1 1>/dev/null 2>&1; then
-		warn "failed to enable firewall"
+		warn "failed to enable IPv4 firewall"
+	fi
+	if afexists inet6; then
+		if ! ${SYSCTL_W} net.inet6.ip6.fw.enable=1 1>/dev/null 2>&1
+		then
+			warn "failed to enable IPv6 firewall"
+		fi
 	fi
 }
 
@@ -70,6 +76,9 @@
 	# Disable the firewall
 	#
 	${SYSCTL_W} net.inet.ip.fw.enable=0
+	if afexists inet6; then
+		${SYSCTL_W} net.inet6.ip6.fw.enable=0
+	fi
 	if [ -f /etc/rc.d/natd ] ; then
 		/etc/rc.d/natd quietstop
 	fi
Index: etc/rc.firewall
diff -u etc/rc.firewall.orig etc/rc.firewall
--- etc/rc.firewall.orig	2009-10-25 10:10:29.000000000 +0900
+++ etc/rc.firewall	2009-11-23 20:03:03.419477872 +0900
@@ -85,12 +85,43 @@
 	${fwcmd} add 100 pass all from any to any via lo0
 	${fwcmd} add 200 deny all from any to 127.0.0.0/8
 	${fwcmd} add 300 deny ip from 127.0.0.0/8 to any
+	if [ $ipv6_available -eq 0 ]; then
+		${fwcmd} add 400 deny ip6 from any to ::1
+		${fwcmd} add 500 deny ip6 from ::1 to any
+	fi
+}
+
+setup_ipv6_mandatory () {
+	[ $ipv6_available -eq 0 ] || return 0
+
+	############
+	# Only in rare cases do you want to change these rules
+	#
+	# ND
+	#
+	# DAD
+	${fwcmd} add pass ip6 from :: to ff02::/16 proto ipv6-icmp
+	# RS, RA, NS, NA, redirect...
+	${fwcmd} add pass ip6 from fe80::/10 to fe80::/10 proto ipv6-icmp
+	${fwcmd} add pass ip6 from fe80::/10 to ff02::/16 proto ipv6-icmp
+
+	# Allow ICMPv6 destination unreach
+	${fwcmd} add pass ip6 from any to any icmp6types 1 proto ipv6-icmp
+
+	# Allow NS/NA/toobig (don't filter it out)
+	${fwcmd} add pass ip6 from any to any icmp6types 2,135,136 \
+	    proto ipv6-icmp
 }
 
 if [ -n "${1}" ]; then
 	firewall_type="${1}"
 fi
 
+. /etc/rc.subr
+. /etc/network.subr
+afexists inet6
+ipv6_available=$?
+
 ############
 # Set quiet mode if requested
 #
@@ -109,6 +140,7 @@
 ${fwcmd} -f flush
 
 setup_loopback
+setup_ipv6_mandatory
 
 ############
 # Network Address Translation.  All packets are passed to natd(8)
@@ -166,11 +198,13 @@
 	# against people from outside your own network.
 	#
 	# Configuration:
-	#  firewall_client_net:		Network address of local network.
+	#  firewall_client_net:		Network address of local IPv4 network.
+	#  firewall_client_net_ipv6:	Network address of local IPv6 network.
 	############
 
 	# set this to your local network
 	net="$firewall_client_net"
+	net6="$firewall_client_net_ipv6"
 
 	# Allow limited broadcast traffic from my own net.
 	${fwcmd} add pass all from ${net} to 255.255.255.255
@@ -178,6 +212,16 @@
 	# Allow any traffic to or from my own net.
 	${fwcmd} add pass all from me to ${net}
 	${fwcmd} add pass all from ${net} to me
+	if [ -n "$net6" ]; then
+		${fwcmd} add pass ip6 from me6 to ${net6}
+		${fwcmd} add pass ip6 from ${net6} to me6
+	fi
+
+	if [ -n "$net6" ]; then
+		# Allow any link-local multicast traffic
+		${fwcmd} add pass ip6 from fe80::/10 to ff02::/16
+		${fwcmd} add pass ip6 from ${net6} to ff02::/16
+	fi
 
 	# Allow TCP through if setup succeeded
 	${fwcmd} add pass tcp from any to any established
@@ -212,23 +256,35 @@
 	# on the inside at this machine for those services.
 	#
 	# Configuration:
-	#  firewall_simple_iif:		Inside network interface.
-	#  firewall_simple_inet:	Inside network address.
-	#  firewall_simple_oif:		Outside network interface.
-	#  firewall_simple_onet:	Outside network address.
+	#  firewall_simple_iif:		Inside IPv4 network interface.
+	#  firewall_simple_inet:	Inside IPv4 network address.
+	#  firewall_simple_oif:		Outside IPv4 network interface.
+	#  firewall_simple_onet:	Outside IPv4 network address.
+	#  firewall_simple_iif_ipv6:	Inside IPv6 network interface.
+	#  firewall_simple_inet_ipv6:	Inside IPv6 network prefix.
+	#  firewall_simple_oif_ipv6:	Outside IPv6 network interface.
+	#  firewall_simple_onet_ipv6:	Outside IPv6 network prefix.
 	############
 
 	# set these to your outside interface network
 	oif="$firewall_simple_oif"
 	onet="$firewall_simple_onet"
+	oif6="$firewall_simple_oif_ipv6"
+	onet6="$firewall_simple_onet_ipv6"
 
 	# set these to your inside interface network
 	iif="$firewall_simple_iif"
 	inet="$firewall_simple_inet"
+	iif6="$firewall_simple_iif_ipv6"
+	inet6="$firewall_simple_inet_ipv6"
 
 	# Stop spoofing
 	${fwcmd} add deny all from ${inet} to any in via ${oif}
 	${fwcmd} add deny all from ${onet} to any in via ${iif}
+	if [ -n "$oif6" -a -n "$onet6" -a -n "$iif6" -a -n "$inet6" ]; then
+		${fwcmd} add deny ip6 from ${inet6} to any in via ${oif6}
+		${fwcmd} add deny ip6 from ${onet6} to any in via ${iif6}
+	fi
 
 	# Stop RFC1918 nets on the outside interface
 	${fwcmd} add deny all from any to 10.0.0.0/8 via ${oif}
@@ -254,7 +310,7 @@
 	case ${natd_enable} in
 	[Yy][Ee][Ss])
 		if [ -n "${natd_interface}" ]; then
-			${fwcmd} add divert natd all from any to any via ${natd_interface}
+			${fwcmd} add divert natd ip4 from any to any via ${natd_interface}
 		fi
 		;;
 	esac
@@ -273,6 +329,55 @@
 	${fwcmd} add deny all from 224.0.0.0/4 to any via ${oif}
 	${fwcmd} add deny all from 240.0.0.0/4 to any via ${oif}
 
+	if [ -n "$oif6" -a -n "$onet6" -a -n "$iif6" -a -n "$inet6" ]; then
+		# Stop unique local unicast address on the outside interface
+		${fwcmd} add deny ip6 from fc00::/7 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to fc00::/7 via ${oif6}
+
+		# Stop site-local on the outside interface
+		${fwcmd} add deny ip6 from fec0::/10 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to fec0::/10 via ${oif6}
+
+		# Disallow "internal" addresses to appear on the wire.
+		${fwcmd} add deny ip6 from ::ffff:0.0.0.0/96 to any \
+		    via ${oif6}
+		${fwcmd} add deny ip6 from any to ::ffff:0.0.0.0/96 \
+		    via ${oif6}
+
+		# Disallow packets to malicious IPv4 compatible prefix.
+		${fwcmd} add deny ip6 from ::224.0.0.0/100 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to ::224.0.0.0/100 via ${oif6}
+		${fwcmd} add deny ip6 from ::127.0.0.0/104 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to ::127.0.0.0/104 via ${oif6}
+		${fwcmd} add deny ip6 from ::0.0.0.0/104 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to ::0.0.0.0/104 via ${oif6}
+		${fwcmd} add deny ip6 from ::255.0.0.0/104 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to ::255.0.0.0/104 via ${oif6}
+
+		${fwcmd} add deny ip6 from ::0.0.0.0/96 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to ::0.0.0.0/96 via ${oif6}
+
+		# Disallow packets to malicious 6to4 prefix.
+		${fwcmd} add deny ip6 from 2002:e000::/20 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to 2002:e000::/20 via ${oif6}
+		${fwcmd} add deny ip6 from 2002:7f00::/24 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to 2002:7f00::/24 via ${oif6}
+		${fwcmd} add deny ip6 from 2002:0000::/24 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to 2002:0000::/24 via ${oif6}
+		${fwcmd} add deny ip6 from 2002:ff00::/24 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to 2002:ff00::/24 via ${oif6}
+
+		${fwcmd} add deny ip6 from 2002:0a00::/24 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to 2002:0a00::/24 via ${oif6}
+		${fwcmd} add deny ip6 from 2002:ac10::/28 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to 2002:ac10::/28 via ${oif6}
+		${fwcmd} add deny ip6 from 2002:c0a8::/32 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to 2002:c0a8::/32 via ${oif6}
+
+		${fwcmd} add deny ip6 from ff05::/16 to any via ${oif6}
+		${fwcmd} add deny ip6 from any to ff05::/16 via ${oif6}
+	fi
+
 	# Allow TCP through if setup succeeded
 	${fwcmd} add pass tcp from any to any established
 
@@ -291,7 +396,11 @@
 	${fwcmd} add pass tcp from any to me 80 setup
 
 	# Reject&Log all setup of incoming connections from the outside
-	${fwcmd} add deny log tcp from any to any in via ${oif} setup
+	${fwcmd} add deny log ip4 from any to any in via ${oif} setup proto tcp
+	if [ -n "$oif6" -a -n "$onet6" -a -n "$iif6" -a -n "$inet6" ]; then
+		${fwcmd} add deny log ip6 from any to any in via ${oif6} \
+		    setup proto tcp
+	fi
 
 	# Allow setup of any other TCP connection
 	${fwcmd} add pass tcp from any to any setup
@@ -313,7 +422,7 @@
 	#			 	 offers services.
 	#  firewall_allowservices:	List of IPs which has access to
 	#				 $firewall_myservices.
-	#  firewall_trusted:		List of IPs which has full access 
+	#  firewall_trusted:		List of IPv4s which has full access 
 	#				 to this host. Be very carefull 
 	#				 when setting this. This option can
 	#				 seriously degrade the level of 
@@ -324,17 +433,31 @@
 	#  firewall_nologports:		List of TCP/UDP ports for which
 	#				 denied incomming packets are not
 	#				 logged.
-	
+	#  firewall_trusted_ipv6:	List of IPv6s which has full access 
+	#				 to this host. Be very carefull 
+	#				 when setting this. This option can
+	#				 seriously degrade the level of 
+	#				 protection provided by the firewall.
+
 	# Allow packets for which a state has been built.
 	${fwcmd} add check-state
 
 	# For services permitted below.
 	${fwcmd} add pass tcp  from me to any established
+	if [ $ipv6_available -eq 0 ]; then
+		${fwcmd} add pass ip6 from any to any proto tcp established
+	fi
 
 	# Allow any connection out, adding state for each.
 	${fwcmd} add pass tcp  from me to any setup keep-state
 	${fwcmd} add pass udp  from me to any       keep-state
 	${fwcmd} add pass icmp from me to any       keep-state
+	if [ $ipv6_available -eq 0 ]; then
+		${fwcmd} add pass ip6 from me6 to any proto tcp setup
+		${fwcmd} add pass ip6 from me6 to any proto udp keep-state
+		${fwcmd} add pass ip6 from me6 to any proto ipv6-icmp \
+		    keep-state
+	fi
 
 	# Allow DHCP.
 	${fwcmd} add pass udp  from 0.0.0.0 68 to 255.255.255.255 67 out
@@ -343,6 +466,10 @@
 	# Some servers will ping the IP while trying to decide if it's 
 	# still in use.
 	${fwcmd} add pass icmp from any to any icmptype 8
+	if [ $ipv6_available -eq 0 ]; then
+		${fwcmd} add pass ip6 from any to any icmp6type 128,129 \
+		    proto ipv6-icmp
+	fi
 
 	# Allow "mandatory" ICMP in.
 	${fwcmd} add pass icmp from any to any icmptype 3,4,11
@@ -361,6 +488,9 @@
 	for i in ${firewall_allowservices} ; do
 	  for j in ${firewall_myservices} ; do
 	    ${fwcmd} add pass tcp from $i to me $j
+	    if [ $ipv6_available -eq 0 ]; then
+	      ${fwcmd} add pass tcp from $i to me6 $j setup
+	    fi
 	  done
 	done
 
@@ -370,7 +500,10 @@
 	for i in ${firewall_trusted} ; do
 	  ${fwcmd} add pass ip from $i to me
 	done
-	
+	for i in ${firewall_trusted_ipv6} ; do
+	  ${fwcmd} add pass ip6 from $i to me6
+	done
+
 	${fwcmd} add 65000 count ip from any to any
 
 	# Drop packets to ports where we don't want logging

--Multipart_Tue_Nov_24_00:13:53_2009-1
Content-Type: text/plain; charset=US-ASCII


--
Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan
ume@mahoroba.org  ume@{,jp.}FreeBSD.org
http://www.imasy.org/~ume/

--Multipart_Tue_Nov_24_00:13:53_2009-1--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?ygek4xhjmtp.wl%ume>