nmap / npcap

Nmap Project's Windows packet capture and transmission library
https://npcap.com
Other
3.03k stars 519 forks source link

Is calling pcap_parsesrcstr() before pcap_create() necessary for pcap_activate() to work properly? #255

Closed matman13 closed 2 years ago

matman13 commented 4 years ago

I'm updating our code from WinPcap 4.1.3 to Npcap 1.0, and I'm trying to do things in accordance with how they should be done in Npcap. What follows is a question about whether I'm doing this correctly and then asking about the possibility of an enhancement to the Npcap API. Nothing, as far as I can tell, appears to be broken.

Our WinPcap 4.1.3 initialization code was simple:

pcap_open(...);
pcap_setbuff(...);

My understanding is that pcap_setbuff() is the WinPcap mechanism (although it'll still works within Npcap) but that Npcap code should prefer pcap_set_buffer_size(). The problem is that I cannot do this:

pcap_open(...);
pcap_set_buffer_size(...);

The reason why is that pcap_open() activates the device handle, and pcap_set_buffer_size() cannot be called after activation has occurred. Fine. So again, trying to play correctly with Npcap, I changed things to the following:

pcap_create(...);
pcap_set_snaplen(...);
pcap_set_promisc(...);
pcap_set_timeout(...);
pcap_set_buffer_size(...);
pcap_activate(...);

And this works great until I get to pcap_activate(), which is where I get a "device does not exist" error. I've tracked this down to the fact that the source parameter to pcap_open() is not the same thing as the device parameter to pcap_create(). In order to make things work, I have to call pcap_parsesrctr() before calling pcap_create(). So...

  1. Is this approach the recommended way of initializing the device in Npcap, i.e., am I doing things correctly?

  2. Assuming I am doing things correctly, can pcap_create() include a call to pcap_parsesrcstr() to make this more streamlined? Or is there a way I can get the device parameter through what is returned from pcap_findalldevs_ex()? I'm currently using the name provided by the _pcapif selected from pcap_findalldevs_ex() and having to call pcap_parsesrcstr() on that.

guyharris commented 4 years ago

If you are only capturing on local interfaces, not on remote interfaces, you do not need to use pcap_open(). You can use pcap_create(), pcap_activate(), and other calls between them to open a local interface.

If you want to read a capture file, you can use pcap_open_offline() rather than pcap_open().

If you want to open a remote interface, you currently must use pcap_open().

pcap_create() does not take a URL as an argument. If you want to open a local interface using a URL, rather than an interface name, you must use pcap_parsesrcstr() to 1) make sure it's a URL for a local interface and 2) get the interface name.

pcap_findalldevs_ex() returns URL strings, so if you are using pcap_findalldevs_ex(), you must use pcap_parsesrcstr()`.

If you only want to capture on local interfaces, you can use pcap_findalldevs() to find all local interfaces, and can use pcap_create() and pcap_activate() (and other calls between those two calls) to open the interface.

matman13 commented 2 years ago

Sorry for not thanking you before. It is MUCH appreciated.

guyharris commented 2 years ago

pcap_create() does not take a URL as an argument.

This is not an intended feature; at some point I'd like to add to libpcap the ability to use the create/activate API to open remote interfaces as well. There are some other changes that need to be made first (to allow a given libpcap module to specify parameters the module supports; this would be useful for remote capture, so it can have a "use UDP" option, but could also be useful for certain local devices).

matman13 commented 2 years ago

We've never had a need for remote capture. Just not sure how that fits into our current problem space. Does npcap support that?

And while I'm here, not sure if you're still on StackOverflow or not, but I asked this question earlier today. Would love your input. https://stackoverflow.com/questions/72999469/using-npcap-for-collection-and-statistics

guyharris commented 2 years ago

We've never had a need for remote capture. Just not sure how that fits into our current problem space. Does npcap support that?

The remote capture stuff originally appeared in WinPcap; I put it into libpcap to make it available on all platforms (and cleaned it up after testing it between a pile of platforms - it worked out of the box on most, but needed a little tweaking to use the same over-the-wire format for the "get a list of interfaces and their addresses" response on Solaris that it uses on other platforms).

It's not built by default on UNXes (due to nervousness about possible security issues - I also did a security audit and fixed the issues I found), but it is* built by default on Windows, so that it shows up by default in Npcap (for compatibility with WinPcap).

However, it also needs a server to be running on the machine to which the interfaces on which you want to capture are attached. WinPcap shipped with the daemon (rpcapd), but I don't think Npcap does, and, to capture from interfaces on a UN*X box, you'd have to compile the daemon and install it.

And while I'm here, not sure if you're still on StackOverflow or not, but I asked this question earlier today. Would love your input.

I'll give a look at some point.

matman13 commented 2 years ago

it also needs a server to be running on the machine to which the interfaces on which you want to capture are attached.

That helps a lot. I was trying to figure out in my head how this worked.

With that understanding, I'll take back my earlier statement about not needing this functionality. An earlier version of our software captured data using WinPcap in a Windows service, bundled that information, and sent it to a remote system for processing. We used TCP/IP at the time, but I'm considering how we might leverage some kind of reliable multicast to improve bandwidth. Any hints on maybe where to focus our efforts in this regard? How do the packets captured on the remote system using WinPcap/libpcap get to the local system for monitoring? Are those packets just bundled and sent over TCP/IP, i.e., the captured packets become the payload (application layer) of a TCP connection?

BTW, really appreciate your feedback, especially this late on a Friday afternoon. If we don't talk again today, have a great weekend.

guyharris commented 2 years ago

How do the packets captured on the remote system using WinPcap/libpcap get to the local system for monitoring? Are those packets just bundled and sent over TCP/IP, i.e., the captured packets become the payload (application layer) of a TCP connection?

For rpcap, yes; there's a TCP control connection and, by default, a TCP data connection over which the packets are sent. UDP can also be used for the data connection.

The 1.10 code (which is what Npcap is currently using) includes TLS support for the TCP connections, but it currently requires OpenSSL or a compatible library, and Npcap isn't built with (and bundled with) such a library. (I'd like to have it support Windows native TLS, and possibly macOS native TLS - Apple stopped shipping headers for OpenSSL with Xcode a while ago, so macOS couldn't ship with TLS support if they decided to ship with remote capture support.)

If you want multiple hosts to be able to process the same capture, reliable multicast might work; if there's only one client, I don't see it helping. Multicast also means that different clients don't get to tap in with different options such as filter and snapshot length.