* Unable to DNAT packets back into originating bridge port
@ 2014-06-27 17:48 Matthijs Kooijman
2014-06-27 18:52 ` Florian Westphal
0 siblings, 1 reply; 3+ messages in thread
From: Matthijs Kooijman @ 2014-06-27 17:48 UTC (permalink / raw)
To: Stephen Hemminger, Bart De Schuymer; +Cc: bridge, netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 4585 bytes --]
Hey folks,
I recently stumbled upon an issue in my iptables setup. After some
extensive debugging, I've found that the problem occurs when trying to
DNAT (+SNAT) a packet that comes in through a bridge, back into the same bridge
port it originated from.
The code ultimately responsible for this is the should_deliver function
[1], which prevents packets from being delivered back to their
originating port (ultimately to prevent bouncing broadcast message, I
believe).
[1]: https://github.com/torvalds/linux/blob/v3.14/net/bridge/br_forward.c#L30-L36
Another requirement for this issue to occur is the
bridge-nf-call-iptables settings, which must be at the default 1
setting. Without that, the packets are passed up through
br_pass_frame_up normally.
Some more details about my setup:
matthijs@grubby:~$ sudo brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.5cff350f105e no eth0
matthijs@grubby:~$ sudo ifconfig br0|grep inet
inet addr:192.168.1.175 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::5eff:35ff:fe0f:105e/64 Scope:Link
matthijs@grubby:~$ sudo iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DNAT tcp -- anywhere anywhere tcp dpt:81 to:192.168.1.252
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT tcp -- anywhere anywhere tcp dpt:81 to:192.168.1.175
When I now create a connection from a host on eth0, to 192.167.1.175:81, that
packet gets dropped instead of DNATed and SNATed back through eth0 to
192.168.1.184. Enable hairpin mode on eth0, or disabling
bridge-nf-call-iptables makes it work as expected.
Now, is this a bug in the kernel? Or should I not be expecting this setup to work?
While debugging, I reviewed the code to trace the path the packet takes
through the code, and this is what I found (this just from review, I
haven't verified with debug output):
- The packet comes in br_handle_frame
- The frame gets dumped into the NF_BR_PRE_ROUTING netfilter chain
(e.g. the bridge / ebtables version, not the ip / iptables one).
- The ebtables rules get called
- The br_nf_pre_routing hook for NF_BR_PRE_ROUTING gets called. This
interrupts (returns NF_STOLEN) the handling of the NF_BR_PRE_ROUTING
chain, and calls the NF_INET_PRE_ROUTING chain.
- The br_nf_pre_routing_finish finish handler gets called after
completing the NF_INET_PRE_ROUTING chain.
- This handler resumes the handling of the interrupted
NF_BR_PRE_ROUTING chain. However, because it detects that DNAT has
happened, it sets the finish handler to
br_nf_pre_routing_finish_bridge instead of the regular
br_handle_frame_finish finish handler.
- br_nf_pre_routing_finish_bridge runs, this skb->dev to the parent
bridge and sets the BRNF_BRIDGED_DNAT flag which calls
neigh->output(neigh, skb); which presumably resolves to one of the
neigh_*output functions, each of which again calls dev_queue_xmit,
which should (eventually) call br_dev_xmit.
- br_dev_xmit sees the BRNF_BRIDGED_DNAT flag and calls
br_nf_pre_routing_finish_bridge_slow instead of actually delivering
the packet.
- br_nf_pre_routing_finish_bridge_slow sets up the destination MAC
address, sets skb->dev back to skb->physindev and calls
br_handle_frame_finish.
- br_handle_frame_finish calls br_forward.
- br_forward calls should_deliver, which returns false when skb->dev !=
p->dev (and "hairpin mode" is not enabled) causing the packet to be
dropped.
Some things to note:
- Why does the packet get redirected to NF_INET_PRE_ROUTING in
br_nf_pre_routing already? Is it important that it happens halfway
through the NF_BR_PRE_ROUTING chain? If not, why not do it in
br_handle_frame_finish / br_forward when it has actually been
established that the packet will be bridged and not routed?
- Should should_deliver make an exception for DNAT'ed packets? Or
perhaps only block broadcasts.
Also see this blogpost for a bit more details about my original setup
and debugging process:
http://www.stderr.nl/Blog/Software/Linux/BouncingPacketsKernelBug.html
Gr.
Matthijs
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Unable to DNAT packets back into originating bridge port
2014-06-27 17:48 Unable to DNAT packets back into originating bridge port Matthijs Kooijman
@ 2014-06-27 18:52 ` Florian Westphal
2014-06-27 20:00 ` Matthijs Kooijman
0 siblings, 1 reply; 3+ messages in thread
From: Florian Westphal @ 2014-06-27 18:52 UTC (permalink / raw)
To: Matthijs Kooijman, Stephen Hemminger, Bart De Schuymer, bridge,
netfilter-devel
Matthijs Kooijman <matthijs@stdin.nl> wrote:
> I recently stumbled upon an issue in my iptables setup. After some
> extensive debugging, I've found that the problem occurs when trying to
> DNAT (+SNAT) a packet that comes in through a bridge, back into the same bridge
> port it originated from.
>
> The code ultimately responsible for this is the should_deliver function
> [1], which prevents packets from being delivered back to their
> originating port (ultimately to prevent bouncing broadcast message, I
> believe).
Sounds like
http://marc.info/?t=136627796900001&r=1&w=2
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Unable to DNAT packets back into originating bridge port
2014-06-27 18:52 ` Florian Westphal
@ 2014-06-27 20:00 ` Matthijs Kooijman
0 siblings, 0 replies; 3+ messages in thread
From: Matthijs Kooijman @ 2014-06-27 20:00 UTC (permalink / raw)
To: Florian Westphal
Cc: Stephen Hemminger, Bart De Schuymer, bridge, netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 286 bytes --]
Hey Florian,
> Sounds like
> http://marc.info/?t=136627796900001&r=1&w=2
Yup, I'm pretty sure this is the same issue. I hadn't realize the need
for source mac address mangling yet. It didn't show up as a problem
in my setup, but I guess it can be needed in some setups.
Gr.
Matthijs
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2014-06-27 20:01 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-27 17:48 Unable to DNAT packets back into originating bridge port Matthijs Kooijman
2014-06-27 18:52 ` Florian Westphal
2014-06-27 20:00 ` Matthijs Kooijman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).