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

Netfilter hooks support and example #980

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

ThisSeanZhang
Copy link
Contributor

  • Add support for attaching eBPF programs to netfilter hooks
  • Add eBPF-based Netfilter blocklist example with Rust control program

Copy link
Collaborator

@danielocfb danielocfb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just skimmed it so far and overall this looks like a reasonable addition. Thanks! Can you please add tests for the functionality? Until we have converged on a more recent vmlinux.h you can just depend on your fork. Will take a closer look then.

Comment on lines 51 to 56
/* To view log output, use: cat /sys/kernel/debug/tracing/trace_pipe */
__be32 addr_host = bpf_ntohl(key.addr);
bpf_printk("Blocked IP: %d.%d.%d.%d, prefix length: %d, map value: %d\n",
(addr_host >> 24) & 0xFF, (addr_host >> 16) & 0xFF,
(addr_host >> 8) & 0xFF, addr_host & 0xFF,
key.prefixlen, *match_value);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation seems off?

#[derive(Clone, Debug, Default)]
/// Options to be provided when attaching a program to a netfilter hook.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's reorder comments before derives for consistency with the rest of the code, please.

@ThisSeanZhang
Copy link
Contributor Author

Please forgive my unfamiliarity with this process. I’m not certain if these tests fully meet the requirements, so if there are additional needs or adjustments, please feel free to let me know, and I’ll do my best to make the necessary additions.

Thank you again for your guidance! 😀

@ThisSeanZhang
Copy link
Contributor Author

Hi @danielocfb , I encountered an issue with the CI tests for this PR. The test_netfilter test fails in the CI environment, but it runs successfully on my local setup.

I'm not entirely sure what might be causing the CI failure. Here’s the successful output from my local environment:

root@router-dev:~/libbpf-rs# cargo test --test test_netfilter
   Compiling libbpf-rs-dev v0.0.0 (/root/libbpf-rs/libbpf-rs/dev)
   Compiling libbpf-rs v0.24.6 (/root/libbpf-rs/libbpf-rs)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 5.57s
     Running tests/test_netfilter.rs (target/debug/deps/test_netfilter-95979185154ac64b)

running 2 tests
test test_invalid_netfilter_opts::root::test ... ok
test test_netfilter::root::test ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

root@router-dev:~/libbpf-rs# uname -a
Linux router-dev 6.9.10+bpo-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.9.10-1~bpo12+1 (2024-07-26) x86_64 GNU/Linux

Let me know if there’s anything specific I should check or modify to address this. Thanks!

@danielocfb
Copy link
Collaborator

Hm, I am not quite sure either. Seems to be some kernel SNAFU. It could be some limitation of the FORWARD hook on the kernel used in CI. Perhaps try excluding it for now.

@danielocfb
Copy link
Collaborator

danielocfb commented Nov 1, 2024

Overall the tests you added seem reasonable, thanks! However, it would be good to also have one that actually makes sure that we trigger the BPF program when, say, sending a package. That is basically what we do for most other probe types and it provides us with some confidence that something is actually happening. Here is what we do for tracepoints:

/// Check that we can attach a BPF program to a kernel tracepoint.
#[tag(root)]
#[test]
fn test_object_tracepoint() {
    bump_rlimit_mlock();

    let mut obj = get_test_object("tracepoint.bpf.o");
    let prog = get_prog_mut(&mut obj, "handle__tracepoint");
    let _link = prog
        .attach_tracepoint("syscalls", "sys_enter_getpid")
        .expect("failed to attach prog");

    let map = get_map_mut(&mut obj, "ringbuf");
    let action = || {
        let _pid = unsafe { libc::getpid() };
    };
    let result = with_ringbuffer(&map, action);

    assert_eq!(result, 1);
}

Do you think you can come up with a similar test for netfilter programs?

@ThisSeanZhang ThisSeanZhang force-pushed the support_netfilter_prog branch 4 times, most recently from 19dcbcb to 9aa0d80 Compare November 2, 2024 06:57
…ctionality

* Fix netfilter-blocklist vmlinux
* Fix format in netfilter-blocklist dependencies
* Update syntax for Rust min version compatibility
* Excluding the [ FORWARD, LOCAL_OUT ] hook
@ThisSeanZhang
Copy link
Contributor Author

I've added a packet sending verification test in test_netfilter.

Thank you again for your patience and guidance ! ! !

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