# reaction A daemon that scans program outputs for repeated patterns, and takes action. A common usage is to scan ssh and webserver logs, and to ban hosts that cause multiple authentication errors. 🚧 This program hasn't received external security audit. However, it already works well on my servers 🚧 ## Rationale I was using the honorable fail2ban since quite a long time, but i was a bit frustrated by its CPU consumption and all its heavy default configuration. In my view, a security-oriented program should be simple to configure and an always-running daemon should be implemented in a fast*er* language. reaction does not have all the features of the honorable fail2ban, but it's more than 10x faster and has more manageable configuration. [πŸ“½οΈ quick french name explanation πŸ˜‰](https://u.ppom.me/reaction.webm) [πŸ‡¬πŸ‡§ in-depth blog article](https://blog.ppom.me/en-reaction) / [πŸ‡«πŸ‡· french version](https://blog.ppom.me/fr-reaction) ## Rust rewrite reaction v2.x is a complete Rust rewrite of reaction. It's in feature parity with the Go version, v1.x, which is now deprecated. See https://blog.ppom.me/en-reaction-v2. ## Configuration YAML and [JSONnet](https://jsonnet.org/) (more powerful) are supported. both are extensions of JSON, so JSON is transitively supported. - See [reaction.yml](./config/example.yml) or [reaction.jsonnet](./config/example.jsonnet) for a fully explained reference (ipv4 + ipv6) - See the [wiki](https://reaction.ppom.me) for multiple examples, security recommendations and FAQ. - See [server.jsonnet](https://reaction.ppom.me/configurations/ppom/server.jsonnet.html) for a real-world configuration - See [reaction.service](./config/reaction.service) for a systemd service file - This minimal example (ipv4 only) shows what's needed to prevent brute force attacks on an ssh server (please read at least the [Security](https://reaction.ppom.me/security.html) part of the wiki before starting πŸ†™):
/etc/reaction.yml ```yaml patterns: ip: type: ipv4 start: - [ 'iptables', '-w', '-N', 'reaction' ] - [ 'iptables', '-w', '-I', 'INPUT', '-p', 'all', '-j', 'reaction' ] - [ 'iptables', '-w', '-I', 'FORWARD', '-p', 'all', '-j', 'reaction' ] stop: - [ 'iptables', '-w', '-D', 'INPUT', '-p', 'all', '-j', 'reaction' ] - [ 'iptables', '-w', '-D', 'FORWARD', '-p', 'all', '-j', 'reaction' ] - [ 'iptables', '-w', '-F', 'reaction' ] - [ 'iptables', '-w', '-X', 'reaction' ] streams: ssh: cmd: [ 'journalctl', '-fu', 'sshd.service' ] filters: failedlogin: regex: - 'authentication failure;.*rhost=' - 'Failed password for .* from ' - 'Invalid user .* from ', - 'banner exchange: Connection from port [0-9]*: invalid format', retry: 3 retryperiod: '6h' actions: ban: cmd: [ 'iptables', '-w', '-I', 'reaction', '1', '-s', '', '-j', 'DROP' ] unban: cmd: [ 'iptables', '-w', '-D', 'reaction', '1', '-s', '', '-j', 'DROP' ] after: '48h' ```
/etc/reaction.jsonnet ```jsonnet local banFor(time) = { ban: { cmd: ['iptables', '-w', '-A', 'reaction', '-s', '', '-j', 'DROP'], }, unban: { cmd: ['iptables', '-w', '-D', 'reaction', '-s', '', '-j', 'DROP'], after: time, }, }; { patterns: { ip: { type: 'ipv4', }, }, start: [ ['iptables', '-N', 'reaction'], ['iptables', '-I', 'INPUT', '-p', 'all', '-j', 'reaction'], ['iptables', '-I', 'FORWARD', '-p', 'all', '-j', 'reaction'], ], stop: [ ['iptables', '-D', 'INPUT', '-p', 'all', '-j', 'reaction'], ['iptables', '-D', 'FORWARD', '-p', 'all', '-j', 'reaction'], ['iptables', '-F', 'reaction'], ['iptables', '-X', 'reaction'], ], streams: { ssh: { cmd: ['journalctl', '-fu', 'sshd.service'], filters: { failedlogin: { regex: [ @'authentication failure;.*rhost=', @'Failed password for .* from ', @'banner exchange: Connection from port [0-9]*: invalid format', @'Invalid user .* from ', ], retry: 3, retryperiod: '6h', actions: banFor('48h'), }, }, }, }, } ```
### Database The embedded database is stored in the working directory (but can be overriden by the `state_directory` config option). If you don't know where to start reaction, `/var/lib/reaction` should be a sane choice. ### CLI - `reaction start` runs the server - `reaction show` show pending actions (ie. show current bans) - `reaction flush` permits to run pending actions (ie. clear bans) - `reaction trigger` permits to manually trigger a filter (ie. run custom ban) - `reaction test-regex` permits to test regexes - `reaction test-config` shows loaded configuration - `reaction help` for full usage. ### `ip46tables` and `nft46` > ⚠️Deprecated since v2.2.0: > reaction now provides builtin support for executing different actions on ipv4 and ipv6. > They will be removed in a future version. `ip46tables` and `nft46` are two minimal c programs present in the `helpers_c` directory with only standard posix dependencies. `ip46tables` permits to configure `iptables` and `ip6tables` at the same time. It will execute `iptables` when detecting ipv4, `ip6tables` when detecting ipv6 and both if no ip address is present on the command line. `nft46` works slightly differently: it will replace the `X` in its argument by 4 or 6 depending on the ip address on the command line. This permits to have 2 IP sets, one of type `ipv4_addr` and one of type `ipv6_addr`. ## Wiki You'll find more ressources, service configurations, etc. on [the wiki](https://reaction.ppom.me)! We recommend that you read the ***Good Practices*** chapters before starting. ## Installation [![Packaging status](https://repology.org/badge/vertical-allrepos/reaction-fail2ban.svg)](https://repology.org/project/reaction-fail2ban/versions) ### Binaries Executables and .deb packages are provided [in the releases page](https://framagit.org/ppom/reaction/-/releases/), for x86-64/amd64 linux and aarch64/arm64 linux. Signature verification and installation instructions are provided in the releases page. > Provided binaries are compiled by running `nix-shell release.py` on a NixOS machine with docker installed. #### NixOS reaction is packaged, but the [**module**](https://framagit.org/ppom/nixos/-/blob/main/modules/common/reaction.nix) has not yet been upstreamed. #### OpenBSD See the [wiki](https://reaction.ppom.me/configurations/OpenBSD.html). ### Compilation You'll need a recent rust toolchain for reaction and a c compiler for ip46tables. ```shell $ make ``` Don't hesitate to take a look at the `Makefile` to understand what's happening! ### Installation To install the binaries ```shell make install ``` To install the systemd file as well ```shell make install_systemd ``` ## Contributing > We, as participants in the open source ecosystem, are ethically responsible for the software > and hardware we help create - as it can be used to perpetuate inequalities or help empower > marginalized communities, and fight against patriarchy, capitalism, sexism, gender violence, > racism, ableism, homophobia, colonialism, fascism, surveillance, and oppressive control. - [NGI's Diversity and Inclusion Guide](https://nlnet.nl/NGI0/bestpractices/DiversityAndInclusionGuide-v4.pdf) I'll do my best to maintain a safe contribution place, as free as possible from discrimination and elitism. ### Ideas Please take a look at issues which have the "Opinion Welcome πŸ‘€" label! *Your opinion is welcome.* Your ideas are welcome in the issues. ### Code Contributions are welcome. For any substantial feature, please file an issue first, to be assured that we agree on the feature, and to avoid unnecessary work. I recommend reading [`ARCHITECTURE.md`](ARCHITECTURE.md) first. This is a quick tour of the codebase, which should save time to new contributors. You can also join this Matrix development room: [#reaction-dev-en:club1.fr](https://matrix.to/#/#reaction-dev-en:club1.fr). French version: [#reaction-dev-fr:club1.fr](https://matrix.to/#/#reaction-dev-fr:club1.fr). ## Help You can ask for help in the issues or in this Matrix room: [#reaction-users-en:club1.fr](https://matrix.to/#/#reaction-users-en:club1.fr). French version: [#reaction-users-fr:club1.fr](https://matrix.to/#/#reaction-users-fr:club1.fr). ## Funding This project is currenlty funded through the [NGI0 Core](https://nlnet.nl/core) Fund, a fund established by [NLnet](https://nlnet.nl) with financial support from the European Commission's [Next Generation Internet](https://ngi.eu) programme. ![NLnet logo](logo/nlnet.svg)