Request for policy decision: kernel nat vs/and/or natd

Ian Smith smithi at nimnet.asn.au
Sat Jan 8 14:30:58 UTC 2011


On Sat, 8 Jan 2011 15:02:29 +1100, Ian Smith wrote:
 > On Fri, 7 Jan 2011, Brandon Gooch wrote:
 >  > On Thu, Dec 23, 2010 at 8:58 AM, Ian Smith <smithi at nimnet.asn.au> wrote:
[..]
 >  > > We could:
 >  > >
 >  > > 1) Preference kernel nat over natd when both are enabled.
 >  > 
 >  > I vote for #1.
 > 
 > Thanks.  So far, that makes an overwhelming majority of 2 / NIL :)
 > 
 > I see that hrs at freebsd.org has just grabbed two related PRs:
 > 
 > kern/148928: [ipfw] Problem with loading of ipfw NAT rules during system startup
 > conf/153155: [PATCH] [8.2-BETA1] ipfw rules fail to load cleanly on start if nat enabled
 > 
 > so this seems a good time to work up patches to that effect for review 
 > (/etc/rc.d/ipfw, maybe natd, /etc/rc.firewall) later tonight my time.

Ok, the attached patches are against HEAD, which is currently identical 
to 8-STABLE for these files.  rc.d_ipfw.patch also applies to 7-STABLE 
with an offset but rc.firewall.patch needs more work for 7.  I've no box 
on which to actually run-test tonight, and will be away for a few days.

/etc/rc.d/ipfw:
 . prefer kernel nat (loading ipfw_nat) to natd when both are enabled
 . add ipdivert to required_modules - when only natd is enabled - as
   proposed by Thomas Sandford in conf/153155 and also re kern/148928
   also fixing the related issue in conf/148137 (and possibly others)
 . prefix /etc/rc.d/natd to firewall_coscripts when only natd is enabled

/etc/rc.d/natd:
 . seems nothing is needed; has KEYWORD nostart and so should only be 
   started now by ipfw when natd - but not firewall_nat - is enabled

/etc/rc.firewall:
 . move firewall_nat and natd code into a function, setup_nat() 
   preferring kernel firewall_nat to natd if both are enabled
 . couldn't resist tidying up that code to within 80 columns
 . call setup_nat also in 'simple' ruleset, with same intent as
   proposed in conf/148144 by David Naylor
 . couldn't resist fixing unnecessarily long line in 'workstation'

I've resisted other patches (enabling icmp) that I added to conf/148144 
for which I apologise to David; one thing at a time ..

If folks prefer that this be submitted as yet another PR, please say.

cheers, Ian
-------------- next part --------------
--- rc.d_ipfw.1.24	Sat Jan  8 18:13:46 2011
+++ ipfw	Sat Jan  8 21:00:18 2011
@@ -27,9 +27,9 @@
 	fi
 
 	if checkyesno firewall_nat_enable; then
-		if ! checkyesno natd_enable; then
-			required_modules="$required_modules ipfw_nat"
-		fi
+		required_modules="$required_modules ipfw_nat"
+	elif checkyesno natd_enable; then
+		required_modules="$required_modules ipdivert"
 	fi
 }
 
@@ -105,6 +105,7 @@
 }
 
 load_rc_config $name
-firewall_coscripts="/etc/rc.d/natd ${firewall_coscripts}"
+checkyesno natd_enable && ! checkyesno firewall_nat_enable && \
+	firewall_coscripts="/etc/rc.d/natd ${firewall_coscripts}"
 
 run_rc_command $*
-------------- next part --------------
--- rc.firewall.1.69	Sat Jan  8 18:04:28 2011
+++ rc.firewall	Sat Jan  8 21:24:54 2011
@@ -52,7 +52,7 @@
 #   filename    - will load the rules in the given filename (full path required)
 #
 # For ``client'' and ``simple'' the entries below should be customized
-# appropriately.
+# appropriately with rc.conf variables.
 
 ############
 #
@@ -112,6 +112,29 @@
 	${fwcmd} add pass ipv6-icmp from any to any icmp6types 2,135,136
 }
 
+setup_nat () {
+	local iflag
+	if checkyesno firewall_nat_enable; then
+		if [ -n "${firewall_nat_interface}" ]; then
+			if echo "${firewall_nat_interface}" | \
+				grep -q -E '^[0-9]+(\.[0-9]+){0,3}$'; then
+				iflag="ip ${firewall_nat_interface}"
+			else
+				iflag="if ${firewall_nat_interface}"
+			fi
+			firewall_nat_flags="$iflag ${firewall_nat_flags}"
+			${fwcmd} nat 123 config log ${firewall_nat_flags}
+			${fwcmd} add $1 nat 123 ip4 from any to any \
+				via ${firewall_nat_interface}
+		fi
+	elif checkyesno natd_enable; then
+		if [ -n "${natd_interface}" ]; then
+			${fwcmd} add $1 divert natd ip4 from any to any \
+				via ${natd_interface}
+		fi
+	fi
+}
+
 if [ -n "${1}" ]; then
 	firewall_type="${1}"
 fi
@@ -142,37 +165,17 @@
 setup_ipv6_mandatory
 
 ############
-# Network Address Translation.  All packets are passed to natd(8)
-# before they encounter your remaining rules.  The firewall rules
-# will then be run again on each packet after translation by natd
-# starting at the rule number following the divert rule.
+# Network Address Translation.  All packets are passed to kernel nat
+# or natd(8) before they encounter your remaining rules.  The firewall
+# rules will then be run again on each packet after NAT translation
+# starting at the rule number following the nat or divert rule.
 #
-# For ``simple'' firewall type the divert rule should be put to a
-# different place to not interfere with address-checking rules.
+# For ``simple'' firewall type the nat or divert rule is installed in
+# a different place to avoid interfering with address-checking rules.
 #
 case ${firewall_type} in
 [Oo][Pp][Ee][Nn]|[Cc][Ll][Ii][Ee][Nn][Tt])
-	case ${natd_enable} in
-	[Yy][Ee][Ss])
-		if [ -n "${natd_interface}" ]; then
-			${fwcmd} add 50 divert natd ip4 from any to any via ${natd_interface}
-		fi
-		;;
-	esac
-	case ${firewall_nat_enable} in
-	[Yy][Ee][Ss])
-		if [ -n "${firewall_nat_interface}" ]; then
-			if echo "${firewall_nat_interface}" | \
-				grep -q -E '^[0-9]+(\.[0-9]+){0,3}$'; then
-				firewall_nat_flags="ip ${firewall_nat_interface} ${firewall_nat_flags}"
-			else
-				firewall_nat_flags="if ${firewall_nat_interface} ${firewall_nat_flags}"
-			fi
-			${fwcmd} nat 123 config log ${firewall_nat_flags}
-			${fwcmd} add 50 nat 123 ip4 from any to any via ${firewall_nat_interface}
-		fi
-		;;
-	esac
+	setup_nat 50
 esac
 
 ############
@@ -311,13 +314,7 @@
 	# translated by natd(8) would match the `deny' rule above.  Similarly
 	# an outgoing packet originated from it before being translated would
 	# match the `deny' rule below.
-	case ${natd_enable} in
-	[Yy][Ee][Ss])
-		if [ -n "${natd_interface}" ]; then
-			${fwcmd} add divert natd ip4 from any to any via ${natd_interface}
-		fi
-		;;
-	esac
+	setup_nat
 
 	# Stop RFC1918 nets on the outside interface
 	${fwcmd} add deny all from 10.0.0.0/8 to any via ${oif}
@@ -519,7 +516,7 @@
 
 	# Deny and (if wanted) log the rest unconditionally.
 	log=""
-	if [ ${firewall_logdeny:-x} = "YES" -o ${firewall_logdeny:-x} = "yes" ] ; then
+	if checkyesno firewall_logdeny; then
 	  log="log logamount 500"	# The default of 100 is too low.
 	  sysctl net.inet.ip.fw.verbose=1 >/dev/null
 	fi


More information about the freebsd-ipfw mailing list