Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv4: Add interface option to enable routing of 127.0.0.0/8

Routing of 127/8 is tradtionally forbidden, we consider
packets from that address block martian when routing and do
not process corresponding ARP requests.

This is a sane default but renders a huge address space
practically unuseable.

The RFC states that no address within the 127/8 block should
ever appear on any network anywhere but it does not forbid
the use of such addresses outside of the loopback device in
particular. For example to address a pool of virtual guests
behind a load balancer.

This patch adds a new interface option 'route_localnet'
enabling routing of the 127/8 address block and processing
of ARP requests on a specific interface.

Note that for the feature to work, the default local route
covering 127/8 dev lo needs to be removed.

Example:
$ sysctl -w net.ipv4.conf.eth0.route_localnet=1
$ ip route del 127.0.0.0/8 dev lo table local
$ ip addr add 127.1.0.1/16 dev eth0
$ ip route flush cache

V2: Fix invalid check to auto flush cache (thanks davem)

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Thomas Graf and committed by
David S. Miller
d0daebc3 0440507b

+34 -11
+5
Documentation/networking/ip-sysctl.txt
··· 862 862 local interfaces over the wire and have them accepted properly. 863 863 default FALSE 864 864 865 + route_localnet - BOOLEAN 866 + Do not consider loopback addresses as martian source or destination 867 + while routing. This enables the use of 127/8 for local routing purposes. 868 + default FALSE 869 + 865 870 rp_filter - INTEGER 866 871 0 - No source validation. 867 872 1 - Strict mode as defined in RFC3704 Strict Reverse Path
+2
include/linux/inetdevice.h
··· 38 38 IPV4_DEVCONF_ACCEPT_LOCAL, 39 39 IPV4_DEVCONF_SRC_VMARK, 40 40 IPV4_DEVCONF_PROXY_ARP_PVLAN, 41 + IPV4_DEVCONF_ROUTE_LOCALNET, 41 42 __IPV4_DEVCONF_MAX 42 43 }; 43 44 ··· 132 131 #define IN_DEV_PROMOTE_SECONDARIES(in_dev) \ 133 132 IN_DEV_ORCONF((in_dev), \ 134 133 PROMOTE_SECONDARIES) 134 + #define IN_DEV_ROUTE_LOCALNET(in_dev) IN_DEV_ORCONF(in_dev, ROUTE_LOCALNET) 135 135 136 136 #define IN_DEV_RX_REDIRECTS(in_dev) \ 137 137 ((IN_DEV_FORWARD(in_dev) && \
+2 -1
net/ipv4/arp.c
··· 790 790 * Check for bad requests for 127.x.x.x and requests for multicast 791 791 * addresses. If this is one such, delete it. 792 792 */ 793 - if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) 793 + if (ipv4_is_multicast(tip) || 794 + (!IN_DEV_ROUTE_LOCALNET(in_dev) && ipv4_is_loopback(tip))) 794 795 goto out; 795 796 796 797 /*
+4 -1
net/ipv4/devinet.c
··· 1500 1500 1501 1501 if (cnf == net->ipv4.devconf_dflt) 1502 1502 devinet_copy_dflt_conf(net, i); 1503 - if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1) 1503 + if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1 || 1504 + i == IPV4_DEVCONF_ROUTE_LOCALNET - 1) 1504 1505 if ((new_value == 0) && (old_value != 0)) 1505 1506 rt_cache_flush(net, 0); 1506 1507 } ··· 1618 1617 "force_igmp_version"), 1619 1618 DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES, 1620 1619 "promote_secondaries"), 1620 + DEVINET_SYSCTL_FLUSHING_ENTRY(ROUTE_LOCALNET, 1621 + "route_localnet"), 1621 1622 }, 1622 1623 }; 1623 1624
+21 -9
net/ipv4/route.c
··· 1960 1960 return -EINVAL; 1961 1961 1962 1962 if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) || 1963 - ipv4_is_loopback(saddr) || skb->protocol != htons(ETH_P_IP)) 1963 + skb->protocol != htons(ETH_P_IP)) 1964 1964 goto e_inval; 1965 + 1966 + if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev))) 1967 + if (ipv4_is_loopback(saddr)) 1968 + goto e_inval; 1965 1969 1966 1970 if (ipv4_is_zeronet(saddr)) { 1967 1971 if (!ipv4_is_local_multicast(daddr)) ··· 2207 2203 by fib_lookup. 2208 2204 */ 2209 2205 2210 - if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) || 2211 - ipv4_is_loopback(saddr)) 2206 + if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr)) 2212 2207 goto martian_source; 2213 2208 2214 2209 if (ipv4_is_lbcast(daddr) || (saddr == 0 && daddr == 0)) ··· 2219 2216 if (ipv4_is_zeronet(saddr)) 2220 2217 goto martian_source; 2221 2218 2222 - if (ipv4_is_zeronet(daddr) || ipv4_is_loopback(daddr)) 2219 + if (ipv4_is_zeronet(daddr)) 2223 2220 goto martian_destination; 2221 + 2222 + if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev))) { 2223 + if (ipv4_is_loopback(daddr)) 2224 + goto martian_destination; 2225 + 2226 + if (ipv4_is_loopback(saddr)) 2227 + goto martian_source; 2228 + } 2224 2229 2225 2230 /* 2226 2231 * Now we are ready to route packet. ··· 2468 2457 u16 type = res->type; 2469 2458 struct rtable *rth; 2470 2459 2471 - if (ipv4_is_loopback(fl4->saddr) && !(dev_out->flags & IFF_LOOPBACK)) 2460 + in_dev = __in_dev_get_rcu(dev_out); 2461 + if (!in_dev) 2472 2462 return ERR_PTR(-EINVAL); 2463 + 2464 + if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev))) 2465 + if (ipv4_is_loopback(fl4->saddr) && !(dev_out->flags & IFF_LOOPBACK)) 2466 + return ERR_PTR(-EINVAL); 2473 2467 2474 2468 if (ipv4_is_lbcast(fl4->daddr)) 2475 2469 type = RTN_BROADCAST; ··· 2485 2469 2486 2470 if (dev_out->flags & IFF_LOOPBACK) 2487 2471 flags |= RTCF_LOCAL; 2488 - 2489 - in_dev = __in_dev_get_rcu(dev_out); 2490 - if (!in_dev) 2491 - return ERR_PTR(-EINVAL); 2492 2472 2493 2473 if (type == RTN_BROADCAST) { 2494 2474 flags |= RTCF_BROADCAST | RTCF_LOCAL;