netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Florian Westphal <fw@strlen.de>
To: Bart De Schuymer <bdschuym@pandora.be>
Cc: Florian Westphal <fw@strlen.de>,
	netdev@vger.kernel.org, netfilter-devel@vger.kernel.org
Subject: Re: [PATCH] bridge: fix IP DNAT handling when packet is sent back via same bport
Date: Thu, 18 Apr 2013 23:02:20 +0200	[thread overview]
Message-ID: <20130418210220.GI1408@breakpoint.cc> (raw)
In-Reply-To: <51705267.3070909@pandora.be>

Bart De Schuymer <bdschuym@pandora.be> wrote:
> Op 18/04/2013 11:37, Florian Westphal schreef:
> >commit e179e6322ac334e21a3c6d669d95bc967e5d0a80
> >(netfilter: bridge-netfilter: Fix MAC header handling with IP DNAT)
> >breaks DNAT when the destination address sits on the same bridgeport
> >the packet originally arrived on.  Example:
> >
> >( Network1 ) -- [ eth1-Bridge-eth0 ] -- ( Network2 )
> >
> >Lets assume bridge has ip 192.168.10.8, and following netfilter rules
> >are active:
> >
> >-A PREROUTING  -s 192.168.10.1 -d 192.168.10.8 -p tcp --dport 21 -j DNAT --to-destination 192.168.10.1
> >-A POSTROUTING -s 192.168.10.1 -d 192.168.10.1 -p tcp --dport 21 -j SNAT --to-source 192.168.10.8
> 
> >With kernels before 2.6.35, this makes host 192.168.10.1 connecting to
> >the bridge on port 21 connect-to-self.
> 
> I don't get why you didn't need the hairpin mode back then.

because afaics before packets were just sent from the bridge, i.e. no
forward path and no should_deliver() check.

[..]

> In my opinion this is just a special kind of MAC SNAT and you can
> already achieve this with hairpin mode, ebtables and iptables now:
>
> 1. make sure to mark the packets with iptables before you perform the DNAT
> 2. in ebtables POSTROUTING, SNAT those marked packets with the MAC
> address of the bridge.
> 3. enable hairpin mode
> Even if it turns out not yet to be fully possible with the current
> kernel, I think such a feature should be implemented as an ebtables
> target instead of increasing the complexity of the generic code.

Well, I am all for doing this with existing tools, problem is
userspace didn't change but newer kernels don't work as they used to.

If consensus is 'too bad, fix configuration' I can accept that.
The fact that noone seems to have reported this until now
pretty much proves that virtually noone has such configurations.

> Your patch also introduces potential unexpected behavior in
> different scenarios. Consider the following rule:
> -A PREROUTING -s 192.168.10.1 -d 192.168.10.8 -p tcp --dport 21 -j
> DNAT --to-destination 192.168.10.2
> Note that the DNAT is to a different IP address. Suppose
> 192.168.10.2 is on a different machine located on the same side of
> the bridge. Your patch would change the MAC source address here too
> without any need.

Not sure if this is even possible, as 10.1 would discard the syn/ack
from 10.2 (expects reply from 10.8 address).

But I think understand what you're saying.

> >diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
> >index dfb4d9e..eacd206 100644
> >--- a/include/linux/netfilter_bridge.h
> >+++ b/include/linux/netfilter_bridge.h
> >@@ -23,6 +23,8 @@ enum nf_br_hook_priorities {
> >  #define BRNF_NF_BRIDGE_PREROUTING	0x08
> >  #define BRNF_8021Q			0x10
> >  #define BRNF_PPPoE			0x20
> >+/* DNAT'd packet is to be sent back on same bridge port: */
> >+#define BRNF_BRIDGED_DNAT_DODGY		0x40
> 
> Obviously, a more descriptive name would be nice :)

I failed to come up with something that isn't more explicit ;)
But I'll try.

> >+static int forward_should_deliver(const struct net_bridge_port *to,
> >+				  struct sk_buff *skb)
> >+{
> >+#ifdef CONFIG_BRIDGE_NETFILTER
> >+	if (skb->dev == to->dev &&
> >+	    skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) {
> >+		skb->nf_bridge->mask |= BRNF_BRIDGED_DNAT_DODGY;
> 
> You should unset the BRNF_BRIDGED_DNAT mask here (no longer needed
> and might confuse other code yet to be executed):
> skb->nf_bridge->mask ^= BRNF_BRIDGED_DNAT;

Sounds reasonable.

> >+		return to->state == BR_STATE_FORWARDING &&
> >+			br_allowed_egress(to->br, nbp_get_vlan_info(to), skb);
> 
> I don't like this change. It's basically a hack to prevent having to
> enable the hairpin mode.

Yes. It wasn't necessary before.  If the consensus is that it should be
used in this case, I am ok with that.

> Putting the new code in should_deliver() would have prevented you
> from having to come up with a new and not very descriptive function
> name.

I wanted to make sure that this extra DNAT crud is not e.g. called in
the multi/broadcast flood case, but only for plain br_forward().

> >+		/* tell br_dev_xmit to continue with forwarding, make
> >+		 * fwd path handle inport == outport case
> >+		 */
> >+		nf_bridge->mask |= BRNF_BRIDGED_DNAT;
> 
> I think you'll be ok here, as long as you unset the mask later (as
> mentioned above).

Noted, thanks for reviewing.

Regards,
Florian

      reply	other threads:[~2013-04-18 21:02 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-18  9:37 [PATCH] bridge: fix IP DNAT handling when packet is sent back via same bport Florian Westphal
2013-04-18 20:07 ` Bart De Schuymer
2013-04-18 21:02   ` Florian Westphal [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130418210220.GI1408@breakpoint.cc \
    --to=fw@strlen.de \
    --cc=bdschuym@pandora.be \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).