- C 92.2%
- Makefile 7.8%
| bpf-compat/gnu | Add dummy gnu/stubs.h file for BPF | |
| common | Initial commit | |
| daemon | daemon: Use fork instead of vfork | |
| rulec | rulec: Cap num_rules at MAX_RULES and print num_rules in decompiler | |
| .gitignore | Add .gitignore | |
| COPYING | Initial commit | |
| Makefile | Makefile: Change -g to -g3 in default CFLAGS | |
| README.md | Add missing line break in README.md | |
bindrestrict
Daemon to restrict which ports users can bind to using eBPF. Very incomplete and lacking proper documentation currently.
Documentation
Proper documentation (man pages) will be written at some point, but here's a (削除) summary (削除ここまで) infodump:
There are two components:
bindrestrictd, the daemon (source located in thedaemondirectory)bindrestrict-rulec, the ruleset compiler (source located in therulecdirectory)
The common directory contains files used by both components.
bindrestrictd
The daemon must be ran as root and loads the eBPF program, which takes
a ruleset struct as an eBPF map. It executes the ruleset compiler
(with reduced privileges) in order to parse the configuration file.
You can use bindrestrictd --help to see which options it accepts.
Currently the default path of the ruleset compiler, the user/group to
execute it as, and the default path of the config file are hardcoded,
but at some point a configure script or similar will be added to make
this configurable at compile time.
Reloading the configuration file is not yet supported, and there is no way to restart the daemon without temporarily unloading the BPF program. This will be implemented in the future, likely by pinning the BPF program so it can survive restarts of the daemon (which will then load the new program and unload the old one).
The BPF program logs any rule matches (whether resulting in an allow
or deny) using bpf_printk. These logs may be read using
cat /sys/kernel/debug/tracing/trace_pipe. The output of the daemon
itself is logged to stderr by default, or to the syslog if the
--syslog option is passed.
bindrestrict-rulec
The ruleset compiler can be invoked with either the compile or decompile subcommand:
compileexpects a textual configuration in stdin, and writes a binary ruleset struct to stdoutdecompiledoes the opposite: it expects a binary ruleset struct in stdin, and writes a textual configuration to stdout
The daemon only uses the compile subcommand, the decompile command is purely for debugging.
Currently, the ruleset compiler has no error checking and will not fail on invalid on nonsensical rules.
It might, however, give unexpected output. For this reason it is recommended to check your rules manually using:
bindrestrict-rulec compile < bindrestrict.conf | bindrestrict-rulec decompile
The textual ruleset format
The textual ruleset format consists of one rule per line, which
contain multiple options in arbitrary order, separated by tabs or
spaces. Some options take a parameter, which is specified after an
= sign after the option name. Empty lines and lines beginning with
# (possibly with whitespace preceding it) are ignored as comments.
These options are:
allow- Makes the rule an allow rule (bind is allowed if it matches)deny- Makes the rule a deny rule (bind is denied if it matches, default)ipv6- Makes the rule match only on IPv6 bindsipv4- Makes the rule match only on IPv4 bindsuser=- Specifies a range of users to match, asmin:maxgroup=- Specifies a range of groups to match, asmin:maxport=- Specifies a range of ports to match, asmin:maxaddr=- Specifies a prefix to match (e.g.addr=192.168.1.0/24, oraddr=::1/128). Ignored unless only one ofipv4andipv6is set. It is currently possible to specify an IPv6 address while also specifyingipv4, or vice versa, but the result is nonsensical and this will be fixed when error checking is added.
If neither ipv6 nor ipv4 is specified, the rule matches both. If
no user/group/port is specified, the rule matches any user/group/port.
Currently nothing prevents duplicate options or nonsensical combinations from being specified, and the only last one takes effect. However, this will change when error checking is added.
Rules are processed in the order they are specified, and there is a hardcoded maximum of 65535 rules. If no rule matches, the bind is allowed by default.
Where a user or group is specified, it is parsed as a numeric ID if it
consists entirely of decimal digits (potentially preceded by a +).
Otherwise, it is assumed to be a user/group name. In order to specify
a user/group name consisting entirely of digits (yes, this is allowed
by POSIX), it must be preceded by an @. The same format is used for
other places that accept user/group names (bindrestrictd's --user
and --group options).
Dependencies
Runtime:
- libbpf
- libcap
- A Linux kernel with BPF-LSM support compiled in (
CONFIG_BPF_LSM=y) and enabled (booted withbpfin thelsmparameter on the kernel command line orCONFIG_LSM) - libc, of course
Compile time only:
- bpftool
- A modern version of clang (supporting C23 and the
bpftarget) - A C23 compiler supporting GNU extensions (modern versions of GCC or clang)
- GNU Make
License
GNU GPLv2 or, at your option, any later version. See COPYING for the full text.