1
1
Fork
You've already forked bindrestrict
0
Daemon to restrict which ports users can bind to using eBPF
  • C 92.2%
  • Makefile 7.8%
Find a file
2026年04月21日 20:06:28 +01:00
bpf-compat/gnu Add dummy gnu/stubs.h file for BPF 2026年04月20日 02:29:07 +01:00
common Initial commit 2026年04月20日 02:13:47 +01:00
daemon daemon: Use fork instead of vfork 2026年04月21日 02:00:06 +01:00
rulec rulec: Cap num_rules at MAX_RULES and print num_rules in decompiler 2026年04月21日 02:32:00 +01:00
.gitignore Add .gitignore 2026年04月21日 01:37:02 +01:00
COPYING Initial commit 2026年04月20日 02:13:47 +01:00
Makefile Makefile: Change -g to -g3 in default CFLAGS 2026年04月21日 01:37:03 +01:00
README.md Add missing line break in README.md 2026年04月21日 20:06:28 +01:00

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 the daemon directory)
  • bindrestrict-rulec, the ruleset compiler (source located in the rulec directory)

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:

  • compile expects a textual configuration in stdin, and writes a binary ruleset struct to stdout
  • decompile does 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 binds
  • ipv4 - Makes the rule match only on IPv4 binds
  • user= - Specifies a range of users to match, as min:max
  • group= - Specifies a range of groups to match, as min:max
  • port= - Specifies a range of ports to match, as min:max
  • addr= - Specifies a prefix to match (e.g. addr=192.168.1.0/24, or addr=::1/128). Ignored unless only one of ipv4 and ipv6 is set. It is currently possible to specify an IPv6 address while also specifying ipv4, 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 with bpf in the lsm parameter on the kernel command line or CONFIG_LSM)
  • libc, of course

Compile time only:

  • bpftool
  • A modern version of clang (supporting C23 and the bpf target)
  • 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.