Made my Rust port into a patch that adds the dedicated reaction user.
The rc.d uglyness is now gone, but requires a patch to the Rust code
to set the correct permissions on the socket. Would prefer to have
this patch in upstream first if commited.
The pkg/MESSAGE is updated to notify of the daemon user changes and
point to the very crucial pkg/README for setup.
files/authlog.jsonnet has some new regexes to match that were taken
from the reaction documentation.
Added Lydia as maintainer since I have no objection.
Index: sysutils/reaction/Makefile
===================================================================
RCS file: /cvs/ports/sysutils/reaction/Makefile,v
diff -u -p -r1.3 Makefile
--- sysutils/reaction/Makefile 24 Jun 2026 06:48:50 -0000 1.3
+++ sysutils/reaction/Makefile 30 Jun 2026 21:55:14 -0000
@@ -3,11 +3,14 @@ COMMENT = scan logs and take action, alt
V = v2.5.1
DISTNAME = reaction-${V}
PKGNAME = ${DISTNAME:S/-v/-/}
+REVISION = 0
SITES = https://framagit.org/ppom/reaction/-/archive/${V}/
CATEGORIES = sysutils security
HOMEPAGE = https://reaction.ppom.me/
+
+MAINTAINER = Lydia Sobot <[email protected]>
# AGPL-3.0
PERMIT_PACKAGE = yes
Index: infrastructure/db/user.list
===================================================================
RCS file: /cvs/ports/infrastructure/db/user.list,v
diff -u -p -r1.490 user.list
--- infrastructure/db/user.list 6 Jun 2026 10:18:19 -0000 1.490
+++ infrastructure/db/user.list 30 Jun 2026 21:55:14 -0000
@@ -414,3 +414,4 @@ id user group port
903 _iaxmodem _iaxmodem telephony/iaxmodem
904 _neighbot _neighbot net/neighbot
905 _pgweb _pgweb www/pgweb
+906 _reaction _reaction sysutils/reaction
Index: sysutils/reaction/files/authlog.jsonnet
===================================================================
RCS file: /cvs/ports/sysutils/reaction/files/authlog.jsonnet,v
diff -u -p -r1.2 authlog.jsonnet
--- sysutils/reaction/files/authlog.jsonnet 24 Jun 2026 06:48:50 -0000
1.2
+++ sysutils/reaction/files/authlog.jsonnet 30 Jun 2026 21:55:14 -0000
@@ -1,10 +1,10 @@
local banFor(time) = {
ban: {
- cmd: ['pfctl', '-t', 'blocked_ssh', '-T', 'add', '<ip>'],
+ cmd: ['doas', 'pfctl', '-t', 'blocked_ssh', '-T', 'add', '<ip>'],
},
unban: {
after: time,
- cmd: ['pfctl', '-t', 'blocked_ssh', '-T', 'del', '<ip>'],
+ cmd: ['doas', 'pfctl', '-t', 'blocked_ssh', '-T', 'del', '<ip>'],
},
};
{
@@ -16,7 +16,7 @@ local banFor(time) = {
start: [
],
stop: [
- ['pfctl', '-t', 'blocked_ssh', '-T', 'flush'],
+ ['doas', 'pfctl', '-t', 'blocked_ssh', '-T', 'flush'],
],
streams: {
ssh: {
@@ -28,6 +28,17 @@ local banFor(time) = {
@'Failed password for invalid user .* from <ip>',
// Client disconnects during authentication
@'Disconnected from invalid user .* <ip>',
+ // Other auth failures
+ @'Connection from <ip> port [0-9]*: invalid format',
+ @'Invalid user .* from <ip>',
+ // Optional: Client disconnects during authentication
+ @'Connection (reset|closed) by (authenticating|invalid) user .*
<ip> port',
+ @'Connection (reset|closed) by <ip> port',
+ @'Disconnected from .* <ip> .*preauth',
+ @'Disconnecting .* <ip> .*preauth',
+ @'Timeout before authentication for <ip>',
+ @'Received disconnect from <ip> .*preauth',
+ @'Unable to negotiate with <ip> .*preauth',
],
retry: 3,
retryperiod: '6h',
Index: sysutils/reaction/patches/patch-src_daemon_socket_rs
===================================================================
RCS file: sysutils/reaction/patches/patch-src_daemon_socket_rs
diff -N sysutils/reaction/patches/patch-src_daemon_socket_rs
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sysutils/reaction/patches/patch-src_daemon_socket_rs 30 Jun 2026
21:55:14 -0000
@@ -0,0 +1,25 @@
+make the socket owner and group writable
+
+Index: src/daemon/socket.rs
+--- src/daemon/socket.rs.orig Mon Jun 29 00:19:57 2026
++++ src/daemon/socket.rs Sun Jun 28 20:29:58 2026
+@@ -2,6 +2,8 @@ use std::{
+ collections::{BTreeMap, HashMap},
+ path::{Path, PathBuf},
+ sync::Arc,
++ fs::Permissions,
++ os::unix::fs::PermissionsExt,
+ };
+
+ use futures::{SinkExt, StreamExt};
+@@ -51,7 +53,9 @@ async fn open_socket(path: &Path) -> Result<UnixListen
+ }),
+ }?;
+ // Open socket
+- err_str!(UnixListener::bind(path))
++ let socket = UnixListener::bind(path);
++ let _ = fs::set_permissions(path, Permissions::from_mode(0o770)).await;
++ err_str!(socket)
+ }
+
+ async fn handle_trigger_order(
Index: sysutils/reaction/pkg/MESSAGE
===================================================================
RCS file: /cvs/ports/sysutils/reaction/pkg/MESSAGE,v
diff -u -p -r1.1.1.1 MESSAGE
--- sysutils/reaction/pkg/MESSAGE 11 Sep 2024 11:30:36 -0000 1.1.1.1
+++ sysutils/reaction/pkg/MESSAGE 30 Jun 2026 21:55:14 -0000
@@ -1,6 +1,7 @@
-To block the bots connecting on ssh by default, add the following line early in
-${SYSCONFDIR}/pf.conf:
+reaction now uses a seperate user for running the daemon.
+Please see the package README for setup details.
-table <blocked_ssh> persist
+Pre 2.5.1p0 users will want to update the database ownership as
+follows:
+# chown _reaction:_reaction /var/reaction/reaction.db
-block return in quick log from <blocked_ssh>
Index: sysutils/reaction/pkg/PLIST
===================================================================
RCS file: /cvs/ports/sysutils/reaction/pkg/PLIST,v
diff -u -p -r1.2 PLIST
--- sysutils/reaction/pkg/PLIST 24 Jun 2026 06:48:50 -0000 1.2
+++ sysutils/reaction/pkg/PLIST 30 Jun 2026 21:55:14 -0000
@@ -1,3 +1,5 @@
+@newgroup _reaction:906
+@newuser _reaction:906:906:default:reaction daemon:/var/reaction:/sbin/nologin
@rcscript ${RCDIR}/reaction
@bin bin/reaction
@bin bin/reaction-plugin-virtual
@@ -13,13 +15,20 @@
share/bash-completion/
share/bash-completion/completions/
share/bash-completion/completions/reaction
+share/doc/pkg-readmes/${PKGSTEM}
share/examples/reaction/
share/examples/reaction/README.md
share/examples/reaction/authlog.jsonnet
@sample ${SYSCONFDIR}/reaction/authlog.jsonnet
share/examples/reaction/example.jsonnet
share/examples/reaction/example.yml
-@sample /var/reaction/
+@mode 750
+@owner _reaction
+@group _reaction
+@sample ${LOCALSTATEDIR}/reaction/
+@mode
+@owner
+@group
share/fish/
share/fish/vendor_completions.d/
share/fish/vendor_completions.d/reaction.fish
Index: sysutils/reaction/pkg/README
===================================================================
RCS file: sysutils/reaction/pkg/README
diff -N sysutils/reaction/pkg/README
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sysutils/reaction/pkg/README 30 Jun 2026 21:55:14 -0000
@@ -0,0 +1,54 @@
++-------------------------------------------------------------------------------
+| Running ${PKGSTEM} on OpenBSD
++-------------------------------------------------------------------------------
+
+Access to log files
+==============
+
+You need to give the _reaction user access to the log files in one of the
+following ways.
+
+Adding _reaction to the wheel group
+-------------------
+# usermod -G wheel _reaction
+
+Creating a new group
+-------------------
+# groupadd groupname
+# usermod -G groupname admin
+# usermod -G groupname _reaction
+# chown :groupname /var/log/authlog
+
+Allowing world readable access
+-------------------
+# chmod 644 /var/log/authlog
+
+Each option has its own security considerations.
+
+Choose which best fits your needs.
+
+Access to pfctl
+==============
+
+Add the following to the bottom of your doas.conf(5) file:
+
+ deny _reaction
+ permit nopass keepenv _reaction as root cmd pfctl
+
+This denies the _reaction user any of the earlier privileges and only
+grants access to pfctl.
+
+Reaction and pf configuration
+==============
+
+You can find yml and jsonnet configuration examples at:
+/usr/local/share/examples/reaction/
+
+The example file, authlog.jsonnet, is configured to monitor /var/log/authlog
+and block any repeated attempts at logon through pfctl(8) with the following
+pf.conf(5) configuration:
+
+ table <blocked_ssh> persist
+
+ block return in quick log from <blocked_ssh>
+
Index: sysutils/reaction/pkg/reaction.rc
===================================================================
RCS file: /cvs/ports/sysutils/reaction/pkg/reaction.rc,v
diff -u -p -r1.2 reaction.rc
--- sysutils/reaction/pkg/reaction.rc 24 Jun 2026 06:48:50 -0000 1.2
+++ sysutils/reaction/pkg/reaction.rc 30 Jun 2026 21:55:14 -0000
@@ -4,6 +4,7 @@ daemon="${TRUEPREFIX}/bin/reaction"
daemon_flags="start -c ${SYSCONFDIR}/reaction/"
daemon_execdir="${LOCALSTATEDIR}/reaction"
daemon_logger="daemon.info"
+daemon_user=_reaction
. /etc/rc.d/rc.subr
@@ -11,7 +12,7 @@ rc_reload=NO
rc_bg=YES
rc_pre() {
- install -d ${LOCALSTATEDIR}/run/reaction
+ install -d -g wheel -m 750 -o _reaction ${LOCALSTATEDIR}/run/reaction
}
rc_cmd $1
On Wed, 24 Jun 2026 21:02:00 +0200
"Lydia Sobot" <[email protected]> wrote:
> On Wed Jun 24, 2026 at 08:50 CEST, Landry Breuil wrote:
> > fwiw, i've finally been able to test it and replaced my setup, still
> > works fine. welcoming further improvements to run it as a separate
> > unpriviledged user, but that requires:
> > - improving MESSAGE to mention what needs to go in doas.conf
> > - testing in various situations
> Sounds good to me, I'm also looping upstream in to guide development.
> Also, if there are no objections, I am willing to take maintainer.