Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IPNEIGH plugin for IPv4/6 discovery using the ip neigh command #896

Merged
merged 4 commits into from
Nov 28, 2024

Conversation

KayJay7
Copy link
Contributor

@KayJay7 KayJay7 commented Nov 26, 2024

What it is

IPNEIGH is a new device discovery plugin that uses the ip neigh command to read from both the ARP and NDP table.

The main objective of this plugin is to allow for discovery of IPv6 devices which use NDP for address resolution, and aren't detectable by ARPSCAN.

How it works

The plugin is extremely simple. First it runs a ping on multicast address ff02::1 which is directed at every IPv6 device from the local network, this causes the network stack to send NDP solicitation requests and populates the NDP table. Note that every device will answer with only one of its addresses, so only those addresses will appear in the table, unless discovered by normal operation.
Then using the ip neigh command it retrieves every neighbouring IP, both v4 and v6, and adds them to the database. It will not discover names or vendors though.

Those tables often contains various multicast addresses that are not real devices. This plugin filters them out and doesn't add them to the database

Note

This does not replace ARPSCAN, because it doesn't actively sends ARP requests, so by itself it might miss some IPv4 device. If you have both, realistically IPNEIGH will never find an IPv4 device that ARPSCAN didn't, unless for some network timing oddity. I could have limited it to IPv6 devices, as it didn't add anything to IPv4 scanning, but there was no reason to.
If someone added ARP requests it would make ARPSCAN unnecessary.

@KayJay7
Copy link
Contributor Author

KayJay7 commented Nov 26, 2024

Also I want to point out a minor difficulty I had during development. I tried using the function handleEmpty to handle the empty columns that this plugin doesn't manage (e.g. hostnames) expecting it to be the correct way of doing so.

That function set the empty values in the database to the string "null" while the system expects unknown values to be the string "(unknown)", and because of that plugins like AVAHISCAN did not count the hostnames as unknown and didn't even try to resolve their name.

I haven't changed the function to return "(unknown)" in case something else depends on the "null" value, but I thing it should, because right now it's quite misleading. Or if there really is an use for the current handleEmpty, than a function handleUnknown would be useful.

@jokob-sk
Copy link
Owner

Thanks a lot for the PR 🎉🙌 - a question - why did you choose this approach instead of using the global subnets setting?

To set up the plugin correctly, make sure to add in the plugin settings the name of the interfaces you want to scan. This plugin doesn't use the global SCAN_SUBNET setting, this is because by design it is not aware of subnets, it just looks at all the IPs reachable from an interface.

If we proceed with this approach, please specify example values in the settings description - users don't often know the format.

One of the main reasons I keep this setting global is to simplify setup, so having a separate subnets configuration for the plugin defeats the purpose. I do understand it comes with more flexibility - maybe in future I'd implement inheriting and overriding settings.

@KayJay7
Copy link
Contributor Author

KayJay7 commented Nov 27, 2024

Thanks a lot for the PR 🎉🙌 - a question - why did you choose this approach instead of using the global subnets setting?

The problem is the way the setting is done: it's formatted like the arguments of a program (like the other scanning utilities (the arp-scan and nmap commands). ip neigh doesn't use the same syntax so it's not guaranteed I can extract the individual fields from the field anyway.

@jokob-sk
Copy link
Owner

hmmm, I can accept the PR if you give me an example of valid inputs - I'd still myself rewrite the plugin to use the global setting at this point, but I can do it myself.

@KayJay7
Copy link
Contributor Author

KayJay7 commented Nov 27, 2024

You mean regex the field? I'm not sure, it's a fragment of the args of totally different commands. It's heavily tailored for the arp-scan-like commands. It might be a dangerous assumption to parse out the values from there.

Moreover, the subnet is currently ignored.. It could be used for IPv4s returned by the plugin, but it would be weird to do that for v4, and not v6. IPv6 adresses of devices in a network can be of two kinds: public and link-local. In case of subnetting a IPv6 subnet field would be required for both. The current implementation of the cli args does not allow this.

I've still to push a fix for the online detection feature, which was incorrectly handled from the command output.

@KayJay7
Copy link
Contributor Author

KayJay7 commented Nov 28, 2024

Okay, that's the fix. I have also added the default value eth0 to match the default value of the global setting, and provided an example with more interfaces in the plugin's README (eth0,wl1,tap0).

@jokob-sk
Copy link
Owner

Thank you! Will look at the regex approach and merge it probably over the weekend

@jokob-sk jokob-sk changed the base branch from main to feature/IPNEIGH November 28, 2024 21:03
@jokob-sk jokob-sk merged commit 148eb5a into jokob-sk:feature/IPNEIGH Nov 28, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants