2019-11-08 21:08:24

by Aaron Conole

[permalink] [raw]
Subject: [PATCH net 1/2] openvswitch: support asymmetric conntrack

The openvswitch module shares a common conntrack and NAT infrastructure
exposed via netfilter. It's possible that a packet needs both SNAT and
DNAT manipulation, due to e.g. tuple collision. Netfilter can support
this because it runs through the NAT table twice - once on ingress and
again after egress. The openvswitch module doesn't have such capability.

Like netfilter hook infrastructure, we should run through NAT twice to
keep the symmetry.

Fixes: 05752523e565 ("openvswitch: Interface with NAT.")
Signed-off-by: Aaron Conole <[email protected]>
---
net/openvswitch/conntrack.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index 05249eb45082..283e8f9a5fd2 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -903,6 +903,17 @@ static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
}
err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype);

+ if (err == NF_ACCEPT &&
+ ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
+ if (maniptype == NF_NAT_MANIP_SRC)
+ maniptype = NF_NAT_MANIP_DST;
+ else
+ maniptype = NF_NAT_MANIP_SRC;
+
+ err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range,
+ maniptype);
+ }
+
/* Mark NAT done if successful and update the flow key. */
if (err == NF_ACCEPT)
ovs_nat_update_key(key, skb, maniptype);
--
2.21.0


2019-11-08 21:11:07

by Aaron Conole

[permalink] [raw]
Subject: [PATCH net 2/2] act_ct: support asymmetric conntrack

The act_ct TC module shares a common conntrack and NAT infrastructure
exposed via netfilter. It's possible that a packet needs both SNAT and
DNAT manipulation, due to e.g. tuple collision. Netfilter can support
this because it runs through the NAT table twice - once on ingress and
again after egress. The act_ct action doesn't have such capability.

Like netfilter hook infrastructure, we should run through NAT twice to
keep the symmetry.

Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")

Signed-off-by: Aaron Conole <[email protected]>
---
net/sched/act_ct.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
index fcc46025e790..f3232a00970f 100644
--- a/net/sched/act_ct.c
+++ b/net/sched/act_ct.c
@@ -329,6 +329,7 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
bool commit)
{
#if IS_ENABLED(CONFIG_NF_NAT)
+ int err;
enum nf_nat_manip_type maniptype;

if (!(ct_action & TCA_CT_ACT_NAT))
@@ -359,7 +360,17 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
return NF_ACCEPT;
}

- return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
+ err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
+ if (err == NF_ACCEPT &&
+ ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
+ if (maniptype == NF_NAT_MANIP_SRC)
+ maniptype = NF_NAT_MANIP_DST;
+ else
+ maniptype = NF_NAT_MANIP_SRC;
+
+ err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
+ }
+ return err;
#else
return NF_ACCEPT;
#endif
--
2.21.0

2019-11-09 22:17:03

by Pravin Shelar

[permalink] [raw]
Subject: Re: [PATCH net 1/2] openvswitch: support asymmetric conntrack

On Fri, Nov 8, 2019 at 1:07 PM Aaron Conole <[email protected]> wrote:
>
> The openvswitch module shares a common conntrack and NAT infrastructure
> exposed via netfilter. It's possible that a packet needs both SNAT and
> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
> this because it runs through the NAT table twice - once on ingress and
> again after egress. The openvswitch module doesn't have such capability.
>
> Like netfilter hook infrastructure, we should run through NAT twice to
> keep the symmetry.
>
> Fixes: 05752523e565 ("openvswitch: Interface with NAT.")
> Signed-off-by: Aaron Conole <[email protected]>

The patch looks ok. But I am not able apply it. can you fix the encoding.

2019-11-12 08:54:10

by Nicolas Dichtel

[permalink] [raw]
Subject: Re: [PATCH net 1/2] openvswitch: support asymmetric conntrack

Le 08/11/2019 ? 22:07, Aaron Conole a ?crit?:
> The openvswitch module shares a common conntrack and NAT infrastructure
> exposed via netfilter. It's possible that a packet needs both SNAT and
> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
> this because it runs through the NAT table twice - once on ingress and
> again after egress. The openvswitch module doesn't have such capability.
>
> Like netfilter hook infrastructure, we should run through NAT twice to
> keep the symmetry.
>
> Fixes: 05752523e565 ("openvswitch: Interface with NAT.")
> Signed-off-by: Aaron Conole <[email protected]>
In this case, ovs_ct_find_existing() won't be able to find the conntrack, right?
Inverting the tuple to find the conntrack doesn't work anymore with double NAT.
Am I wrong?


Regards,
Nicolas

2019-11-14 14:25:00

by Roi Dayan

[permalink] [raw]
Subject: Re: [PATCH net 2/2] act_ct: support asymmetric conntrack



On 2019-11-08 11:07 PM, Aaron Conole wrote:
> The act_ct TC module shares a common conntrack and NAT infrastructure
> exposed via netfilter. It's possible that a packet needs both SNAT and
> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
> this because it runs through the NAT table twice - once on ingress and
> again after egress. The act_ct action doesn't have such capability.
>
> Like netfilter hook infrastructure, we should run through NAT twice to
> keep the symmetry.
>
> Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
>
> Signed-off-by: Aaron Conole <[email protected]>
> ---
> net/sched/act_ct.c | 13 ++++++++++++-
> 1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
> index fcc46025e790..f3232a00970f 100644
> --- a/net/sched/act_ct.c
> +++ b/net/sched/act_ct.c
> @@ -329,6 +329,7 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
> bool commit)
> {
> #if IS_ENABLED(CONFIG_NF_NAT)
> + int err;
> enum nf_nat_manip_type maniptype;
>
> if (!(ct_action & TCA_CT_ACT_NAT))
> @@ -359,7 +360,17 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
> return NF_ACCEPT;
> }
>
> - return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> + if (err == NF_ACCEPT &&
> + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
> + if (maniptype == NF_NAT_MANIP_SRC)
> + maniptype = NF_NAT_MANIP_DST;
> + else
> + maniptype = NF_NAT_MANIP_SRC;
> +
> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> + }
> + return err;
> #else
> return NF_ACCEPT;
> #endif
>

+paul

2019-11-14 14:25:38

by Paul Blakey

[permalink] [raw]
Subject: Re: [PATCH net 2/2] act_ct: support asymmetric conntrack

On 11/14/2019 4:22 PM, Roi Dayan wrote:
>
> On 2019-11-08 11:07 PM, Aaron Conole wrote:
>> The act_ct TC module shares a common conntrack and NAT infrastructure
>> exposed via netfilter. It's possible that a packet needs both SNAT and
>> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
>> this because it runs through the NAT table twice - once on ingress and
>> again after egress. The act_ct action doesn't have such capability.
>>
>> Like netfilter hook infrastructure, we should run through NAT twice to
>> keep the symmetry.
>>
>> Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
>>
>> Signed-off-by: Aaron Conole <[email protected]>
>> ---
>> net/sched/act_ct.c | 13 ++++++++++++-
>> 1 file changed, 12 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
>> index fcc46025e790..f3232a00970f 100644
>> --- a/net/sched/act_ct.c
>> +++ b/net/sched/act_ct.c
>> @@ -329,6 +329,7 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
>> bool commit)
>> {
>> #if IS_ENABLED(CONFIG_NF_NAT)
>> + int err;
>> enum nf_nat_manip_type maniptype;
>>
>> if (!(ct_action & TCA_CT_ACT_NAT))
>> @@ -359,7 +360,17 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
>> return NF_ACCEPT;
>> }
>>
>> - return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>> + if (err == NF_ACCEPT &&
>> + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
>> + if (maniptype == NF_NAT_MANIP_SRC)
>> + maniptype = NF_NAT_MANIP_DST;
>> + else
>> + maniptype = NF_NAT_MANIP_SRC;
>> +
>> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>> + }
>> + return err;
>> #else
>> return NF_ACCEPT;
>> #endif
>>
> +paul

Hi Aaron,

I think I understand the issue and this looks good,

Can you describe the scenario to reproduce this?


Thanks,

Paul.



2019-11-14 16:31:31

by Marcelo Ricardo Leitner

[permalink] [raw]
Subject: Re: [PATCH net 2/2] act_ct: support asymmetric conntrack

On Fri, Nov 08, 2019 at 04:07:14PM -0500, Aaron Conole wrote:
> The act_ct TC module shares a common conntrack and NAT infrastructure
> exposed via netfilter. It's possible that a packet needs both SNAT and
> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
> this because it runs through the NAT table twice - once on ingress and
> again after egress. The act_ct action doesn't have such capability.
>
> Like netfilter hook infrastructure, we should run through NAT twice to
> keep the symmetry.
>
> Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
>
> Signed-off-by: Aaron Conole <[email protected]>
> ---
> net/sched/act_ct.c | 13 ++++++++++++-
> 1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
> index fcc46025e790..f3232a00970f 100644
> --- a/net/sched/act_ct.c
> +++ b/net/sched/act_ct.c
> @@ -329,6 +329,7 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
> bool commit)
> {
> #if IS_ENABLED(CONFIG_NF_NAT)
> + int err;
> enum nf_nat_manip_type maniptype;
>
> if (!(ct_action & TCA_CT_ACT_NAT))
> @@ -359,7 +360,17 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
> return NF_ACCEPT;
> }
>
> - return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> + if (err == NF_ACCEPT &&
> + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
> + if (maniptype == NF_NAT_MANIP_SRC)
> + maniptype = NF_NAT_MANIP_DST;
> + else
> + maniptype = NF_NAT_MANIP_SRC;
> +
> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> + }

I keep thinking about this and I'm not entirely convinced that this
shouldn't be simpler. More like:

if (DNAT)
DNAT
if (SNAT)
SNAT

So it always does DNAT before SNAT, similarly to what iptables would
do on PRE/POSTROUTING chains.

> + return err;
> #else
> return NF_ACCEPT;
> #endif
> --
> 2.21.0
>

2019-11-18 20:40:59

by Aaron Conole

[permalink] [raw]
Subject: Re: [PATCH net 1/2] openvswitch: support asymmetric conntrack

Pravin Shelar <[email protected]> writes:

> On Fri, Nov 8, 2019 at 1:07 PM Aaron Conole <[email protected]> wrote:
>>
>> The openvswitch module shares a common conntrack and NAT infrastructure
>> exposed via netfilter. It's possible that a packet needs both SNAT and
>> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
>> this because it runs through the NAT table twice - once on ingress and
>> again after egress. The openvswitch module doesn't have such capability.
>>
>> Like netfilter hook infrastructure, we should run through NAT twice to
>> keep the symmetry.
>>
>> Fixes: 05752523e565 ("openvswitch: Interface with NAT.")
>> Signed-off-by: Aaron Conole <[email protected]>
>
> The patch looks ok. But I am not able apply it. can you fix the encoding.

Hrrm. I didn't make any special changes (just used git send-email). I
will look at spinning a second patch.

2019-11-18 21:23:18

by Aaron Conole

[permalink] [raw]
Subject: Re: [PATCH net 1/2] openvswitch: support asymmetric conntrack

Nicolas Dichtel <[email protected]> writes:

> Le 08/11/2019 à 22:07, Aaron Conole a écrit :
>> The openvswitch module shares a common conntrack and NAT infrastructure
>> exposed via netfilter. It's possible that a packet needs both SNAT and
>> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
>> this because it runs through the NAT table twice - once on ingress and
>> again after egress. The openvswitch module doesn't have such capability.
>>
>> Like netfilter hook infrastructure, we should run through NAT twice to
>> keep the symmetry.
>>
>> Fixes: 05752523e565 ("openvswitch: Interface with NAT.")
>> Signed-off-by: Aaron Conole <[email protected]>
> In this case, ovs_ct_find_existing() won't be able to find the
> conntrack, right?

vswitchd normally won't allow both actions to get programmed. Even the
kernel module won't allow it, so this really will only happen when the
connection gets established via the nf_hook path, and then needs to be
processed via openvswitch. In those cases, the tuple lookup should be
correct, because the nf_nat table should contain the correct tuple data,
and the skbuff should have the correct tuples in the packet data to
begin with.

> Inverting the tuple to find the conntrack doesn't work anymore with double NAT.
> Am I wrong?

I think since the packet was double-NAT on the way out (via nf_hook
path), then the incoming reply will have the correct NAT tuples and the
lookup will happen just fine. Just that during processing, both
transformations aren't applied.

Makes sense?

> Regards,
> Nicolas

2019-11-18 21:25:17

by Aaron Conole

[permalink] [raw]
Subject: Re: [PATCH net 2/2] act_ct: support asymmetric conntrack

Marcelo Ricardo Leitner <[email protected]> writes:

> On Fri, Nov 08, 2019 at 04:07:14PM -0500, Aaron Conole wrote:
>> The act_ct TC module shares a common conntrack and NAT infrastructure
>> exposed via netfilter. It's possible that a packet needs both SNAT and
>> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
>> this because it runs through the NAT table twice - once on ingress and
>> again after egress. The act_ct action doesn't have such capability.
>>
>> Like netfilter hook infrastructure, we should run through NAT twice to
>> keep the symmetry.
>>
>> Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
>>
>> Signed-off-by: Aaron Conole <[email protected]>
>> ---
>> net/sched/act_ct.c | 13 ++++++++++++-
>> 1 file changed, 12 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
>> index fcc46025e790..f3232a00970f 100644
>> --- a/net/sched/act_ct.c
>> +++ b/net/sched/act_ct.c
>> @@ -329,6 +329,7 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
>> bool commit)
>> {
>> #if IS_ENABLED(CONFIG_NF_NAT)
>> + int err;
>> enum nf_nat_manip_type maniptype;
>>
>> if (!(ct_action & TCA_CT_ACT_NAT))
>> @@ -359,7 +360,17 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
>> return NF_ACCEPT;
>> }
>>
>> - return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>> + if (err == NF_ACCEPT &&
>> + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
>> + if (maniptype == NF_NAT_MANIP_SRC)
>> + maniptype = NF_NAT_MANIP_DST;
>> + else
>> + maniptype = NF_NAT_MANIP_SRC;
>> +
>> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>> + }
>
> I keep thinking about this and I'm not entirely convinced that this
> shouldn't be simpler. More like:
>
> if (DNAT)
> DNAT
> if (SNAT)
> SNAT
>
> So it always does DNAT before SNAT, similarly to what iptables would
> do on PRE/POSTROUTING chains.

I can rewrite the whole function, but I wanted to start with the smaller
fix that worked. I also think it needs more testing then (since it's
something of a rewrite of the function).

I guess it's not too important - do you think it gives any readability
to do it this way? If so, I can respin the patch changing it like you
describe.

>> + return err;
>> #else
>> return NF_ACCEPT;
>> #endif
>> --
>> 2.21.0
>>

2019-11-18 21:26:20

by Aaron Conole

[permalink] [raw]
Subject: Re: [PATCH net 2/2] act_ct: support asymmetric conntrack

Paul Blakey <[email protected]> writes:

> On 11/14/2019 4:22 PM, Roi Dayan wrote:
>>
>> On 2019-11-08 11:07 PM, Aaron Conole wrote:
>>> The act_ct TC module shares a common conntrack and NAT infrastructure
>>> exposed via netfilter. It's possible that a packet needs both SNAT and
>>> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
>>> this because it runs through the NAT table twice - once on ingress and
>>> again after egress. The act_ct action doesn't have such capability.
>>>
>>> Like netfilter hook infrastructure, we should run through NAT twice to
>>> keep the symmetry.
>>>
>>> Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
>>>
>>> Signed-off-by: Aaron Conole <[email protected]>
>>> ---
>>> net/sched/act_ct.c | 13 ++++++++++++-
>>> 1 file changed, 12 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
>>> index fcc46025e790..f3232a00970f 100644
>>> --- a/net/sched/act_ct.c
>>> +++ b/net/sched/act_ct.c
>>> @@ -329,6 +329,7 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
>>> bool commit)
>>> {
>>> #if IS_ENABLED(CONFIG_NF_NAT)
>>> + int err;
>>> enum nf_nat_manip_type maniptype;
>>>
>>> if (!(ct_action & TCA_CT_ACT_NAT))
>>> @@ -359,7 +360,17 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
>>> return NF_ACCEPT;
>>> }
>>>
>>> - return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>>> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>>> + if (err == NF_ACCEPT &&
>>> + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
>>> + if (maniptype == NF_NAT_MANIP_SRC)
>>> + maniptype = NF_NAT_MANIP_DST;
>>> + else
>>> + maniptype = NF_NAT_MANIP_SRC;
>>> +
>>> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>>> + }
>>> + return err;
>>> #else
>>> return NF_ACCEPT;
>>> #endif
>>>
>> +paul
>
> Hi Aaron,
>
> I think I understand the issue and this looks good,
>
> Can you describe the scenario to reproduce this?

It reproduces with OpenShift 3.10, which makes forward direction packets
between namespaces pump through a tun device that applies NAT rules to
rewrite the dest. Limit the namespace number of ephemeral sockets using
by editing net.ipv4.ip_local_port_range in the client namespace, and
connect to the server namespace. That's the mechanism for OvS. But for
TC I guess there wouldn't be anything convenient avaiable.

I'll try to script up something that doesn't use openshift.

>
> Thanks,
>
> Paul.

2019-11-18 22:42:21

by Marcelo Ricardo Leitner

[permalink] [raw]
Subject: Re: [PATCH net 2/2] act_ct: support asymmetric conntrack

On Mon, Nov 18, 2019 at 04:21:39PM -0500, Aaron Conole wrote:
> Marcelo Ricardo Leitner <[email protected]> writes:
>
> > On Fri, Nov 08, 2019 at 04:07:14PM -0500, Aaron Conole wrote:
> >> The act_ct TC module shares a common conntrack and NAT infrastructure
> >> exposed via netfilter. It's possible that a packet needs both SNAT and
> >> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
> >> this because it runs through the NAT table twice - once on ingress and
> >> again after egress. The act_ct action doesn't have such capability.
> >>
> >> Like netfilter hook infrastructure, we should run through NAT twice to
> >> keep the symmetry.
> >>
> >> Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
> >>
> >> Signed-off-by: Aaron Conole <[email protected]>
> >> ---
> >> net/sched/act_ct.c | 13 ++++++++++++-
> >> 1 file changed, 12 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
> >> index fcc46025e790..f3232a00970f 100644
> >> --- a/net/sched/act_ct.c
> >> +++ b/net/sched/act_ct.c
> >> @@ -329,6 +329,7 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
> >> bool commit)
> >> {
> >> #if IS_ENABLED(CONFIG_NF_NAT)
> >> + int err;
> >> enum nf_nat_manip_type maniptype;
> >>
> >> if (!(ct_action & TCA_CT_ACT_NAT))
> >> @@ -359,7 +360,17 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
> >> return NF_ACCEPT;
> >> }
> >>
> >> - return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> >> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> >> + if (err == NF_ACCEPT &&
> >> + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
> >> + if (maniptype == NF_NAT_MANIP_SRC)
> >> + maniptype = NF_NAT_MANIP_DST;
> >> + else
> >> + maniptype = NF_NAT_MANIP_SRC;
> >> +
> >> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> >> + }
> >
> > I keep thinking about this and I'm not entirely convinced that this
> > shouldn't be simpler. More like:
> >
> > if (DNAT)
> > DNAT
> > if (SNAT)
> > SNAT
> >
> > So it always does DNAT before SNAT, similarly to what iptables would
> > do on PRE/POSTROUTING chains.
>
> I can rewrite the whole function, but I wanted to start with the smaller
> fix that worked. I also think it needs more testing then (since it's
> something of a rewrite of the function).
>
> I guess it's not too important - do you think it gives any readability
> to do it this way? If so, I can respin the patch changing it like you
> describe.

I didn't mean a rewrite, but just to never handle SNAT before DNAT. So
the fix here would be like:

- return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
+ err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
+ if (err == NF_ACCEPT && maniptype == NF_NAT_MANIP_DST &&
+ ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
+ maniptype = NF_NAT_MANIP_SRC;
+ err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
+ }
+ return err;

> >> + return err;
> >> #else
> >> return NF_ACCEPT;
> >> #endif
> >> --
> >> 2.21.0
> >>
>

2019-11-22 20:41:43

by Aaron Conole

[permalink] [raw]
Subject: Re: [PATCH net 2/2] act_ct: support asymmetric conntrack

Marcelo Ricardo Leitner <[email protected]> writes:

> On Mon, Nov 18, 2019 at 04:21:39PM -0500, Aaron Conole wrote:
>> Marcelo Ricardo Leitner <[email protected]> writes:
>>
>> > On Fri, Nov 08, 2019 at 04:07:14PM -0500, Aaron Conole wrote:
>> >> The act_ct TC module shares a common conntrack and NAT infrastructure
>> >> exposed via netfilter. It's possible that a packet needs both SNAT and
>> >> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
>> >> this because it runs through the NAT table twice - once on ingress and
>> >> again after egress. The act_ct action doesn't have such capability.
>> >>
>> >> Like netfilter hook infrastructure, we should run through NAT twice to
>> >> keep the symmetry.
>> >>
>> >> Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
>> >>
>> >> Signed-off-by: Aaron Conole <[email protected]>
>> >> ---
>> >> net/sched/act_ct.c | 13 ++++++++++++-
>> >> 1 file changed, 12 insertions(+), 1 deletion(-)
>> >>
>> >> diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
>> >> index fcc46025e790..f3232a00970f 100644
>> >> --- a/net/sched/act_ct.c
>> >> +++ b/net/sched/act_ct.c
>> >> @@ -329,6 +329,7 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
>> >> bool commit)
>> >> {
>> >> #if IS_ENABLED(CONFIG_NF_NAT)
>> >> + int err;
>> >> enum nf_nat_manip_type maniptype;
>> >>
>> >> if (!(ct_action & TCA_CT_ACT_NAT))
>> >> @@ -359,7 +360,17 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
>> >> return NF_ACCEPT;
>> >> }
>> >>
>> >> - return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>> >> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>> >> + if (err == NF_ACCEPT &&
>> >> + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
>> >> + if (maniptype == NF_NAT_MANIP_SRC)
>> >> + maniptype = NF_NAT_MANIP_DST;
>> >> + else
>> >> + maniptype = NF_NAT_MANIP_SRC;
>> >> +
>> >> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
>> >> + }
>> >
>> > I keep thinking about this and I'm not entirely convinced that this
>> > shouldn't be simpler. More like:
>> >
>> > if (DNAT)
>> > DNAT
>> > if (SNAT)
>> > SNAT
>> >
>> > So it always does DNAT before SNAT, similarly to what iptables would
>> > do on PRE/POSTROUTING chains.
>>
>> I can rewrite the whole function, but I wanted to start with the smaller
>> fix that worked. I also think it needs more testing then (since it's
>> something of a rewrite of the function).
>>
>> I guess it's not too important - do you think it gives any readability
>> to do it this way? If so, I can respin the patch changing it like you
>> describe.
>
> I didn't mean a rewrite, but just to never handle SNAT before DNAT. So
> the fix here would be like:
>
> - return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> + if (err == NF_ACCEPT && maniptype == NF_NAT_MANIP_DST &&
> + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
> + maniptype = NF_NAT_MANIP_SRC;
> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> + }
> + return err;

But the maniptype of the first call could be NAT_MANIP_SRC. In fact,
that's what I see if the packet is reply direction && !related.

So, we need the block to invert the manipulation type. Otherwise, we
miss the DNAT manipulation.

So I don't think I can use that block.

>> >> + return err;
>> >> #else
>> >> return NF_ACCEPT;
>> >> #endif
>> >> --
>> >> 2.21.0
>> >>
>>

2019-11-22 20:45:51

by Marcelo Ricardo Leitner

[permalink] [raw]
Subject: Re: [PATCH net 2/2] act_ct: support asymmetric conntrack

On Fri, Nov 22, 2019 at 03:39:16PM -0500, Aaron Conole wrote:
> Marcelo Ricardo Leitner <[email protected]> writes:
>
> > On Mon, Nov 18, 2019 at 04:21:39PM -0500, Aaron Conole wrote:
> >> Marcelo Ricardo Leitner <[email protected]> writes:
> >>
> >> > On Fri, Nov 08, 2019 at 04:07:14PM -0500, Aaron Conole wrote:
> >> >> The act_ct TC module shares a common conntrack and NAT infrastructure
> >> >> exposed via netfilter. It's possible that a packet needs both SNAT and
> >> >> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
> >> >> this because it runs through the NAT table twice - once on ingress and
> >> >> again after egress. The act_ct action doesn't have such capability.
> >> >>
> >> >> Like netfilter hook infrastructure, we should run through NAT twice to
> >> >> keep the symmetry.
> >> >>
> >> >> Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
> >> >>
> >> >> Signed-off-by: Aaron Conole <[email protected]>
> >> >> ---
> >> >> net/sched/act_ct.c | 13 ++++++++++++-
> >> >> 1 file changed, 12 insertions(+), 1 deletion(-)
> >> >>
> >> >> diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c
> >> >> index fcc46025e790..f3232a00970f 100644
> >> >> --- a/net/sched/act_ct.c
> >> >> +++ b/net/sched/act_ct.c
> >> >> @@ -329,6 +329,7 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
> >> >> bool commit)
> >> >> {
> >> >> #if IS_ENABLED(CONFIG_NF_NAT)
> >> >> + int err;
> >> >> enum nf_nat_manip_type maniptype;
> >> >>
> >> >> if (!(ct_action & TCA_CT_ACT_NAT))
> >> >> @@ -359,7 +360,17 @@ static int tcf_ct_act_nat(struct sk_buff *skb,
> >> >> return NF_ACCEPT;
> >> >> }
> >> >>
> >> >> - return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> >> >> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> >> >> + if (err == NF_ACCEPT &&
> >> >> + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
> >> >> + if (maniptype == NF_NAT_MANIP_SRC)
> >> >> + maniptype = NF_NAT_MANIP_DST;
> >> >> + else
> >> >> + maniptype = NF_NAT_MANIP_SRC;
> >> >> +
> >> >> + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> >> >> + }
> >> >
> >> > I keep thinking about this and I'm not entirely convinced that this
> >> > shouldn't be simpler. More like:
> >> >
> >> > if (DNAT)
> >> > DNAT
> >> > if (SNAT)
> >> > SNAT
> >> >
> >> > So it always does DNAT before SNAT, similarly to what iptables would
> >> > do on PRE/POSTROUTING chains.
> >>
> >> I can rewrite the whole function, but I wanted to start with the smaller
> >> fix that worked. I also think it needs more testing then (since it's
> >> something of a rewrite of the function).
> >>
> >> I guess it's not too important - do you think it gives any readability
> >> to do it this way? If so, I can respin the patch changing it like you
> >> describe.
> >
> > I didn't mean a rewrite, but just to never handle SNAT before DNAT. So
> > the fix here would be like:
> >
> > - return ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> > + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> > + if (err == NF_ACCEPT && maniptype == NF_NAT_MANIP_DST &&
> > + ct->status & IPS_SRC_NAT && ct->status & IPS_DST_NAT) {
> > + maniptype = NF_NAT_MANIP_SRC;
> > + err = ct_nat_execute(skb, ct, ctinfo, range, maniptype);
> > + }
> > + return err;
>
> But the maniptype of the first call could be NAT_MANIP_SRC. In fact,
> that's what I see if the packet is reply direction && !related.

Interesting, ok.

>
> So, we need the block to invert the manipulation type. Otherwise, we
> miss the DNAT manipulation.
>
> So I don't think I can use that block.

Thanks for digging on it.

Acked-by: Marcelo Ricardo Leitner <[email protected]>

>
> >> >> + return err;
> >> >> #else
> >> >> return NF_ACCEPT;
> >> >> #endif
> >> >> --
> >> >> 2.21.0
> >> >>
> >>
>

2019-11-25 18:47:44

by Aaron Conole

[permalink] [raw]
Subject: Re: [PATCH net 1/2] openvswitch: support asymmetric conntrack

Aaron Conole <[email protected]> writes:

> Pravin Shelar <[email protected]> writes:
>
>> On Fri, Nov 8, 2019 at 1:07 PM Aaron Conole <[email protected]> wrote:
>>>
>>> The openvswitch module shares a common conntrack and NAT infrastructure
>>> exposed via netfilter. It's possible that a packet needs both SNAT and
>>> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
>>> this because it runs through the NAT table twice - once on ingress and
>>> again after egress. The openvswitch module doesn't have such capability.
>>>
>>> Like netfilter hook infrastructure, we should run through NAT twice to
>>> keep the symmetry.
>>>
>>> Fixes: 05752523e565 ("openvswitch: Interface with NAT.")
>>> Signed-off-by: Aaron Conole <[email protected]>
>>
>> The patch looks ok. But I am not able apply it. can you fix the encoding.
>
> Hrrm. I didn't make any special changes (just used git send-email). I
> will look at spinning a second patch.

Pravin,

I tried the following:

10:36:59 aconole@dhcp-25 {(312434617cb1...)} ~/git/linux$ curl http://patchwork.ozlabs.org/patch/1192219/mbox/ > test.patch
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4827 100 4827 0 0 8824 0 --:--:-- --:--:-- --:--:-- 8808
10:37:21 aconole@dhcp-25 {(312434617cb1...)} ~/git/linux$ git am test.patch
Applying: openvswitch: support asymmetric conntrack
10:37:24 aconole@dhcp-25 {(f759cc2b7323...)} ~/git/linux$


Can you check your mailer settings? The patchwork mbox worked fine, and
I was able to apply from my own mbox as well.

-Aaron

2019-11-26 04:13:06

by Pravin Shelar

[permalink] [raw]
Subject: Re: [PATCH net 1/2] openvswitch: support asymmetric conntrack

Downloading from patchwork is working for me. Its strange other
patches in my mailbox does not has this issue.

Thanks.

On Mon, Nov 25, 2019 at 7:39 AM Aaron Conole <[email protected]> wrote:
>
> Aaron Conole <[email protected]> writes:
>
> > Pravin Shelar <[email protected]> writes:
> >
> >> On Fri, Nov 8, 2019 at 1:07 PM Aaron Conole <[email protected]> wrote:
> >>>
> >>> The openvswitch module shares a common conntrack and NAT infrastructure
> >>> exposed via netfilter. It's possible that a packet needs both SNAT and
> >>> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
> >>> this because it runs through the NAT table twice - once on ingress and
> >>> again after egress. The openvswitch module doesn't have such capability.
> >>>
> >>> Like netfilter hook infrastructure, we should run through NAT twice to
> >>> keep the symmetry.
> >>>
> >>> Fixes: 05752523e565 ("openvswitch: Interface with NAT.")
> >>> Signed-off-by: Aaron Conole <[email protected]>
> >>
> >> The patch looks ok. But I am not able apply it. can you fix the encoding.
> >
> > Hrrm. I didn't make any special changes (just used git send-email). I
> > will look at spinning a second patch.
>
> Pravin,
>
> I tried the following:
>
> 10:36:59 aconole@dhcp-25 {(312434617cb1...)} ~/git/linux$ curl http://patchwork.ozlabs.org/patch/1192219/mbox/ > test.patch
> % Total % Received % Xferd Average Speed Time Time Time Current
> Dload Upload Total Spent Left Speed
> 100 4827 100 4827 0 0 8824 0 --:--:-- --:--:-- --:--:-- 8808
> 10:37:21 aconole@dhcp-25 {(312434617cb1...)} ~/git/linux$ git am test.patch
> Applying: openvswitch: support asymmetric conntrack
> 10:37:24 aconole@dhcp-25 {(f759cc2b7323...)} ~/git/linux$
>
>
> Can you check your mailer settings? The patchwork mbox worked fine, and
> I was able to apply from my own mbox as well.
>
> -Aaron
>

2019-11-28 08:24:59

by Nicolas Dichtel

[permalink] [raw]
Subject: Re: [PATCH net 1/2] openvswitch: support asymmetric conntrack

Le 18/11/2019 à 22:19, Aaron Conole a écrit :
> Nicolas Dichtel <[email protected]> writes:
>
>> Le 08/11/2019 à 22:07, Aaron Conole a écrit :
>>> The openvswitch module shares a common conntrack and NAT infrastructure
>>> exposed via netfilter. It's possible that a packet needs both SNAT and
>>> DNAT manipulation, due to e.g. tuple collision. Netfilter can support
>>> this because it runs through the NAT table twice - once on ingress and
>>> again after egress. The openvswitch module doesn't have such capability.
>>>
>>> Like netfilter hook infrastructure, we should run through NAT twice to
>>> keep the symmetry.
>>>
>>> Fixes: 05752523e565 ("openvswitch: Interface with NAT.")
>>> Signed-off-by: Aaron Conole <[email protected]>
>> In this case, ovs_ct_find_existing() won't be able to find the
>> conntrack, right?
>
> vswitchd normally won't allow both actions to get programmed. Even the
> kernel module won't allow it, so this really will only happen when the
> connection gets established via the nf_hook path, and then needs to be
> processed via openvswitch. In those cases, the tuple lookup should be
> correct, because the nf_nat table should contain the correct tuple data,
> and the skbuff should have the correct tuples in the packet data to
> begin with.
>
>> Inverting the tuple to find the conntrack doesn't work anymore with double NAT.
>> Am I wrong?
>
> I think since the packet was double-NAT on the way out (via nf_hook
> path), then the incoming reply will have the correct NAT tuples and the
> lookup will happen just fine. Just that during processing, both
> transformations aren't applied.
Ok, I didn't look deeply, thank you for the explanation.

Regards,
Nicolas