Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Nov 2009 01:01:16 +0900
From:      Hajimu UMEMOTO <ume@freebsd.org>
To:        John Baldwin <jhb@freebsd.org>
Cc:        freebsd-net@freebsd.org, freebsd-current@freebsd.org, Doug Barton <dougb@freebsd.org>
Subject:   Re: [CFR] unified rc.firewall
Message-ID:  <yged436d25v.wl%ume@mahoroba.org>
In-Reply-To: <200911231255.26279.jhb@freebsd.org>
References:  <ygeljhyk1qg.wl%ume@mahoroba.org> <200911231056.15247.jhb@freebsd.org> <ygetywlgnic.wl%ume@mahoroba.org> <200911231255.26279.jhb@freebsd.org>

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

Hi,

>>>>> On Mon, 23 Nov 2009 12:55:25 -0500
>>>>> John Baldwin <jhb@freebsd.org> said:

I updated the patch.

jhb> I had missed the me vs any.  It is true that the equivalent rule would use
jhb> me6.  I would rather figure out the IPv6 bug so that TCP is treated the
jhb> same for both protocols instead of having a weaker firewall for IPv6 than
jhb> IPV4.

Yes, it is better, definitely.  I thought that we could change to use
dynamic rule, once it was fixed.
Since the PR kern/117234 fixed it, I changed to use dynamic rule for
IPv6 as well.  So, it requires the patch in the PR.

jhb> I do find the shorter version easier to read, and it matches the existing
jhb> style as well as the examples in the manual page, handbook, etc.

Okay, I changed 'ip6' to 'all' where we can use it, and stopped use of
'proto xxx'' as possible.

I reconsidered oif vs oif6 and iif vs iif6 issue.  Now, if
$firewall_simple_oif_ipv6 is not set, $firewall_simple_oif is assumed
for oif6, and, $firewall_simple_iif_ipv6 is not set,
$firewall_simple_iif is assumed for iif6.
Further, I think we don't assign a global IPv6 address to oif in
usual.  So, I made $firewall_simple_onet_ipv6 optional.
One more change is that DHCPv6 is allowed as well as IPv4 DHCP for
WORKSTATION type.  I'm using DHCPv6 in usual; L2TP + DHCPv6 PD, DHCPv6
DNS option ...

Sincerely,


--Multipart_Thu_Nov_26_01:01:16_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-25 03:18:14.568870172 +0900
@@ -85,12 +85,42 @@
 	${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 all from any to ::1
+		${fwcmd} add 500 deny all 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 ipv6-icmp from :: to ff02::/16
+	# RS, RA, NS, NA, redirect...
+	${fwcmd} add pass ipv6-icmp from fe80::/10 to fe80::/10
+	${fwcmd} add pass ipv6-icmp from fe80::/10 to ff02::/16
+
+	# Allow ICMPv6 destination unreach
+	${fwcmd} add pass ipv6-icmp from any to any icmp6types 1
+
+	# Allow NS/NA/toobig (don't filter it out)
+	${fwcmd} add pass ipv6-icmp from any to any icmp6types 2,135,136
 }
 
 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 +139,7 @@
 ${fwcmd} -f flush
 
 setup_loopback
+setup_ipv6_mandatory
 
 ############
 # Network Address Translation.  All packets are passed to natd(8)
@@ -166,11 +197,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 +211,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 all from me6 to ${net6}
+		${fwcmd} add pass all from ${net6} to me6
+	fi
+
+	if [ -n "$net6" ]; then
+		# Allow any link-local multicast traffic
+		${fwcmd} add pass all from fe80::/10 to ff02::/16
+		${fwcmd} add pass all from ${net6} to ff02::/16
+	fi
 
 	# Allow TCP through if setup succeeded
 	${fwcmd} add pass tcp from any to any established
@@ -212,23 +255,38 @@
 	# 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:-$firewall_simple_oif}"
+	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:-$firewall_simple_iif}"
+	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 "$inet6" ]; then
+		${fwcmd} add deny all from ${inet6} to any in via ${oif6}
+		if [ -n "$onet6" ]; then
+			${fwcmd} add deny all from ${onet6} to any in \
+			    via ${iif6}
+		fi
+	fi
 
 	# Stop RFC1918 nets on the outside interface
 	${fwcmd} add deny all from any to 10.0.0.0/8 via ${oif}
@@ -254,7 +312,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 +331,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 "$inet6" ]; then
+		# Stop unique local unicast address on the outside interface
+		${fwcmd} add deny all from fc00::/7 to any via ${oif6}
+		${fwcmd} add deny all from any to fc00::/7 via ${oif6}
+
+		# Stop site-local on the outside interface
+		${fwcmd} add deny all from fec0::/10 to any via ${oif6}
+		${fwcmd} add deny all from any to fec0::/10 via ${oif6}
+
+		# Disallow "internal" addresses to appear on the wire.
+		${fwcmd} add deny all from ::ffff:0.0.0.0/96 to any \
+		    via ${oif6}
+		${fwcmd} add deny all from any to ::ffff:0.0.0.0/96 \
+		    via ${oif6}
+
+		# Disallow packets to malicious IPv4 compatible prefix.
+		${fwcmd} add deny all from ::224.0.0.0/100 to any via ${oif6}
+		${fwcmd} add deny all from any to ::224.0.0.0/100 via ${oif6}
+		${fwcmd} add deny all from ::127.0.0.0/104 to any via ${oif6}
+		${fwcmd} add deny all from any to ::127.0.0.0/104 via ${oif6}
+		${fwcmd} add deny all from ::0.0.0.0/104 to any via ${oif6}
+		${fwcmd} add deny all from any to ::0.0.0.0/104 via ${oif6}
+		${fwcmd} add deny all from ::255.0.0.0/104 to any via ${oif6}
+		${fwcmd} add deny all from any to ::255.0.0.0/104 via ${oif6}
+
+		${fwcmd} add deny all from ::0.0.0.0/96 to any via ${oif6}
+		${fwcmd} add deny all from any to ::0.0.0.0/96 via ${oif6}
+
+		# Disallow packets to malicious 6to4 prefix.
+		${fwcmd} add deny all from 2002:e000::/20 to any via ${oif6}
+		${fwcmd} add deny all from any to 2002:e000::/20 via ${oif6}
+		${fwcmd} add deny all from 2002:7f00::/24 to any via ${oif6}
+		${fwcmd} add deny all from any to 2002:7f00::/24 via ${oif6}
+		${fwcmd} add deny all from 2002:0000::/24 to any via ${oif6}
+		${fwcmd} add deny all from any to 2002:0000::/24 via ${oif6}
+		${fwcmd} add deny all from 2002:ff00::/24 to any via ${oif6}
+		${fwcmd} add deny all from any to 2002:ff00::/24 via ${oif6}
+
+		${fwcmd} add deny all from 2002:0a00::/24 to any via ${oif6}
+		${fwcmd} add deny all from any to 2002:0a00::/24 via ${oif6}
+		${fwcmd} add deny all from 2002:ac10::/28 to any via ${oif6}
+		${fwcmd} add deny all from any to 2002:ac10::/28 via ${oif6}
+		${fwcmd} add deny all from 2002:c0a8::/32 to any via ${oif6}
+		${fwcmd} add deny all from any to 2002:c0a8::/32 via ${oif6}
+
+		${fwcmd} add deny all from ff05::/16 to any via ${oif6}
+		${fwcmd} add deny all 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 +398,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 "$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 +424,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,25 +435,44 @@
 	#  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 tcp from me6 to any 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 tcp from me6 to any setup keep-state
+		${fwcmd} add pass udp from me6 to any keep-state
+		${fwcmd} add pass ipv6-icmp from me6 to any keep-state
+	fi
 
 	# Allow DHCP.
 	${fwcmd} add pass udp  from 0.0.0.0 68 to 255.255.255.255 67 out
 	${fwcmd} add pass udp  from any 67     to me 68 in
 	${fwcmd} add pass udp  from any 67     to 255.255.255.255 68 in
+	if [ $ipv6_available -eq 0 ]; then
+		${fwcmd} add pass udp from fe80::/10 to me6 546 in
+	fi
 	# 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 ipv6-icmp from any to any icmp6type 128,129
+	fi
 
 	# Allow "mandatory" ICMP in.
 	${fwcmd} add pass icmp from any to any icmptype 3,4,11
@@ -361,6 +491,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
+	    fi
 	  done
 	done
 
@@ -370,7 +503,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 all 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_Thu_Nov_26_01:01:16_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_Thu_Nov_26_01:01:16_2009-1--



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