ipv6: Add icmp_echo_ignore_anycast for ICMPv6
authorStephen Suryaputra <ssuryaextr@gmail.com>
Wed, 20 Mar 2019 14:29:27 +0000 (10:29 -0400)
committerDavid S. Miller <davem@davemloft.net>
Wed, 20 Mar 2019 23:29:37 +0000 (16:29 -0700)
In addition to icmp_echo_ignore_multicast, there is a need to also
prevent responding to pings to anycast addresses for security.

Signed-off-by: Stephen Suryaputra <ssuryaextr@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Documentation/networking/ip-sysctl.txt
include/net/netns/ipv6.h
net/ipv6/af_inet6.c
net/ipv6/icmp.c

index 55ea7def46be522e057e911e0eda43ff0e0ec753..bd029fc55ccb047766cac5f10b8f07acac0243c6 100644 (file)
@@ -1923,6 +1923,11 @@ echo_ignore_multicast - BOOLEAN
        requests sent to it over the IPv6 protocol via multicast.
        Default: 0
 
+echo_ignore_anycast - BOOLEAN
+       If set non-zero, then the kernel will ignore all ICMP ECHO
+       requests sent to it over the IPv6 protocol destined to anycast address.
+       Default: 0
+
 xfrm6_gc_thresh - INTEGER
        The threshold at which we will start garbage collecting for IPv6
        destination cache entries.  At twice this value the system will
index e29aff15acc9176873825e2c813c2e50d62212f8..64e29b58bb5e695612b3d216e8934d6c19550b78 100644 (file)
@@ -34,6 +34,7 @@ struct netns_sysctl_ipv6 {
        int icmpv6_time;
        int icmpv6_echo_ignore_all;
        int icmpv6_echo_ignore_multicast;
+       int icmpv6_echo_ignore_anycast;
        int anycast_src_echo_reply;
        int ip_nonlocal_bind;
        int fwmark_reflect;
index fdc117de849cb4fb6700fecafbd661e8c4e5cadd..fa6b404cbd104f5170e0b7002769491402d10b13 100644 (file)
@@ -848,6 +848,7 @@ static int __net_init inet6_net_init(struct net *net)
        net->ipv6.sysctl.icmpv6_time = 1*HZ;
        net->ipv6.sysctl.icmpv6_echo_ignore_all = 0;
        net->ipv6.sysctl.icmpv6_echo_ignore_multicast = 0;
+       net->ipv6.sysctl.icmpv6_echo_ignore_anycast = 0;
        net->ipv6.sysctl.flowlabel_consistency = 1;
        net->ipv6.sysctl.auto_flowlabels = IP6_DEFAULT_AUTO_FLOW_LABELS;
        net->ipv6.sysctl.idgen_retries = 3;
index 0907bcede5e5ef603623043d38a41c25a67610ad..cc14b99989415e0075c1269b396ac55aed356507 100644 (file)
@@ -683,6 +683,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        struct dst_entry *dst;
        struct ipcm6_cookie ipc6;
        u32 mark = IP6_REPLY_MARK(net, skb->mark);
+       bool acast;
 
        if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) &&
            net->ipv6.sysctl.icmpv6_echo_ignore_multicast)
@@ -690,9 +691,12 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 
        saddr = &ipv6_hdr(skb)->daddr;
 
+       acast = ipv6_anycast_destination(skb_dst(skb), saddr);
+       if (acast && net->ipv6.sysctl.icmpv6_echo_ignore_anycast)
+               return;
+
        if (!ipv6_unicast_destination(skb) &&
-           !(net->ipv6.sysctl.anycast_src_echo_reply &&
-             ipv6_anycast_destination(skb_dst(skb), saddr)))
+           !(net->ipv6.sysctl.anycast_src_echo_reply && acast))
                saddr = NULL;
 
        memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
@@ -1126,6 +1130,13 @@ static struct ctl_table ipv6_icmp_table_template[] = {
                .mode           = 0644,
                .proc_handler = proc_dointvec,
        },
+       {
+               .procname       = "echo_ignore_anycast",
+               .data           = &init_net.ipv6.sysctl.icmpv6_echo_ignore_anycast,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler = proc_dointvec,
+       },
        { },
 };
 
@@ -1141,6 +1152,7 @@ struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net)
                table[0].data = &net->ipv6.sysctl.icmpv6_time;
                table[1].data = &net->ipv6.sysctl.icmpv6_echo_ignore_all;
                table[2].data = &net->ipv6.sysctl.icmpv6_echo_ignore_multicast;
+               table[3].data = &net->ipv6.sysctl.icmpv6_echo_ignore_anycast;
        }
        return table;
 }