Wrong addresses passed to warn_if_extra_mangle() ?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

Since Linux 2.6.11, DNAT of locally generated packets does no implicit source NAT to match the new destination any more.

From ChangeLog-2.6.11 :
  [PATCH] Remove do_extra_mangle: double NAT on LOCAL_OUT

  On NF_IP_LOCAL_OUT, when destination NAT changes the destination
  interface, we also change the source address, so the packet is the
  same as if it were generated to go that way in the first place.  This
  is not strictly necessary, I believe.

  This patch rips that code out to see what breaks.

[One thing that breaks is that now you cannot do things like this any more :

iptables -t nat -A OUTPUT -d 127.x.y.z -j DNAT --to <remote_ip>

because the default source address for a destination in 127.0.0.0/8 is the same as the destination, and the output routing prohibits using such source address to send a packet to a remote destination.

But this is not the subject of this message.]

Consider a host 192.168.0.4/24, a gateway 192.168.0.1/24 with public address 81.56.x.y and HTTP port forwarding to a local server 192.168.0.6/24. When using the following rule on the host :

iptables -t nat -A OUTPUT -d 81.56.x.y -p tcp --dport 80 \
  -j DNAT --to-destination 192.168.0.6

the first time a locally generated packet matches the rule, the kernel prints the following message :

NAT: no longer support implicit source local NAT
NAT: packet src 192.168.0.6 -> dst 81.56.x.y

This message is printed by the function warn_if_extra_mangle(). But the "src" and "dst" addresses look strange. I would expect "src" to be the packet source address (192.168.0.4) instead of the new destination address (192.168.0.6) and "dst" to be the new destination address (192.168.0.6) instead of the original destination address (81.56.x.y). Besides, if I understand correctly, this message should not be printed in this situation because the source address would be the same for both the original and the new destination addresses. Am I correct ?

From net/ipv4/netfilter/ip_nat_rule.c :

/* Before 2.6.11 we did implicit source NAT if required. Warn about change. */
static void warn_if_extra_mangle(u32 dstip, u32 srcip)
{
	static int warned = 0;
	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } };
	struct rtable *rt;

	if (ip_route_output_key(&rt, &fl) != 0)
		return;

	if (rt->rt_src != srcip && !warned) {
		printk("NAT: no longer support implicit source local NAT\n");
		printk("NAT: packet src %u.%u.%u.%u -> dst %u.%u.%u.%u\n",
		       NIPQUAD(srcip), NIPQUAD(dstip))
	warned = 1;
	}
	ip_rt_put(rt);
}

warn_if_extra_mangle() is called in ipt_dnat_target() :

	if (hooknum == NF_IP_LOCAL_OUT
	    && mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
		warn_if_extra_mangle((*pskb)->nh.iph->daddr,
				     mr->range[0].min_ip);


If I understand correctly :
- dstip = (*pskb)->nh.iph->daddr which is the original destination address ;
- srcip = mr->range[0].min_ip which is the new destination address.

However I am not sure whether mr->range[0].min_ip is the actual new destination address or the lower address in the DNAT --to range.

Shouldn't it be rather :
- dstip = the new destination address ;
- srcip = the source address ((*pskb)->nh.iph->saddr ?) ?


[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux