Commit bc6e14b6 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[NETFILTER]: Fix NAT PMTUD problems

ICMP errors are only SNATed when their source matches the source of the
connection they are related to, otherwise the source address is not
changed. This creates problems with ICMP frag. required messages
originating from a router behind the NAT, if private IPs are used the
packet has a good change of getting dropped on the path to its destination.

Always NAT ICMP errors similar to the original connection.

Based on report by Al Viro.
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 99511014
...@@ -434,6 +434,7 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb, ...@@ -434,6 +434,7 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
} *inside; } *inside;
struct ip_conntrack_tuple inner, target; struct ip_conntrack_tuple inner, target;
int hdrlen = (*pskb)->nh.iph->ihl * 4; int hdrlen = (*pskb)->nh.iph->ihl * 4;
unsigned long statusbit;
if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
return 0; return 0;
...@@ -495,17 +496,16 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb, ...@@ -495,17 +496,16 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
/* Change outer to look the reply to an incoming packet /* Change outer to look the reply to an incoming packet
* (proto 0 means don't invert per-proto part). */ * (proto 0 means don't invert per-proto part). */
if (manip == IP_NAT_MANIP_SRC)
statusbit = IPS_SRC_NAT;
else
statusbit = IPS_DST_NAT;
/* Obviously, we need to NAT destination IP, but source IP /* Invert if this is reply dir. */
should be NAT'ed only if it is from a NAT'd host. if (dir == IP_CT_DIR_REPLY)
statusbit ^= IPS_NAT_MASK;
Explanation: some people use NAT for anonymizing. Also, if (ct->status & statusbit) {
CERT recommends dropping all packets from private IP
addresses (although ICMP errors from internal links with
such addresses are not too uncommon, as Alan Cox points
out) */
if (manip != IP_NAT_MANIP_SRC
|| ((*pskb)->nh.iph->saddr == ct->tuplehash[dir].tuple.src.ip)) {
invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
if (!manip_pkt(0, pskb, 0, &target, manip)) if (!manip_pkt(0, pskb, 0, &target, manip))
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment