Open s3rj1k opened 4 years ago
Hello @s3rj1k! I intended to add real client validation and checking if client address is validated as the next step of this demo project, but unfortunately I recently had little time for it. I do have some working code though, so feel free to ask. Basically, you have to declare a BPF map of type BPF_TYPE_HASH and call bpf_map_lookup_elem()
to check if a client is validated and bpf_map_update_elem()
to mark an IP validated after an ACK with a correct SYN cookie.
@PlushBeaver I am willing to test it out, please share :)
Code pushed to usermode-proto
branch.
Create a local directory and mount BPF FS there (see xdp_control.cc
):
mkdir maps
sudo mount -t bpf none maps
After getting the stand up and attaching the filter, you can watch statistics and mange validated client list:
$ sudo ./xdp_control watch
time 1580352190
pass 5089231 packets 274818515 bytes
back 1 packets 74 bytes
drop 939557 packets 50736078 bytes
$ sudo ./xdp_control list
192.0.2.2
$ sudo ./xdp_control delete 192.0.2.2
$ # see xdp_control.cc for more commands
@PlushBeaver I am having trouble compiling this code on Ubuntu 19.10 with 5.3.0-29-generic kernel.
libbpf is compiled from git HEAD.
/usr/bin/ld: xdp_control.cc:(.text+0x3a6): undefined reference to `bpf_map_get_next_key'
/usr/bin/ld: xdp_control.cc:(.text+0x41f): undefined reference to `bpf_map_update_elem'
/usr/bin/ld: xdp_control.cc:(.text+0x436): undefined reference to `bpf_map_delete_elem'
/usr/bin/ld: xdp_control.cc:(.text+0x458): undefined reference to `bpf_map_lookup_elem'
Also loading xdp like this, compiled from master brunch:
ip -force link set dev eth0 xdp object xdp_filter.o
Drops all inbound connections, outbound connections work.
@PlushBeaver There is also bpf helper for syncookie https://www.fclose.com/linux-kernels/3990408-bpf-add-helper-to-check-for-a-valid-syn-cookie
I am wondering, can this be reused?
@s3rj1k,
It appears, these functions were a bit renamed in upstream: https://github.com/iovisor/bcc/blob/master/src/cc/libbpf.h#L4. I test my code in Arch Linux 5.4.12-arch1-1 with libbpf-git 5188b0c-1.
Yes, this filter drops all inbound connections with an RST, even the ones that provide a valid SYN cookie. The next connection from the same client will pass the filter, because client's IP is in the table. This is done because kernel does not know about this connection, as the handshake was handled by XDP. One workaround is to send an out-of-sequence ACK instead of RST, which will make the client to repeat the handshake without closing the connection. Note that some real-world middleboxes may interfere with this scheme.
Reused in which way? You cannot call it, because it requires a struct bpf_sock*
, which you do not have in an RX filter. You may be able to borrow some code from there, but it is already present in my sample.
@PlushBeaver
https://github.com/torvalds/linux/blob/master/tools/testing/selftests/bpf/progs/test_tcp_check_syncookie_kern.c
I have sshd running on my host and verify as follows:
$ make all
$ mkdir maps
$ sudo mount -t bpf none maps
$ sudo ./stand up
$ sudo ./stand attach
<output omitted>
$ sudo ./xdp_control install
bpf_prog_load() = 0 <--- success, despite of the following
libbpf: failed to pin map: File exists
bpf_object__pin_maps() = -17
$ sudo ./stand exec ssh 192.0.2.1
ssh: connect to host 192.0.2.1 port 22: Connection reset by peer <--- RST by filter
$ sudo ./stand exec ssh 192.0.2.1
root@192.0.2.1's password: <--- SSH connected
I didn't not know this function existed. It seems you're correct and it can be used here. I haven't tried it myself yet, so cannot comment further.
One workaround is to send an out-of-sequence ACK instead of RST, which will make the client to repeat the handshake without closing the connection. Note that some real-world middleboxes may interfere with this scheme.
Are there any websites that document this behavior?
Do I just send a packet with only the ACK and no SYN flag with a random acknowledgement number?
@bottiger1, please pardon me for this misguiding typo. I meant to write "send an out-of-sequence SYNACK instead, then wait for an RST". By placing cookie in SYN-ACK's acknum you can get it in RST thus verifying the client. Statefull firewalls may block such SYN-ACKs as bogus. This scheme is also known as safe reset.
Will that make the client auto-reconnect? Why bother doing it that way if it will cause a RST anyway?
Will that make the client auto-reconnect?
Yes, that's the point. Refer to Figure 10 of RFC 793.
Hi @PlushBeaver I have already been able to assemble everything perfectly, the only problem I have is that from the server I cannot download or browse. How could I solve it?
https://github.com/PlushBeaver/xdp-syn-cookie/blob/master/xdp_filter.c#L320