the-tcpdump-group / libpcap

the LIBpcap interface to various kernel packet capture mechanism
https://www.tcpdump.org/
Other
2.72k stars 854 forks source link

go RPCAP protocol implementation comparison with the source code here? #1298

Closed daluu closed 3 months ago

daluu commented 8 months ago

I came across a go implementation of the RPCAP protocol: https://pkg.go.dev/github.com/kor44/rpcap.

It's more like a specification and doesn't yet have any example rpcapd or rpcap client implementations using that go-based protocol implementation.

While this is not a feature request or bug filed, thought I'd mention this for review by anyone here and the community. It's the first of its kind I think that is independent of libpcap sources in C. Would be an interesting way to interface to actual packet capture on remote host the capture is run on, but where the actual rpcap protocol exchange doesn't have to stay with/in libpcap code, for 3rd party implementations.

For this post, I'm just curious how accurate that protocol implementation is translating from the rpcap related libpcap APIs to a go-centric interface. I don't know the historical context, it might be based on the older source from Winpcap, and the source here might have deviated a bit since or not.

In any case, pointing out any errors or improvements to the protocol implementation there could be beneficial to the community.

Maybe this could be the start of defining the RPCAP protocol outside of libpcap native APIs too.

guyharris commented 8 months ago

The APIs shouldn't be used as a source for developing a description of the protocol. The details of the protocol are hidden underneath the APIs - and, in fact, there may be other non-rpcap-based forms of "remote capture" implemented in the future (e.g., using the remotepeek protocol).

If somebody wants to describe the protocol, they should look not at the documentation of libpcap (or WinPcap) APIs, but at, for example, rpcap-protocol.h, rpcap-protocol.c, pcap-rpcap.c (the libpcap client-side implementation), and rpcapd/daemon.c (the rpcapd server-side implementation).

It's more like a specification

Not really. A specification wouldn't be a collection of description of subroutines and classes, it would be "here's what goes over the wire, here's what it means, and here's what the client side and server side need to do".

I don't know the historical context, it might be based on the older source from Winpcap,

It probably is, in which case it wouldn't support, for example, protocol version negotiation (which I had to implement by adding additional information at the end of an authentication reply, which can still allow newer clients to work with older servers by checking the length of the authentication reply to see if the additional information is present; older clients that don't get upset if there's extra stuff at the end of the authentication reply, such as the WinPcap client and older libpcap clients, can work with newer servers).

I'll look at the Go implementation to make sure it can handle extra stuff at the end of the authentication reply and, if not, tell them what needs to be done to fix that.

and the source here might have deviated a bit since or not.

The source here has definitely deviated - I audited it to make sure it wouldn't run past the end of packets and cleaned up the code a bit to catch that, and also added capabilities such as the aforementioned protocol version negotiation.

And, at some point, in my Copious Free Time(TM), I'll finish my Internet-Draft-style rpcap protocol specification.

guyharris commented 8 months ago

I'll look at the Go implementation to make sure it can handle extra stuff at the end of the authentication reply

It appears that it will read, but ignore, anything in the authentication reply that's past the standard message header, so a client using that code should work with a server based on the current code (it won't be able to negotiate any protocol version other than version 0, but there aren't yet any such versions, and if you, for example, run the server on a big-endian Linux box and remotely capture on a netfilter device on that box from a little-endian client, hilarity will ensure as the packets won't have host-byte-order fields in the right byte order).

(That, by the way, will power my default rejection of ALL future LINKTYPE_ requests with host-byte-order data. Not until the last IBM Z mainframe running Linux is melted down for scrap will that policy change.)

daluu commented 7 months ago

Regarding the rpcap protocol, I haven't looked through the full sources yet, is there anything to be aware of regarding TCP vs UDP and how the data is sent?

I just noticed this blurb from a fork of Winpcap's rpcapd: https://github.com/ExtraHop/rpcapd?tab=readme-ov-file#udpstr-mode

Was wondering if that has any applicability to the latest version of rpcapd here.

infrastation commented 7 months ago

It would help to state which problem you are looking to solve.

guyharris commented 7 months ago

I just noticed this blurb from a fork of Winpcap's rpcapd: https://github.com/ExtraHop/rpcapd?tab=readme-ov-file#udpstr-mode

Was wondering if that has any applicability to the latest version of rpcapd here.

The only part that applies is "The unmodified winpcap rpcapd forwards each captured packet encapsulated in a udp packet with some added headers:", which is what the unmodified libpcap rpcapd also does (in the same format - the only protocol change between the WinPcap version and the current libpcap version is that the libpcap rpcap server appends some additional information to the authentication message reply, indicating the range of protocol versions supported by the server and the byte order of the server, and the libpcap rpcap client reads that information and uses it to 1) determine the right protocol version to use and 2) byte-swap some packet data as necessary.

The libpcap rpcap client will assume 1) only version 0 is supported and 2) the byte order is the same as the host running the client if the extra data is missing, so it'll work with older servers.

The WinPcap rpcap client will ignore that extra data, so it will work with newer servers.

I.e., the protocol change is compatible, and can be used in the future to negotiate the newest protocol version supported on both sides if there is ever a newer protocol version, and to properly handle, on a machine with one byte order, captures such as netlink captures from a machine with the opposite byte order.

There is no support for udpstr mode in the libpcap rpcap client or server, so the problems with UDP mentioned by that page exist with the libpcap code.

So, again, what is the issue you're trying to resolve?

daluu commented 7 months ago

No specific issue trying to solve, just wanted to be aware of some protocol specific details, since as mentioned here, there is no official protocol specification other than looking through the code.

infrastation commented 7 months ago

For a problem that does not exist this is taking a bit too much attention. Let's reconsider this in 30 days.

infrastation commented 3 months ago

Closing due to lack of focus.