Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Jan 2003 20:43:08 -0600 (CST)
From:      "brucegb@realtime.net" <brucegb@realtime.net>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/47529: natd/ipfw lose TCP packets for firewalled machines
Message-ID:  <200301270243.h0R2h8SQ000897@tigerfish2.my.domain>

next in thread | raw e-mail | index | archive | help

>Number:         47529
>Category:       kern
>Synopsis:       natd/ipfw lose TCP packets for firewalled machines
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jan 26 18:50:01 PST 2003
>Closed-Date:
>Last-Modified:
>Originator:     brucegb@realtime.net
>Release:        FreeBSD 5.0-RELEASE i386
>Organization:
>Environment:
System: FreeBSD tigerfish.my.domain 5.0-RELEASE FreeBSD 5.0-RELEASE #0: Fri Jan 24 18:59:03 CST 2002 brucegb@tigerfish.my.domain:/usr/src/sys/compile/BRUCE i386

natd.c v1.40

>Description:

I decided to install 5.0-RELEASE on my firewall, as it is an SMP machine, but it
doesn't do much besides act as a firewall. Things went relatively smoothly, and
the new code was installed. Then the problems started. I was able to get pings
(ICMP) and DNS, time, and other UDP related packets through the firewall, and back.

TCP responses, however, would hit the firewall, go to natd for translation to the
local IP address, and then disapper. A "deny" rule immediately following the divert
rule that should have caught the specific packets was never incremented.

>How-To-Repeat:

	P <- n1 -> F <- n0 -> M

P - primary system (RELENG_4)
n1 - private network, with a switch
F - firewall system (5.0-RELEASE)
n0 - cable to cable modem
M - cable modem.

In this case, I was attempting a ssh connection to my ISP:


=========================================== rc.firewall

# Copyright (c) 1996  Poul-Henning Kamp
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD: src/etc/rc.firewall,v 1.45 2002/02/21 13:14:19 cjc Exp $
#

#
# Setup system for firewall service.
#

# Suck in the configuration variables.
if [ -z "${source_rc_confs_defined}" ]; then
	if [ -r /etc/defaults/rc.conf ]; then
		. /etc/defaults/rc.conf
		source_rc_confs
	elif [ -r /etc/rc.conf ]; then
		. /etc/rc.conf
	fi
fi

############
# Define the firewall type in /etc/rc.conf.  Valid values are:
#   open     - will allow anyone in
#   client   - will try to protect just this machine
#   simple   - will try to protect a whole network
#   closed   - totally disables IP services except via lo0 interface
#   UNKNOWN  - disables the loading of firewall rules.
#   filename - will load the rules in the given filename (full path required)
#
# For ``client'' and ``simple'' the entries below should be customized
# appropriately.

############
#
# If you don't know enough about packet filtering, we suggest that you
# take time to read this book:
#
#	Building Internet Firewalls, 2nd Edition
#	Brent Chapman and Elizabeth Zwicky
#
#	O'Reilly & Associates, Inc
#	ISBN 1-56592-871-7
#	http://www.ora.com/
#	http://www.oreilly.com/catalog/fire2/
#
# For a more advanced treatment of Internet Security read:
#
#	Firewalls & Internet Security
#	Repelling the wily hacker
#	William R. Cheswick, Steven M. Bellowin
#
#	Addison-Wesley
#	ISBN 0-201-63357-4
#	http://www.awl.com/
#	http://www.awlonline.com/product/0%2C2627%2C0201633574%2C00.html
#

setup_loopback () {
	############
	# Only in rare cases do you want to change these rules
	#
	${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 [ -n "${1}" ]; then
	firewall_type="${1}"
fi

############
# Set quiet mode if requested
#
case ${firewall_quiet} in
[Yy][Ee][Ss])
	fwcmd="/sbin/ipfw -q"
	;;
*)
	fwcmd="/sbin/ipfw"
	;;
esac

############
# Flush out the list before we begin.
#
${fwcmd} -f flush

############
# 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.
#
# For ``simple'' firewall type the divert rule should be put to a
# different place to not interfere 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 all from any to any via ${natd_interface}
		fi
		;;
	esac
esac

############
# If you just configured ipfw in the kernel as a tool to solve network
# problems or you just want to disallow some particular kinds of traffic
# then you will want to change the default policy to open.  You can also
# do this as your only action by setting the firewall_type to ``open''.
#
# ${fwcmd} add 65000 pass all from any to any


# Prototype setups.
#
case ${firewall_type} in
[Oo][Pp][Ee][Nn])
	setup_loopback
	${fwcmd} add 65000 pass all from any to any
	;;

[Cc][Ll][Ii][Ee][Nn][Tt])
	############
	# This is a prototype setup that will protect your system somewhat
	# against people from outside your own network.
	############

	# set these to your network and netmask and ip
	net="192.0.2.0"
	mask="255.255.255.0"
	ip="192.0.2.1"

	setup_loopback

	# Allow any traffic to or from my own net.
	${fwcmd} add pass all from ${ip} to ${net}:${mask}
	${fwcmd} add pass all from ${net}:${mask} to ${ip}

	# Allow TCP through if setup succeeded
	${fwcmd} add pass tcp from any to any established

	# Allow IP fragments to pass through
	${fwcmd} add pass all from any to any frag

	# Allow setup of incoming email
	${fwcmd} add pass tcp from any to ${ip} 25 setup

	# Allow setup of outgoing TCP connections only
	${fwcmd} add pass tcp from ${ip} to any setup

	# Disallow setup of all other TCP connections
	${fwcmd} add deny tcp from any to any setup

	# Allow DNS queries out in the world
	${fwcmd} add pass udp from ${ip} to any 53 keep-state

	# Allow NTP queries out in the world
	${fwcmd} add pass udp from ${ip} to any 123 keep-state

	# Everything else is denied by default, unless the
	# IPFIREWALL_DEFAULT_TO_ACCEPT option is set in your kernel
	# config file.
	;;

[Ss][Ii][Mm][Pp][Ll][Ee])
	############
	# This is a prototype setup for a simple firewall.  Configure this
	# machine as a named server and ntp server, and point all the machines
	# on the inside at this machine for those services.
	############

	${fwcmd} enable verbose
	${fwcmd} enable debug

	# set these to your outside interface network and netmask and ip
        oif="dc0"
        onet="66.25.0.0"
        omask="255.255.0.0"
        oip="66.25.4.17"

	# set these to your inside interface network and netmask and ip
        iif="dc1"
        inet="192.168.1.0"
        imask="255.255.255.0"
        iip="192.168.1.1"

	setup_loopback

	${fwcmd} add allow all from any to any via ${iif}

	# Stop spoofing
	${fwcmd} add deny all from ${inet}:${imask} to any in via ${oif}
	${fwcmd} add deny all from ${onet}:${omask} to any in via ${iif}

	# Stop RFC1918 nets on the outside interface
	${fwcmd} add deny all from any to 10.0.0.0/8 via ${oif}
	${fwcmd} add deny all from any to 172.16.0.0/12 via ${oif}
	${fwcmd} add deny all from any to 192.168.0.0/16 via ${oif}

	# Stop draft-manning-dsua-03.txt (1 May 2000) nets (includes RESERVED-1,
	# DHCP auto-configuration, NET-TEST, MULTICAST (class D), and class E)
	# on the outside interface
	${fwcmd} add deny all from any to 0.0.0.0/8 via ${oif}
	${fwcmd} add deny all from any to 169.254.0.0/16 via ${oif}
	${fwcmd} add deny all from any to 192.0.2.0/24 via ${oif}
	${fwcmd} add deny all from any to 224.0.0.0/4 via ${oif}
	${fwcmd} add deny all from any to 240.0.0.0/4 via ${oif}

	# Network Address Translation.  This rule is placed here deliberately
	# so that it does not interfere with the surrounding address-checking
	# rules.  If for example one of your internal LAN machines had its IP
	# address set to 192.0.2.1 then an incoming packet for it after being
	# 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 all from any to any via ${natd_interface}
		fi
		;;
	esac

	# Stop RFC1918 nets on the outside interface
	${fwcmd} add deny all from 10.0.0.0/8 to any via ${oif}
	${fwcmd} add deny all from 172.16.0.0/12 to any via ${oif}
	${fwcmd} add deny all from 192.168.0.0/16 to any via ${oif}

	# Stop draft-manning-dsua-03.txt (1 May 2000) nets (includes RESERVED-1,
	# DHCP auto-configuration, NET-TEST, MULTICAST (class D), and class E)
	# on the outside interface
	${fwcmd} add deny all from 0.0.0.0/8 to any via ${oif}
	${fwcmd} add deny all from 169.254.0.0/16 to any via ${oif}
	${fwcmd} add deny all from 192.0.2.0/24 to any via ${oif}
	${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}

#	${fwcmd} add allow udp from ${onet}:${omask} 68 to 10.1.1.64 67 out via ${oif}

	# Allow TCP through if setup succeeded
	${fwcmd} add pass tcp from any to any established

	# Allow IP fragments to pass through
	${fwcmd} add pass all from any to any frag

	#(Don't) Allow setup of incoming email
#	${fwcmd} add pass tcp from any to ${oip} 25 setup

	# Allow access to our DNS
	${fwcmd} add pass tcp from any to ${inet}:${imask} 53 setup
	${fwcmd} add pass udp from any to ${inet}:${imask} 53
	${fwcmd} add pass udp from ${inet}:${imask} 53 to any

	#(Don't) Allow access to our WWW
#	${fwcmd} add pass tcp from any to ${oip} 80 setup

	${fwcmd} add allow log logamount 100 tcp from any 20 to any in via ${oif} setup

	# Reject&Log all setup of incoming connections from the outside
	${fwcmd} add deny log tcp from any to any in via ${oif} setup

	# Allow setup of any other TCP connection
	${fwcmd} add pass tcp from any to any out via ${oif} setup

	# Allow DNS queries out in the world
	${fwcmd} add pass udp from any to any 53 out via ${oif} keep-state
#	${fwcmd} add pass udp from any to any 53 via ${oif}

	# Allow DNS responses in from the world
	${fwcmd} add pass udp from any 53 to any in via ${oif} keep-state
#	${fwcmd} add pass udp from any 53 to any via ${oif} 

        # Deny incoming ICMP requests not specifically from the DNS
        #
	${fwcmd} add deny icmp from not 205.238.0.0:255.255.0.0 to any in via ${oif} icmptypes 8
	${fwcmd} add allow icmp from 205.238.0.0:255.255.0.0 to any in via ${oif} icmptypes 8
        # Allow outgoing ICMP requests
        #
	${fwcmd} add allow icmp from any to any out via ${oif} icmptypes 8
	${fwcmd} add allow icmp from any to any in via ${oif} icmptypes 0

	# Allow NTP queries out in the world
#	${fwcmd} add pass udp from any to any 123 via ${oif} keep-state
	${fwcmd} add pass udp from any to any 123 via ${oif}

        # Allow ourselves to talk to the outside world...
        # 
	${fwcmd} add allow all from ${onet}:${omask} to any via ${oif}

	# Everything else is denied by default, unless the
	# IPFIREWALL_DEFAULT_TO_ACCEPT option is set in your kernel
	# config file.
	;;

[Cc][Ll][Oo][Ss][Ee][Dd])
	setup_loopback
	;;
[Uu][Nn][Kk][Nn][Oo][Ww][Nn])
	;;
*)
	if [ -r "${firewall_type}" ]; then
		${fwcmd} ${firewall_flags} ${firewall_type}
	fi
	;;
esac

=========================================== tcpdump output, n1 traffic on firewall


16:29:26.978103 tigerfish2.my.domain.1090 > ns1.austin.rr.com.domain:  5762+ AAAA? access.realtime.net. (37)
16:29:29.114987 ns1.austin.rr.com.domain > tigerfish2.my.domain.1090:  5762 1/1/0 CNAME[|domain] (DF)
16:29:29.115590 tigerfish2.my.domain.1091 > ns1.austin.rr.com.domain:  5763+ A? access.realtime.net. (37)
16:29:29.131164 ns1.austin.rr.com.domain > tigerfish2.my.domain.1091:  5763 2/2/1 CNAME[|domain] (DF)
16:29:29.131714 tigerfish2.my.domain.1086 > sullivan.realtime.net.ssh: S 936413443:936413443(0) win 57344 <mss 1460,nop,wscale 0,nop,nop,timestamp 904114 0> (DF)
16:29:32.123023 tigerfish2.my.domain.1086 > sullivan.realtime.net.ssh: S 936413443:936413443(0) win 57344 <mss 1460,nop,wscale 0,nop,nop,timestamp 904414 0> (DF)
16:29:35.323223 tigerfish2.my.domain.1086 > sullivan.realtime.net.ssh: S 936413443:936413443(0) win 57344 <mss 1460,nop,wscale 0,nop,nop,timestamp 904734 0> (DF)
16:29:38.523418 tigerfish2.my.domain.1086 > sullivan.realtime.net.ssh: S 936413443:936413443(0) win 57344 <mss 1460> (DF)
16:29:41.723597 tigerfish2.my.domain.1086 > sullivan.realtime.net.ssh: S 936413443:936413443(0) win 57344 <mss 1460> (DF)
16:29:44.923805 tigerfish2.my.domain.1086 > sullivan.realtime.net.ssh: S 936413443:936413443(0) win 57344 <mss 1460> (DF)
16:29:51.124165 tigerfish2.my.domain.1086 > sullivan.realtime.net.ssh: S 936413443:936413443(0) win 57344 <mss 1460> (DF)
16:30:03.324929 tigerfish2.my.domain.1086 > sullivan.realtime.net.ssh: S 936413443:936413443(0) win 57344 <mss 1460> (DF)
16:30:27.526379 tigerfish2.my.domain.1086 > sullivan.realtime.net.ssh: S 936413443:936413443(0) win 57344 <mss 1460> (DF)
>Fix:

Note that there are 11 packets sent, 2 received (from DNS, or the UDP packets)

=========================================== initial output from ipfw show


00100          0          0 allow ip from any to any via lo0
00200          0          0 deny ip from any to 127.0.0.0/8
00300          0          0 deny ip from 127.0.0.0/8 to any
00400          0          0 allow ip from any to any via dc1
00500          0          0 deny ip from 192.168.1.0/24 to any in via dc0
00600          0          0 deny ip from 66.25.0.0/16 to any in via dc1
00700          0          0 deny ip from any to 10.0.0.0/8 via dc0
00800          0          0 deny ip from any to 172.16.0.0/12 via dc0
00900          0          0 deny ip from any to 192.168.0.0/16 via dc0
01000          0          0 deny ip from any to 0.0.0.0/8 via dc0
01100          0          0 deny ip from any to 169.254.0.0/16 via dc0
01200          0          0 deny ip from any to 192.0.2.0/24 via dc0
01300          0          0 deny ip from any to 224.0.0.0/4 via dc0
01400          0          0 deny ip from any to 240.0.0.0/4 via dc0
01500          0          0 divert 8668 ip from any to any via dc0
01600          0          0 deny ip from 10.0.0.0/8 to any via dc0
01700          0          0 deny ip from 172.16.0.0/12 to any via dc0
01800          0          0 deny ip from 192.168.0.0/16 to any via dc0
01900          0          0 deny ip from 0.0.0.0/8 to any via dc0
02000          0          0 deny ip from 169.254.0.0/16 to any via dc0
02100          0          0 deny ip from 192.0.2.0/24 to any via dc0
02200          0          0 deny ip from 224.0.0.0/4 to any via dc0
02300          0          0 deny ip from 240.0.0.0/4 to any via dc0
02400          0          0 allow tcp from any to any established
02500          0          0 allow ip from any to any frag
02600          0          0 allow tcp from any to 192.168.1.0/24 dst-port 53 setup
02700          0          0 allow udp from any to 192.168.1.0/24 dst-port 53
02800          0          0 allow udp from 192.168.1.0/24 53 to any
02900          0          0 allow log logamount 100 tcp from any 20 to any in via dc0 setup
03000          0          0 deny log tcp from any to any in via dc0 setup
03100          0          0 allow tcp from any to any out via dc0 setup
03200          0          0 allow udp from any to any dst-port 53 out via dc0 keep-state
03300          0          0 allow udp from any 53 to any in via dc0 keep-state
03400          0          0 deny icmp from not 205.238.0.0/16 to any in via dc0 icmptypes 8
03500          0          0 allow icmp from 205.238.0.0/16 to any in via dc0 icmptypes 8
03600          0          0 allow icmp from any to any out via dc0 icmptypes 8
03700          0          0 allow icmp from any to any in via dc0 icmptypes 0
03800          0          0 allow udp from any to any dst-port 123 via dc0
03900          0          0 allow ip from 66.25.0.0/16 to any via dc0
65535          0          0 deny ip from any to any


=========================================== ssh timeout output from ipfw show


00100          0          0 allow ip from any to any via lo0
00200          0          0 deny ip from any to 127.0.0.0/8
00300          0          0 deny ip from 127.0.0.0/8 to any
00400         13        867 allow ip from any to any via dc1
00500          0          0 deny ip from 192.168.1.0/24 to any in via dc0
00600          0          0 deny ip from 66.25.0.0/16 to any in via dc1
00700          0          0 deny ip from any to 10.0.0.0/8 via dc0
00800          0          0 deny ip from any to 172.16.0.0/12 via dc0
00900          0          0 deny ip from any to 192.168.0.0/16 via dc0
01000          0          0 deny ip from any to 0.0.0.0/8 via dc0
01100          0          0 deny ip from any to 169.254.0.0/16 via dc0
01200          0          0 deny ip from any to 192.0.2.0/24 via dc0
01300          0          0 deny ip from any to 224.0.0.0/4 via dc0
01400          0          0 deny ip from any to 240.0.0.0/4 via dc0
01500         33       2012 divert 8668 ip from any to any via dc0
01600          0          0 deny ip from 10.0.0.0/8 to any via dc0
01700          0          0 deny ip from 172.16.0.0/12 to any via dc0
01800          0          0 deny ip from 192.168.0.0/16 to any via dc0
01900          0          0 deny ip from 0.0.0.0/8 to any via dc0
02000          0          0 deny ip from 169.254.0.0/16 to any via dc0
02100          0          0 deny ip from 192.0.2.0/24 to any via dc0
02200          0          0 deny ip from 224.0.0.0/4 to any via dc0
02300          0          0 deny ip from 240.0.0.0/4 to any via dc0
02400          0          0 allow tcp from any to any established
02500          0          0 allow ip from any to any frag
02600          0          0 allow tcp from any to 192.168.1.0/24 dst-port 53 setup
02700          0          0 allow udp from any to 192.168.1.0/24 dst-port 53
02800          0          0 allow udp from 192.168.1.0/24 53 to any
02900          0          0 allow log logamount 100 tcp from any 20 to any in via dc0 setup
03000          0          0 deny log tcp from any to any in via dc0 setup
03100          9        444 allow tcp from any to any out via dc0 setup
03200          6        607 allow udp from any to any dst-port 53 out via dc0 keep-state
03300          2        293 allow udp from any 53 to any in via dc0 keep-state
03400          0          0 deny icmp from not 205.238.0.0/16 to any in via dc0 icmptypes 8
03500          0          0 allow icmp from 205.238.0.0/16 to any in via dc0 icmptypes 8
03600          0          0 allow icmp from any to any out via dc0 icmptypes 8
03700          0          0 allow icmp from any to any in via dc0 icmptypes 0
03800          0          0 allow udp from any to any dst-port 123 via dc0
03900          0          0 allow ip from 66.25.0.0/16 to any via dc0
65535          0          0 deny ip from any to any


Note the 13 packets incremented the counter on rule 400, the private network
Note the 9 TCP attempts to establish a connection with the ssh server, rule 3100
Note the DNS query/responses, rules 3200 and 3300.

Note that no other counters were incremented to tell me what happened to the
packets that arrived from the ssh server in response to my connection attempt.
Which, I note, I apparently did not save off.

>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200301270243.h0R2h8SQ000897>