An eBPF XDP program that helps with finding IP addresses that have tried to reach out to a specific port during a certain interval (IPv4 and IPv6 with TCP or UDP payloads only). It serves the metrics in prometheus format as well as a list of IP addresses with some extra metadata.
The initial idea was to find out who is connected to what, specifically for services that does not provide such capabilities out of the box.
This project is a work in progress.
-
The return code for all received packets is always
XDP_PASS
and the default XDP attach mode isSKB_MODE
. -
XDP programs are invoked right after the network driver recieves a packet. Since it doesn't know whether there is an open socket for a specific port or not, it's a good idea to specify ports you care about using
--ports
flag. -
Built with Aya and Rust.
An eBPF XDP program that helps with finding IP addresses that have tried to reach out to a specific port during a certain interval. Metrics are served in prometheus format on :[server_port]/metrics and IPs are available on :[server_port]/list
Usage: xdp-ip-counter [OPTIONS]
Options:
-i, --iface <IFACE> Network Interface to attach eBPF program to [default: eth0]
-p, --ports <PORTS> Comma-separated ports to collect data for. 0 means all ports [default: 0]
-w, --window <WINDOW> Sampling interval in seconds. value must be divisable by 10 [default: 60]
-s, --server-port <SERVER_PORT> Port to serve prometheus metrics on (i.e. HTTP Server Port) [default: 3031]
--serve-ip-list Whether to serve a list of connected IP addresses on :[server_port]/list
-h, --help Print help
# HELP active_users Number of users actively hitting on a specific port.
# TYPE active_users counter
active_users{network="IPv4",transport="TCP",port="22"} 8
# EOF
Available at :[server_port]/metrics
, This indicates that 8 unique IPv4 addresses have tried to connect to port 22 over the past sampling interval.
[
{
"ip": "xxx.xxx.xxx.xxx",
"network": "IPv4",
"transport": "TCP",
"port": 22
},
{
"ip": "yyy.yyy.yyy.yyy",
"network": "IPv4",
"transport": "TCP",
"port": 22
},
...
}
Served at :[server_port]/list
- Download and extract the binary from releases
- Run with appropriate flags, e.g.
sudo ./xdp-ip-counter --iface=eth0 --ports=80,22 --window=60 --server-port=3031 --serve-ip-list
- Install rust stable toolchain:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- Install rust nightly toolchain with the rust-src component:
rustup toolchain install nightly --component rust-src
- Add x86_64-unknown-linux-musl target:
rustup target add x86_64-unknown-linux-musl
- Install bpf-linker:
cargo install bpf-linker
- Build eBPF:
cargo xtask build-ebpf --release
- Build binary:
cargo build --release --target=x86_64-unknown-linux-musl
- Run:
sudo ./target/x86_64-unknown-linux-musl/release/xdp-ip-counter --iface=eth0 --ports=80,22 --window=60 --server-port=3031 --serve-ip-list
- Run steps 1-4
- Run with appropriate flags, e.g.
RUST_LOG=info cargo xtask run -- --iface=eth0 --ports=80,22 --window=60 --server-port=3031 --serve-ip-list
- IPv6 Support
- Show/Hide Local IP addresses via CLI flags
- Use Prometheus Client Library instead of a custom one
- Add Support for more IP Protocols
- Cache counts for the duration of sampling interval
- An option to filter based on destination address (e.g. ignore forwarding packets)