Hi, This is the second variant of the patch which addresses the route changes affecting already masqueraded connections. When the route changes (backup default route, VPNs), the packets are sent out with wrong source address. The patch addresses the issue by comparing the outgoing interface directly with the masquerade interface in the nat table. It *is* MASQUERADE specific, so probably the inserted code could be enclosed in a proper ifdef. Events are inefficient, because it'd require scanning the whole conntrack table at any route change and re-checking the route for all entry, which is simply way too expensive. Comments are highly welcomed. Best regards, Jozsef --- net/ipv4/netfilter/iptable_nat.c | 19 +++++++++++++++++++ net/ipv6/netfilter/ip6table_nat.c | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+), 0 deletions(-) diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index ac635a7..128885d 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c @@ -17,6 +17,7 @@ #include <net/netfilter/nf_nat.h> #include <net/netfilter/nf_nat_core.h> #include <net/netfilter/nf_nat_l3proto.h> +#include <net/netfilter/nf_conntrack_ecache.h> static const struct xt_table nf_nat_ipv4_table = { .name = "nat", @@ -134,6 +135,24 @@ nf_nat_ipv4_fn(unsigned int hooknum, /* ESTABLISHED */ NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || ctinfo == IP_CT_ESTABLISHED_REPLY); + if (hooknum == NF_INET_POST_ROUTING && + CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL && + nat->masq_index && nat->masq_index != out->ifindex) { + /* Outgoing interface changed, kill ct. */ + if (del_timer(&ct->timeout)) { + if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) { + nf_ct_delete_from_lists(ct); + nf_ct_insert_dying_list(ct); + nf_ct_put(ct); + return NF_DROP; + } + set_bit(IPS_DYING_BIT, &ct->status); + nf_ct_delete_from_lists(ct); + nf_ct_put(ct); + } + nf_ct_put(ct); + return NF_DROP; + } } return nf_nat_packet(ct, ctinfo, hooknum, skb); diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index fa84cf8..d06d7de 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c @@ -19,6 +19,7 @@ #include <net/netfilter/nf_nat.h> #include <net/netfilter/nf_nat_core.h> #include <net/netfilter/nf_nat_l3proto.h> +#include <net/netfilter/nf_conntrack_ecache.h> static const struct xt_table nf_nat_ipv6_table = { .name = "nat", @@ -137,6 +138,24 @@ nf_nat_ipv6_fn(unsigned int hooknum, /* ESTABLISHED */ NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || ctinfo == IP_CT_ESTABLISHED_REPLY); + if (hooknum == NF_INET_POST_ROUTING && + CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL && + nat->masq_index && nat->masq_index != out->ifindex) { + /* Outgoing interface changed, kill ct. */ + if (del_timer(&ct->timeout)) { + if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) { + nf_ct_delete_from_lists(ct); + nf_ct_insert_dying_list(ct); + nf_ct_put(ct); + return NF_DROP; + } + set_bit(IPS_DYING_BIT, &ct->status); + nf_ct_delete_from_lists(ct); + nf_ct_put(ct); + } + nf_ct_put(ct); + return NF_DROP; + } } return nf_nat_packet(ct, ctinfo, hooknum, skb); -- 1.7.0.4 Best regards, Jozsef - E-mail : kadlec@xxxxxxxxxxxxxxxxx, kadlecsik.jozsef@xxxxxxxxxxxxx PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt Address : Wigner Research Centre for Physics, Hungarian Academy of Sciences H-1525 Budapest 114, POB. 49, Hungary -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html