Netgate Discussion Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search
    • Register
    • Login

    IGMP issues causing ISP to perform multicast DOS on my pfSense

    Routing and Multi WAN
    3
    7
    7.2k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • V
      v3gard
      last edited by

      Hi guys

      I am using my pfSense FW as a WAN router/firewall and also as an IGMP proxy server for controlling IPTV multicast streams from my ISP.

      I have set up my pfSense firewall as the IGMP proxy, but I think I have screwed up the configuration somewhere. I've managed to get the IGMP messages flowing to a certain degree. I can switch channels on my IPTV tuner and get the multicast streams streaming - but for some reason I suspect the "IGMP leave reports" aren't returned properly back to my ISP. The result, as you can imagine, is that my ISP is bombarding me with X multicast streams causing the load of my pfSense to hit the roof and become unstable. This usually happens when 9-10 streams are active simultanously and the multicast bandwidth usage from my ISP to the pfsense FW exceeds 90MBit/s.

      The only way I work around this issue at the moment is to disconnect power from the fiber/ethernet converter between my pfSense and the ISP.

      My IPTV tuner is on a separate LAN named TVLAN and directly connected to my pfSense FW. My other computers are behind another router which WAN port is connected to one of the ports in the pfSense FW. I have added a diagram of my network topology to clarify any misunderstandings.

      I am positive that this is not related to the firewall rules since I can verify with tcpdump that there are indeed IGMP messages going on both vr0 (WAN) and vr1 (TVLAN). No IGMP packages are sent to vr2 (LAN).

      Here are my igmpproxy settings:

      
      ##------------------------------------------------------
      ## Enable Quickleave mode (Sends Leave instantly)
      ##------------------------------------------------------
      quickleave
      phyint vr0 upstream ratelimit 0 threshold 2
      altnet 148.122.7.125/24
      altnet 93.91.111.0/24
      
      phyint vr1 downstream ratelimit 0 threshold 2
      altnet 10.10.0.0/24
      
      phyint vr2 disabled
      
      

      To further clarify, my WAN interface is vr0, my TVLAN interface is vr1 and LAN is vr2.

      Here is example output from tcpdump showing IGMP packets on vr0 (the WAN interface). As seen, IGMP packets are sent from pfSense to my ISP.

      [2.1-RELEASE][root@morannon.me.lan]/root(36): tcpdump -ivr0 igmp
      tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
      listening on vr0, link-type EN10MB (Ethernet), capture size 96 bytes
      18:42:27.891721 IP 148.122.7.125 > all-systems.mcast.net: igmp query v2
      18:43:15.315588 IP ti0140a400-1922.bb.online.no > igmp.mcast.net: igmp v3 report, 1 group record(s)
      18:43:15.316639 IP ti0140a400-1922.bb.online.no > 233.171.129.255: igmp v2 report 233.171.129.255
      18:43:19.418903 IP ti0140a400-1922.bb.online.no > igmp.mcast.net: igmp v3 report, 1 group record(s)
      18:43:19.419725 IP ti0140a400-1922.bb.online.no > 233.171.129.217: igmp v2 report 233.171.129.217
      18:43:48.795802 IP ti0140a400-1922.bb.online.no > 224.0.39.17: igmp v2 report 224.0.39.17
      18:43:48.797620 IP ti0140a400-1922.bb.online.no > igmp.mcast.net: igmp v3 report, 1 group record(s)
      18:43:53.638593 IP ti0140a400-1922.bb.online.no > igmp.mcast.net: igmp v3 report, 1 group record(s)
      18:43:53.639964 IP ti0140a400-1922.bb.online.no > 224.0.39.17: igmp v2 report 224.0.39.17
      ^C
      9 packets captured
      196448 packets received by filter
      0 packets dropped by kernel
      
      

      And here are the IGMP packets from vr1 (TVLAN) in the same time period as the dump above. The IPTV tuner sends the packets to the igmpproxy server running on the pfSense FW. I have changed the channel on the IPTV tuner during the dump and also returned to the original channel.

      [2.1-RELEASE][root@morannon.me.lan]/root(1): tcpdump -ivr1 igmp
      tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
      listening on vr1, link-type EN10MB (Ethernet), capture size 96 bytes
      18:43:14.912876 IP morannon.me.lan > all-systems.mcast.net: igmp query v2
      18:43:14.915432 IP morannon.me.lan > all-systems.mcast.net: igmp query v3
      18:43:15.311056 IP 10.10.0.200 > 233.171.129.255: igmp v2 report 233.171.129.255
      18:43:16.962510 IP morannon.me.lan > all-routers.mcast.net: igmp v2 report all-routers.mcast.net
      18:43:19.415822 IP 10.10.0.200 > 233.171.129.217: igmp v2 report 233.171.129.217
      18:43:48.618457 IP 10.10.0.200 > all-routers.mcast.net: igmp leave 233.171.129.217
      18:43:48.620029 IP morannon.me.lan > 233.171.129.217: igmp query v2 [gaddr 233.171.129.217]
      18:43:48.621219 IP morannon.me.lan > all-systems.mcast.net: igmp query v3 [gaddr 233.171.129.217]
      18:43:48.622795 IP morannon.me.lan > 233.171.129.217: igmp query v2 [gaddr 233.171.129.217]
      18:43:48.623429 IP morannon.me.lan > all-systems.mcast.net: igmp query v3 [gaddr 233.171.129.217]
      18:43:48.793386 IP 10.10.0.200 > 224.0.39.17: igmp v2 report 224.0.39.17
      18:43:53.634198 IP 10.10.0.200 > 224.0.39.17: igmp v2 report 224.0.39.17
      ^C
      12 packets captured
      69587 packets received by filter
      0 packets dropped by kernel
      
      

      One thing I notice is that when the IPTV tuner sends IGMP leave message to the igmpproxy at the pfSense FW, the igmpproxy doesn't just forward the IGMP leave message. Instead it sends it as an "igmp v3 report" with 1 group record. Could it be that my ISP does not support this?

      Here is an example:

      
      TUNER to FW - 18:43:48.618457 IP 10.10.0.200 > all-routers.mcast.net: igmp leave 233.171.129.217
      FW to ISP   - 18:43:48.797620 IP ti0140a400-1922.bb.online.no > igmp.mcast.net: igmp v3 report, 1 group record(s)
      
      

      Thanks for reading!

      edit: some further clarifications and fix of spelling errors.

      1 Reply Last reply Reply Quote 0
      • V
        v3gard
        last edited by

        Update.

        Spent a couple of hours this weekend trying to forge IGMPv2 packets using nmap/nping and wrote the following script that generates an IGMPv2 leave report. Using nmap, I sent the packet from my FW towards my ISP. By the way, 233.171.129.255 is the destination address of one of the multicast streams that I was trying to stop.

        local nmap = require "nmap"
        local stdnse = require "stdnse"
        local io = require "io"
        local bin = require "bin"
        local packet = require "packet"
        local ipOps = require "ipOps"
        
        prerule = function()
            if nmap.address_family() ~= 'inet' then
            stdnse.print_verbose("s is IPv3 only.", SCRIPT_NAME)
            return false
            end
            if ( not(nmap.is_privileged()) ) then
            stdnse.print_verbose("%s not running due to lack of privileges.", SCRIPT_NAME)
            return false
            end
            return true
        end
        
        local igmpLeave;
        --- Sends an IGMP leave report
        igmpLeave = function(interface, version, ipAddress)
            local igmpPacket = bin.pack(">C", 0x17) -- Leave group query
            stdnse.print_debug("%s: Creating IGMP leave packet...", SCRIPT_NAME)
            igmpPacket = igmpPacket .. bin.pack(">C", 0x00) -- Max response time: 0 seconds
            igmpPacket = igmpPacket .. bin.pack(">S", 0x00) -- Checksum. Calculated later.
            --igmpPacket = igmpPacket .. bin.pack(">I", 0xe1010104) -- 225.1.1.4
            igmpPacket = igmpPacket .. bin.pack(">I", ipOps.todword(ipAddress))
            -- 224.0.39.84       3758106452      E0002754
            -- 233.171.129.255   3920331263      E9AB81FF
            -- 233.171.129.75    3920331083      E9AB814B
            igmpPacket = igmpPacket:sub(1,2) .. bin.pack(">S", packet.in_cksum(igmpPacket)) .. igmpPacket:sub(5)
            stdnse.print_debug("%s: Packet created!", SCRIPT_NAME)
            return igmpPacket
        end
        
        action = function(host, port)
            --- START
            stdnse.print_debug("--- START ---")
            local version = stdnse.get_script_args(SCRIPT_NAME .. ".version") or 2
            local leaveMe = stdnse.get_script_args(SCRIPT_NAME .. ".ip") or "233.171.129.255"
            local interface = nmap.get_interface()
            local responses, results = {}, {}
            local result
            if interface==nil then
                return ("ERROR: Failed to retrieve interface information.")
            end
            interface = nmap.get_interface_info(interface)
            local srcip = interface.address
            local dstip = "224.0.0.2"
            --local dstip = "233.171.129.255"
            stdnse.print_debug("%s: Will use %s interface.", SCRIPT_NAME, interface)
            stdnse.print_debug("%s: Will use IGMP version %s.", SCRIPT_NAME, version)
            -- if we want to listen for results:
            --   local co = stdnse.new_thread(igmpListener, interface, timeout, responses)
            local igmp_leave = igmpLeave(interface, version, leaveMe)
            local ip_raw = bin.pack("H", "45c00040ed780000010218bc0a00c8750a00c86b") .. igmp_leave
            local igmp_packet = packet.Packet:new(ip_raw, ip_raw:len())
            igmp_packet:ip_set_bin_src(ipOps.ip_to_str(srcip))
            igmp_packet:ip_set_bin_dst(ipOps.ip_to_str(dstip))
            igmp_packet:ip_set_len(#igmp_packet.buf)
            igmp_packet:ip_count_checksum()
        
            local sock = nmap.new_dnet()
            sock:ethernet_open(interface.device)
              local eth_hdr = bin.pack("HAH", "01 00 5e 00 00 01", interface.mac, "08 00")
              sock:ethernet_send(eth_hdr .. igmp_packet.buf)
            sock:ethernet_close()
            stdnse.print_debug("%s: Packet sent!.", SCRIPT_NAME)
        
            stdnse.print_debug("--- STOP  ---")
            --- STOP
        end
        
        

        To send the packets I installed nmap on my pfSense FW and ran the following command:

        nmap -e vr0 -d --script igmpLeave.nse
        

        If I listen on the vr0 interface while I run this command, the following entry appears:

        [2.1-RELEASE][root@morannon.me.lan]/root(1): tcpdump -ivr0 igmp
        tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
        listening on vr0, link-type EN10MB (Ethernet), capture size 96 bytes
        08:05:05.058830 IP ti0140a400-1922.bb.online.no > all-routers.mcast.net: igmp leave 233.171.129.255
        
        

        As the above output confirms, the packet was sent on the interface, but this did not close the multicast stream either..! I think I need to study the IGMP protocol more to fully understand this..

        1 Reply Last reply Reply Quote 0
        • H
          haavardg
          last edited by

          v3gard, where you able to resolve this issue? I currently have the same issue with the same ISP (Telenor).

          1 Reply Last reply Reply Quote 0
          • V
            v3gard
            last edited by

            @haavardg:

            v3gard, where you able to resolve this issue?

            Yes I did, but not with pfSense unfortunately. I ended up using a MikroTik router that used IGMPv2 natively, with the same configuration as I posted earlier for my old pfSense unit. I am certain that you can get this to work with pfSense also once you figure out the IGMPv2/IGMPv3 issues, but I had to make priorities as my time was required elsewhere.

            1 Reply Last reply Reply Quote 0
            • W
              wenga
              last edited by

              Sorry for digging this out again, but right now I have the same issue as mentioned by v3gard with pfSense2.2

              @v3gard: Are you still using MikroTik or have you tried it with pfSense again? Let me guess, you've asked on the ISP's forums already, because I saw someone posting there about this problem (after reading a guide of tuxone  ;))

              Is someone else in the community having the same issue or maybe a possible solution? Could this be a bug in pfSense itself?

              1 Reply Last reply Reply Quote 0
              • V
                v3gard
                last edited by

                @wenga:

                @v3gard: Are you still using MikroTik or have you tried it with pfSense again?

                Still using MikroTik. Works like a charm!
                @wenga:

                Let me guess, you've asked on the ISP's forums already, because I saw someone posting there about this problem (after reading a guide of tuxone  ;))

                Nope, not me (I think).I don't think this is an ISP issue as my ISP has standardized on IGMPv2. The problem is that I couldn't get IGMPv3 (which was installed on pfSense) to work seamless with IGMPv2. My main problem was that the active streams never disconnected.
                @wenga:

                Could this be a bug in pfSense itself?

                I assume you can solve the problem if you manage to compile a version of the igmp tools where you force IGMPv2 - but I haven't tried it myself.

                1 Reply Last reply Reply Quote 0
                • W
                  wenga
                  last edited by

                  @v3gard:

                  Nope, not me (I think).I don't think this is an ISP issue as my ISP has standardized on IGMPv2. The problem is that I couldn't get IGMPv3 (which was installed on pfSense) to work seamless with IGMPv2. My main problem was that the active streams never disconnected.

                  Oh, I thought you were that user, since you also switched to MikroTik. But based on your tcpdumps you are on a different ISP. I'm currently on Swisscom.

                  @v3gard:

                  I assume you can solve the problem if you manage to compile a version of the igmp tools where you force IGMPv2 - but I haven't tried it myself.

                  I'm not sure if this is going to help. I configured FreeBSD now that it should use only v2 as default. Additionally I set the force_igmp_version in sysctl to "2". I have read somewhere, that igmpproxy uses v2 as default for downstreams. For upstreams it uses the version configured in the kernel igmp-module of the FreeBSD.

                  This didn't really help for now. But based on your description, my problem might be a different one. At least the symptoms are different. As soon as I configure an upstream IGMP proxy to my ISP, my ISP router is restarting itself. This happens over and over again, as long as the upstream is active.

                  Looking at the tcpdump didn't help at all. I just see that there are two IGMPv2 and IGMPv3 packets, both seem to be okay. After that the ISP router is gone (about 10 seconds after).

                  Does anyone have any idea how I can solve this problem?

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post
                  Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.