Capturing multicast data with Wireshark with IGMP Snooping Enabled at the switch
I am trying to capture multicast traffic via Wireshark (actually TShark), however the switch has IGMP snooping enabled and will only send Multicast traffic on the ports that have an active IGMP subscription.
I am currently getting around this by having a separate application hold the groups open I wish to record, but I am trying to set up a system to start/stop recording data dynamically and this extra complexity is painful.
Is there a way to force Wireshark to send out IGMP Subscriptions for multicast groups it is recording?
You can use "ip maddr add" to subscribe to additional groups. That should cause the kernel to respond to IGMP queries and receive traffic for them.
Presumably by "multicast groups it is recording" you mean that you've specified a capture filter asking for particular multicast destination addresses in a "host" keyword; that's the only way Wireshark could limit its packet capture to particular multicast groups.
Wireshark has no mechanism by which it sends out IGMP subscriptions based on the capture filter; it assumes that you have somehow arranged to have all relevant packets sent to the port on which it's capturing, for example by port mirroring/SPAN/whatever your switch vendor calls it on that port, so that the switch sends all packets to that port. If you can't set up port mirroring, or if that will send too many packets to the port on which you're capturing, you'll have to subscribe that port to the appropriate multicast group (as you appear to be doing already).
Create a custom lua listener and call it from wireshark.
Here is a well documented example:
-- This program will register a menu that will open a window with a count of occurrences
-- of every address in the capture
local function menuable_tap()
-- Declare the window we will use
local tw = TextWindow.new("Address Counter")
-- This will contain a hash of counters of appearances of a certain address
local ips = {}
-- this is our tap
local tap = Listener.new();
local function remove()
-- this way we remove the listener that otherwise will remain running indefinitely
tap:remove();
end
-- we tell the window to call the remove() function when closed
tw:set_atclose(remove)
-- this function will be called once for each packet
function tap.packet(pinfo,tvb)
local src = ips[tostring(pinfo.src)] or 0
local dst = ips[tostring(pinfo.dst)] or 0
ips[tostring(pinfo.src)] = src + 1
ips[tostring(pinfo.dst)] = dst + 1
end
-- this function will be called once every few seconds to update our window
function tap.draw(t)
tw:clear()
for ip,num in pairs(ips) do
tw:append(ip .. "\t" .. num .. "\n");
end
end
-- this function will be called whenever a reset is needed
-- e.g. when reloading the capture file
function tap.reset()
tw:clear()
ips = {}
end
-- Ensure that all existing packets are processed.
retap_packets()
end
-- using this function we register our function
-- to be called when the user selects the Tools->Test->Packets menu
register_menu("Test/Packets", menuable_tap, MENU_TOOLS_UNSORTED)