Re: ipfw nat and smaller wan mtu

2022-12-07 Thread John Hay
Hi,

Adding this patch does make it work for me. There might be better ways to
do it. I have tested with ping and ssh. In ping's case, ping reported:
frag needed and DF set (MTU 1392)

In ssh's case I could see with tcpdump that the "need to frag (mtu 1392)"
was sent back and the next packet's length was adjusted.

#
06:29:59.869677 IP (tos 0x48, ttl 64, id 0, offset 0, flags [DF], proto TCP
(6), length 1500)
10.10.1.3.64344 > 10.10.7.7.22: Flags [.], cksum 0xb64d (correct), seq
39:1487, ack 39, win 1027, options [nop,nop,TS val 260430893 ecr
926374970], length 1448
06:29:59.869954 IP (tos 0x0, ttl 63, id 62454, offset 0, flags [none],
proto ICMP (1), length 596)
10.10.2.2 > 10.10.1.3: ICMP 10.10.7.7 unreachable - need to frag (mtu
1392), length 576
IP (tos 0x48, ttl 63, id 0, offset 0, flags [DF], proto TCP (6), length
1500, bad cksum e081 (->19b7)!)
10.10.1.3.64344 > 10.10.7.7.22: Flags [.], seq 39:1487, ack 39, win
1027, options [nop,nop,TS val 260430893 ecr 926374970], length 1448
06:29:59.871301 IP (tos 0x48, ttl 64, id 0, offset 0, flags [DF], proto TCP
(6), length 1392)
10.10.1.3.64344 > 10.10.7.7.22: Flags [.], cksum 0x6841 (correct), seq
39:1379, ack 39, win 1027, options [nop,nop,TS val 260430893 ecr
926374970], length 1340
#

--- sys/netinet/libalias/alias.c.orig   2022-05-12 04:54:03.0 +
+++ sys/netinet/libalias/alias.c2022-12-08 05:42:25.12798 +
@@ -365,6 +365,19 @@
lnk = NULL;

if (lnk != NULL) {
+   /*
+   If the packet was locally generated, it will have a
+   loopback address as source, which will not be handled
+   correctly. For now use the destination address as source
+   address. The correct source address might be the the
+   interface address that the packet will be going out on.
+   */
+   if (IN_LOOPBACK(ntohl(pip->ip_src.s_addr)) &&
+   !IN_LOOPBACK(ntohl(pip->ip_dst.s_addr))) {
+   DifferentialChecksum(>ip_sum,
+   >ip_dst, >ip_src, 2);
+   pip->ip_src = pip->ip_dst;
+   }
if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) {
int accumulate, accumulate2;
struct in_addr original_address;

On Wed, 7 Dec 2022 at 16:33, John Hay  wrote:

> Hi,
>
> What would the proper ipfw rules be to make nat work and properly get the
> icmp too big packets back to a local host if the wan interface needs a
> smaller mtu?
>
> I'm using a FreeBSD machine as router/firewall, but its wan interface
> needs a smaller mtu (1392) than the default ethernet mtu. I have replicated
> this in a VM so I can test it. My simplified ipfw rules make it work for
> packets that are smaller than the wan mtu:
>
> #
> net.inet.ip.fw.one_pass=0
> net.inet.ip.fw.verbose=1
> #
> fwcmd="/sbin/ipfw -q"
> wan="vtnet0"
> lan="vtnet1"
> ${fwcmd} nat 123 config if ${wan} log
> ${fwcmd} add 1000 count log all from any to any
> ${fwcmd} add 5000 nat 123 ip4 from any to any via ${wan}
> ${fwcmd} add 6000 allow log all from any to any
> #
> The wan ip of the firewall is 10.10.2.2 and the ip address of the host (on
> the lan side) I'm testing from is 10.10.1.3. And I did a ping to 10.10.5.5,
> which is on the other side of the wan interface.
>
> This works for packets smaller than the wan mtu. But if the packet is
> larger than the wan mtu, the icmp too big is generated, but with 127.0.0.1
> as the source and the wan ip as the destination and then sent via lo0 and
> it looks like this in the ipfw log:
>
> Dec  7 13:24:59 rtr kernel: ipfw: 1000 Count ICMP:3.4 127.0.0.1 10.10.2.2
> out via lo0
>
> So I added a nat ipfw rule to catch that:
>
> ${fwcmd} add 5050 nat 123 ip4 from any to not 127.0.0.1 via lo0
>
> That helped partly because it was then able to recover the address of the
> host I was testing from and tried to send the packet out on the correct
> interface (vtnet1). Unfortunately it still had the source address of
> 127.0.0.1, which means it did not actually make it to the wire:
>
> ##
> Dec  7 14:17:31 rtr kernel: ipfw: 1000 Count ICMP:8.0 10.10.1.3 10.10.5.5
> in via vtnet1
> Dec  7 14:17:31 rtr kernel: ipfw: 6000 Accept ICMP:8.0 10.10.1.3 10.10.5.5
> in via vtnet1
> Dec  7 14:17:31 rtr kernel: ipfw: 1000 Count ICMP:8.0 10.10.1.3 10.10.5.5
> out via vtnet0
> Dec  7 14:17:31 rtr kernel: ipfw: 6000 Accept ICMP:8.0 10.10.2.2 10.10.5.5
> out via vtnet0
> Dec  7 14:17:31 rtr kernel: ipfw: 1000 Count ICMP:3.4 127.0.0.1 10.10.2.2
> out via lo0
> Dec  7 14:17:31 rtr kernel: ipfw: 6000 Accept ICMP:3.4 127.0.0.1 10.10.2.2
> out via lo0
> Dec  7 14:17:31 rtr kernel: ipfw: 1000 Count ICMP:3.4 127.0.0.1 10.10.2.2
> in via lo0
> Dec  7 14:17:31 rtr kernel: ipfw: 6000 Accept ICMP:3.4 127.0.0.1 10.10.1.3
> in via lo0
> Dec  7 14:17:31 rtr kernel: ipfw: 1000 Count ICMP:3.4 

ipfw nat and smaller wan mtu

2022-12-07 Thread John Hay
Hi,

What would the proper ipfw rules be to make nat work and properly get the
icmp too big packets back to a local host if the wan interface needs a
smaller mtu?

I'm using a FreeBSD machine as router/firewall, but its wan interface needs
a smaller mtu (1392) than the default ethernet mtu. I have replicated this
in a VM so I can test it. My simplified ipfw rules make it work for packets
that are smaller than the wan mtu:

#
net.inet.ip.fw.one_pass=0
net.inet.ip.fw.verbose=1
#
fwcmd="/sbin/ipfw -q"
wan="vtnet0"
lan="vtnet1"
${fwcmd} nat 123 config if ${wan} log
${fwcmd} add 1000 count log all from any to any
${fwcmd} add 5000 nat 123 ip4 from any to any via ${wan}
${fwcmd} add 6000 allow log all from any to any
#
The wan ip of the firewall is 10.10.2.2 and the ip address of the host (on
the lan side) I'm testing from is 10.10.1.3. And I did a ping to 10.10.5.5,
which is on the other side of the wan interface.

This works for packets smaller than the wan mtu. But if the packet is
larger than the wan mtu, the icmp too big is generated, but with 127.0.0.1
as the source and the wan ip as the destination and then sent via lo0 and
it looks like this in the ipfw log:

Dec  7 13:24:59 rtr kernel: ipfw: 1000 Count ICMP:3.4 127.0.0.1 10.10.2.2
out via lo0

So I added a nat ipfw rule to catch that:

${fwcmd} add 5050 nat 123 ip4 from any to not 127.0.0.1 via lo0

That helped partly because it was then able to recover the address of the
host I was testing from and tried to send the packet out on the correct
interface (vtnet1). Unfortunately it still had the source address of
127.0.0.1, which means it did not actually make it to the wire:

##
Dec  7 14:17:31 rtr kernel: ipfw: 1000 Count ICMP:8.0 10.10.1.3 10.10.5.5
in via vtnet1
Dec  7 14:17:31 rtr kernel: ipfw: 6000 Accept ICMP:8.0 10.10.1.3 10.10.5.5
in via vtnet1
Dec  7 14:17:31 rtr kernel: ipfw: 1000 Count ICMP:8.0 10.10.1.3 10.10.5.5
out via vtnet0
Dec  7 14:17:31 rtr kernel: ipfw: 6000 Accept ICMP:8.0 10.10.2.2 10.10.5.5
out via vtnet0
Dec  7 14:17:31 rtr kernel: ipfw: 1000 Count ICMP:3.4 127.0.0.1 10.10.2.2
out via lo0
Dec  7 14:17:31 rtr kernel: ipfw: 6000 Accept ICMP:3.4 127.0.0.1 10.10.2.2
out via lo0
Dec  7 14:17:31 rtr kernel: ipfw: 1000 Count ICMP:3.4 127.0.0.1 10.10.2.2
in via lo0
Dec  7 14:17:31 rtr kernel: ipfw: 6000 Accept ICMP:3.4 127.0.0.1 10.10.1.3
in via lo0
Dec  7 14:17:31 rtr kernel: ipfw: 1000 Count ICMP:3.4 127.0.0.1 10.10.1.3
out via vtnet1
Dec  7 14:17:31 rtr kernel: ipfw: 6000 Accept ICMP:3.4 127.0.0.1 10.10.1.3
out via vtnet1
##

Once I have this sorted, there seems to be a similar problem with nptv6.

Regards

John