Incorrect source IP address on IGMP membership report

4 messages, 2 authors, 2017-12-09 · open the first message on its own page

Incorrect source IP address on IGMP membership report

From: Kevin Cernekee <cernekee@chromium.org>
Date: 2017-12-09 05:26:21

Closing a multicast socket after the final IPv4 address is deleted
from an interface will generate a membership report that uses the
source IP from a different interface.  The following test script, run
from an isolated netns, reproduces the issue:

    #!/bin/bash

    ip link add dummy0 type dummy
    ip link add dummy1 type dummy
    ip link set dummy0 up
    ip link set dummy1 up
    ip addr add 10.1.1.1/24 dev dummy0
    ip addr add 192.168.99.99/24 dev dummy1

    tcpdump -U -i dummy0 -w dummy0.pcap &
    socat EXEC:"sleep 2"
UDP4-DATAGRAM:239.101.1.68:8889,ip-add-membership=239.0.1.68:10.1.1.1
&

    sleep 1
    ip addr del 10.1.1.1/24 dev dummy0
    sleep 5
    kill %tcpdump

After running this script, dummy0.pcap contains one Membership Report
/ Join Group packet with source IP 10.1.1.1, and two Membership Report
/ Leave Group packets with source IP 192.168.99.99.

Sending out multicasts on the LAN using an unexpected source IP
address seems to be causing issues in some enterprise environments[0],
where the network infrastructure is set up to flag suspicious packets.

I believe the source address is provided by ip_route_output_ports()
called from igmpv3_newpack() in the kernel.

Is this behavior intentional?  If not, is it something that we should fix?

I was able to suppress these reports with an iptables OUTPUT rule, but
maybe there is a cleaner way.


[0] https://bugs.chromium.org/p/chromium/issues/detail?id=786514

Re: Incorrect source IP address on IGMP membership report

From: Andrew Lunn <andrew@lunn.ch>
Date: 2017-12-09 16:01:18

On Fri, Dec 08, 2017 at 09:25:58PM -0800, Kevin Cernekee wrote:
Closing a multicast socket after the final IPv4 address is deleted
from an interface will generate a membership report that uses the
source IP from a different interface.  The following test script, run
from an isolated netns, reproduces the issue:

    #!/bin/bash

    ip link add dummy0 type dummy
    ip link add dummy1 type dummy
    ip link set dummy0 up
    ip link set dummy1 up
    ip addr add 10.1.1.1/24 dev dummy0
    ip addr add 192.168.99.99/24 dev dummy1

    tcpdump -U -i dummy0 -w dummy0.pcap &
    socat EXEC:"sleep 2"
UDP4-DATAGRAM:239.101.1.68:8889,ip-add-membership=239.0.1.68:10.1.1.1
&

    sleep 1
    ip addr del 10.1.1.1/24 dev dummy0
    sleep 5
    kill %tcpdump

After running this script, dummy0.pcap contains one Membership Report
/ Join Group packet with source IP 10.1.1.1, and two Membership Report
/ Leave Group packets with source IP 192.168.99.99.

Sending out multicasts on the LAN using an unexpected source IP
address seems to be causing issues in some enterprise environments[0],
where the network infrastructure is set up to flag suspicious packets.

I believe the source address is provided by ip_route_output_ports()
called from igmpv3_newpack() in the kernel.

Is this behavior intentional?  If not, is it something that we should fix?
Hi Kevin

The choice of IP address for IGMP in Linux is 'interesting'.  Try with
multiple IP addresses on the interfaces, addresses with different
scopes, etc.  I've seen it reply to the querier using an address from
a different subnet to the incoming request, etc.

Part of it is an implementation problem. When the application did a
join, it passed an IP address to identify the interface to perform the
join on. That IP address would be an idle choice for IGMP for that
group. However, the information gets discard once the interface has
been determined.

With a single IP address on a single interface, Linux IGMP probably
works. Outside of that, expect oddness.

In your particular case, it is a global scope address. You are allowed
to use it on any interface. So it should not really trigger suspicious
activity. However, the RFC about multicast suggests IGMP with an
unexpected source address should be dropped. However, it is only a
should, not a must, if i remember correctly.

       Andrew

Re: Incorrect source IP address on IGMP membership report

From: Kevin Cernekee <cernekee@chromium.org>
Date: 2017-12-09 20:33:09

On Sat, Dec 9, 2017 at 8:01 AM, Andrew Lunn [off-list ref] wrote:
The choice of IP address for IGMP in Linux is 'interesting'.  Try with
multiple IP addresses on the interfaces, addresses with different
scopes, etc.  I've seen it reply to the querier using an address from
a different subnet to the incoming request, etc.

Part of it is an implementation problem. When the application did a
join, it passed an IP address to identify the interface to perform the
join on. That IP address would be an idle choice for IGMP for that
group. However, the information gets discard once the interface has
been determined.
Right, and even if an address is specified in struct ip_mreqn for an
IP_DROP_MEMBERSHIP call, that address is ignored (at least in my
testing).
With a single IP address on a single interface, Linux IGMP probably
works. Outside of that, expect oddness.

In your particular case, it is a global scope address. You are allowed
to use it on any interface. So it should not really trigger suspicious
activity. However, the RFC about multicast suggests IGMP with an
unexpected source address should be dropped. However, it is only a
should, not a must, if i remember correctly.
Hmm, RFC3376 says:

4.2.13. IP Source Addresses for Reports

   An IGMP report is sent with a valid IP source address for the
   destination subnet.  The 0.0.0.0 source address may be used by a
   system that has not yet acquired an IP address.  Note that the
   0.0.0.0 source address may simultaneously be used by multiple systems
   on a LAN.  Routers MUST accept a report with a source address of
   0.0.0.0.

Would it make sense to add a special case that says "zero out
pip->saddr if the interface doesn't have any IPv4 addresses"?  e.g.
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index d1f8f30..db02779 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -332,6 +332,10 @@ static struct sk_buff *igmpv3_newpack(struct
net_device *dev, unsigned int mtu)
  int hlen = LL_RESERVED_SPACE(dev);
  int tlen = dev->needed_tailroom;
  unsigned int size = mtu;
+ struct in_device *in_dev = __in_dev_get_rcu(dev);
+
+ if (!in_dev)
+     return NULL;

  while (1) {
  skb = alloc_skb(size + hlen + tlen,
@@ -368,7 +372,7 @@ static struct sk_buff *igmpv3_newpack(struct
net_device *dev, unsigned int mtu)
  pip->frag_off = htons(IP_DF);
  pip->ttl      = 1;
  pip->daddr    = fl4.daddr;
- pip->saddr    = fl4.saddr;
+ pip->saddr    = in_dev->ifa_list ? fl4.saddr : INADDR_ANY;
  pip->protocol = IPPROTO_IGMP;
  pip->tot_len  = 0; /* filled in later */
  ip_select_ident(net, skb, NULL);

Re: Incorrect source IP address on IGMP membership report

From: Andrew Lunn <andrew@lunn.ch>
Date: 2017-12-09 22:20:09

Hmm, RFC3376 says:

4.2.13. IP Source Addresses for Reports

   An IGMP report is sent with a valid IP source address for the
   destination subnet.  The 0.0.0.0 source address may be used by a
   system that has not yet acquired an IP address.  Note that the
   0.0.0.0 source address may simultaneously be used by multiple systems
   on a LAN.  Routers MUST accept a report with a source address of
   0.0.0.0.

Would it make sense to add a special case that says "zero out
pip->saddr if the interface doesn't have any IPv4 addresses"?  e.g.
Yes, this looks O.K. for IGMPv3.

     Andrew
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help