Subject: kern/10993: [ipf] NAT uses wrong IPv4 source address on NEEDFRAG message
To: None <gnats-bugs@gnats.netbsd.org>
From: None <itojun@itojun.org>
List: netbsd-bugs
Date: 09/11/2000 16:46:13
>Number:         10993
>Category:       kern
>Synopsis:       [ipf] NAT uses wrong IPv4 source address on NEEDFRAG message
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Sep 11 16:47:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Jun-ichiro itojun Hagino
>Release:        NetBSD 1.4.2, possibly current too
>Organization:
	itojun.org
>Environment:
System: NetBSD lychee.itojun.org 1.4.2 NetBSD 1.4.2 (LYCHEE.v6) #1138: Sun Sep 10 22:00:15 JST 2000 itojun@lychee.itojun.org:/export/home/itojun/k/kame/netbsd/sys/arch/i386/compile/LYCHEE.v6 i386


>Description:
	If we set NAT box with difrerent interface MTU on two sides,
	ipfilter will transmit wrong ICMPv6 "need fragment" message.

>How-To-Repeat:
	setup the following configuration.  NAT box has two IPv4 address
	B and C, http server has A, http client has C.
	C and D are private address.
	also setup MTU(B) to be > MTU(C).  setup A to perform path MTU
	discovery, and make sure A to send TCP packets with DF bit raised.

	(http server) A --- B (NAT box) C --- D (http client)

		global address		private address

	try to transfer large amount of data from A to D.  Eventually,
	A will transmit a packet which fits MTU(B) but does not fit MTU(C).
	NAT box.
		orginal packet from A:  A --> B

	The packet will be rewritten in ip_nat.c:ip_natin(), and passed to
	ip_fil.c:ipfr_fastroute().
		after ip_natin(): A --> D

	ipfr_fastroute() cannot forward the packet to interface C
	(as MTU is too big), and NAT box will attempt to transmit an ICMPv4
	"need fragment" error message, against the packet, via
	ip_fil.c:send_icmp_err().

	send_icmp_err() constructs ICMPv4 need fragment packet.  The packet
	will become like this:
		IPv4 header: B --> A	(correct)
		ICMPv4 header: need fragment
		old IPv4 packet: A --> D (wrong)
	here, the destination address of the old IPv4 packet needs to be
	translated back to "A --> B".  otherwise, A will not recognize
	smaller-than-normal path MTU between A and D, and tcp session will
	choke (hang up).

>Fix:
	improve send_icmp_err().  make a nat_outlookup() against IPv4
	destination of the original packet (D), and rewrite it back to 
	global address of NAT box (B).
>Release-Note:
>Audit-Trail:
>Unformatted: