Commit a0ecb85a2c3af73c63b6d44ce82aea52347ccf55

Authored by Jozsef Kadlecsik
Committed by Pablo Neira Ayuso
1 parent 6d1fafcaec

netfilter: nf_nat: Handle routing changes in MASQUERADE target

When the route changes (backup default route, VPNs) which affect a
masqueraded target, the packets were sent out with the outdated source
address. The patch addresses the issue by comparing the outgoing interface
directly with the masqueraded interface in the nat table.

Events are inefficient in this case, because it'd require adding route
events to the network core and then scanning the whole conntrack table
and re-checking the route for all entry.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Showing 3 changed files with 23 additions and 0 deletions Side-by-side Diff

include/net/netfilter/nf_nat.h
... ... @@ -68,5 +68,20 @@
68 68 #endif
69 69 }
70 70  
  71 +static inline bool nf_nat_oif_changed(unsigned int hooknum,
  72 + enum ip_conntrack_info ctinfo,
  73 + struct nf_conn_nat *nat,
  74 + const struct net_device *out)
  75 +{
  76 +#if IS_ENABLED(CONFIG_IP_NF_TARGET_MASQUERADE) || \
  77 + IS_ENABLED(CONFIG_IP6_NF_TARGET_MASQUERADE)
  78 + return nat->masq_index && hooknum == NF_INET_POST_ROUTING &&
  79 + CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL &&
  80 + nat->masq_index != out->ifindex;
  81 +#else
  82 + return false;
  83 +#endif
  84 +}
  85 +
71 86 #endif
net/ipv4/netfilter/iptable_nat.c
... ... @@ -134,6 +134,10 @@
134 134 /* ESTABLISHED */
135 135 NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
136 136 ctinfo == IP_CT_ESTABLISHED_REPLY);
  137 + if (nf_nat_oif_changed(hooknum, ctinfo, nat, out)) {
  138 + nf_ct_kill_acct(ct, ctinfo, skb);
  139 + return NF_DROP;
  140 + }
137 141 }
138 142  
139 143 return nf_nat_packet(ct, ctinfo, hooknum, skb);
net/ipv6/netfilter/ip6table_nat.c
... ... @@ -137,6 +137,10 @@
137 137 /* ESTABLISHED */
138 138 NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
139 139 ctinfo == IP_CT_ESTABLISHED_REPLY);
  140 + if (nf_nat_oif_changed(hooknum, ctinfo, nat, out)) {
  141 + nf_ct_kill_acct(ct, ctinfo, skb);
  142 + return NF_DROP;
  143 + }
140 144 }
141 145  
142 146 return nf_nat_packet(ct, ctinfo, hooknum, skb);