a couple /etc/rc.firewall questions

Ian Smith smithi at nimnet.asn.au
Sun Aug 23 06:00:28 UTC 2015


On Sun, 23 Aug 2015 08:44:53 +0900, Hiroki Sato wrote:
 > Don Lewis <truckman at FreeBSD.org> wrote
 >   in <201508222103.t7ML3gAx000794 at gw.catspoiler.org>:
 > 
 > tr> The example /etc/rc.firewall has provisions to use either in-kernel NAT
 > tr> or natd for the open and client firewall types, but the simple filewall
 > tr> type only has code for natd.  Is there any reason that in-kernel NAT
 > tr> could not be used with the simple firewall type?
 > 
 >  I think there is no particular reason.  Simple rule was just not updated.

I did send you and -ipfw@ a patch for that on several occasions since 
Feb. 2013, though I did fail to push it into the 3-4 PRs it affected.

The attached patch addresses that, chooses kernel NAT over natd(8) if 
both were enabled in rc.conf, updates some commentary and fixes an 
overwordy line in 'workstation'.  Just now checked it against HEAD.

 > tr> After allowing connections to selected TCP ports and then denying all
 > tr> other incoming TCP setup connections from ${oif}, the simple firewall
 > tr> code in /etc/rc.firewall then permits all other TCP setup connections:
 > tr> 	# Allow setup of any other TCP connection
 > tr> 	${fwcmd} add pass tcp from any to any setup
 > tr> This is potentially undesirable since it allows unrestricted TCP
 > tr> connections between "me" and the inside network.  When I changed this to
 > tr> 	${fwcmd} add pass tcp from any to any out via ${oif} setup
 > tr> I was able to open TCP connections from the firewall box to the outside,
 > tr> but NATed connections from inside network to the outside were blocked.
 > tr> If I run "ipfw show", it appears that the TCP setup packets are falling
 > tr> through to the final implicit deny all rule, but I don't see any obvious
 > tr> reason.
 > 
 >  A TCP setup packet coming from a host on the internal LAN to the NAPT
 >  router falls into the last deny-all rule because it does not match if
 >  you added "out via ${oif}" to that rule.  Does the following
 >  additional rule work for you?
 > 
 >  ${fwcmd} add pass tcp from any to any out via ${oif} setup

That looks ok, maybe some UDP too?  Adding some stateful rules is 
another option for dealing with inside hosts' external requests.

 >  ${fwcmd} add pass tcp from any to not me in via ${iif} setup

If you want to deny inside hosts access to host services, that'll do it.

The other long-term issue with 'simple' is that it permits no ICMPv4 at 
all.  Neither inside nor outside, no pings, no PMTU, nothing .. although 
curiously allows selected ICMP for ipv6.  I usually add something like:

 ${fwcmd} add pass icmp from any to any icmptype 0,3,8,11

If you don't want to allow pings from outside your net, preceded with:

 ${fwcmd} add deny icmp from any to any in recv ${oif} icmptype 8

cheers, Ian

 > -- Hiroki
-------------- next part --------------
--- rc.firewall.r238416	2015-08-23 14:48:26.000000000 +1000
+++ rc.firewall	2014-03-26 15:42:25.000000000 +1100
@@ -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-net mailing list