NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/52074: -current npf map directive broken



On 05/08/17 11:04, Roy Marples wrote:
Hi Frank!

On 07/05/2017 22:07, Frank Kardel wrote:
Hmm, wouldn't this bring us back the bug again? ia == NULL for a
non-local source addresses (generated via pfil_run_hooks-NAT operation)
and IP_FORWARDING is not set as tcp_input.c:syn_cache_respond does
rightfully not set IP_FORWARDING and pfil_run_hooks has no means to set
that flag. That gives us error == -1 with your sequence.
So we would return EADDRNOTAVAIL breaking packet filter NAT action
again, if I didn't overlook something.
Ah yes.
I didn't actually read your initial report .... my bad!
No worries - I am just trying to keep us from running too far in the wrong direction.
OK, so I don't fully understand the use case for sending packets from an
address we don't have locally. Could you fill me in on this please?
The mapping is as follows

Machine A (Client) Machine B (Gateway/NAT/redirect box) Machine C (target) a.b.c.d:x -> W.X.Y.Z -> 10.200.1.2 (will never see a packet from a.b.c.dx)
                          map 127.0.0.1 25 <- 10.200.1.2 25
                          redirects to 127.0.0.1 25 (local)
A must see the association a.b.c.d:x <-> 10.200.1.2:25

Thus local postfix will see a.b.c.d x <-> 127.0.0.1 25

So dest addr 10.200.1.2 will be replaced incoming with 127.0.0.1 25 in pf_fil_run_hooks in ip_input and on the way back the src addr of 127.0.0.1 is replaced with 10.200.1.2 (not local)
                          in pfil_run_hooks in ip_output.

To quote the condensed analysis from the bug + where in the stack it happens:

 Following happens:
 1) ip_input: packet arrives on interface (a.b.c.d:x -> 10.200.1.2:25
 1a) ip_input call pfil_run_hooks -> NPF
 2) NPF: NAT assoc gets created
 3) NPF: packet gets NATed (=> a.b.c.d:x -> 127.0.0.1:25)
 3a) NPF returns
 3b) ip_input hands over to tcp_input
 4) tcp_input: packet gets entered in syn_cache
 5) tcp_input: syn_cache attempts to send SYN,ACK response (127.0.0.1:25 ->
 a.b.c.d:x) via ip_output()
 6) ip_output: ip_output calls pfil_hooks (->NPF)
 7) NPF: find nat assoc
 8) NPF: SYN,ACK packet gets reverse NATed (10.200.1.2:25 -> a.b.c.d:x)
 8a) NPF returns
 9) ip_output: ip_output tries for find the interface adress (ia) for 10.200.1.2 and
 fails (ia == NULL)
 10) ip_output: ip_output fumbles badly at ip_output:1.276:620 and declares the
 packet coming from an invalid address(ip_ifaddrvalid(NULL))
 11) confusion commences from here on


 From what I understand  this code originally attempted to avoid sending
from invalid/unusable local address (e. g. duplicate IP - error,
tentative and detached should just be dropped).
No validation can be done for non-local addresses at all. IP_FORWARDING
formerly used to be used to suppress infinite recursion on mcast
forwarding, but it seems the semantics where extended a little bit in
the mean time (like here to suppress a check).
So I cannot say something about the intentions for the IP_FORWARDING check.
I *think* the idea was IP_FORWARDING would be set and we could skip
source address validation because the filter may have changed it.
https://nxr.netbsd.org/xref/src/sys/net/npf/npf_sendpkt.c#178
That's what I thought was the intention. As you see above the transmitted SYN,ACK is not created by NPF and not by npf_sendpkt.c#178. NPF and other filters do an in place header modification and the flags variable is not part of pfil_run_hooks(). So
the IP_FORWARDING logic cannot be used by the packet filters AFAICS.
Does NAT not hit that?
Nope - see above - coming directly from tcp_input:syn_cache_add:syn_cache_respond. IP_FORWARD is not set there. Before the packet filter we still have a valid local address, Maybe we should move the check there - IPv6 also does the check before IIANM.
  I ask because I do run NPF+NAT on my erlite
router which uses -current, but my mapping rule uses a local address -
hence asking for your use case about a non local address.

Could NAT set another flag we could check? rmind?
OTOMHI see
1) extend pfil_run_hooks interface to pass a pointer to flags- relatively cheap, somewhat dirty 2) add a tag the the mbuf - more expensive b/c we also need to add checks

Would we gain enough speed/functionality/abstraction to warrant an interface change? Does the condition "before packet filter we have either IP_FORWARD set or a local address as source" always hold? If so, we could just move the check and set up ia correctly for IFASTATS.IPv6 checks before packet filter runs.

I have not analyzed the invariants enough to make a quick recommendation here.

I hope I explained the setup good enough to describe the issue with NAT redirection.


Roy
Frank


Home | Main Index | Thread Index | Old Index