From fbfef44944021c656d1ac031be442685204c6d78 Mon Sep 17 00:00:00 2001 From: Catalan Lover Date: Wed, 5 Aug 2026 12:04:25 +0200 Subject: [PATCH] Add config flag for ACL Allow IP Literals. This is bot wide and not exposed in the AS subset of the config because this patch is lazy. Its a simple fix to add to the AS subset later if demand materialises. --- .changeset/afraid-pans-sing.md | 5 ++++ .changeset/jolly-falcons-stay.md | 6 +++++ .../ServerACLConsequencesRenderer.tsx | 2 ++ apps/draupnir/src/config.ts | 3 +++ config/default.yaml | 5 ++++ .../ServerACLSynchronisationCapability.ts | 26 ++++++++++++++----- ...latedServerBanSynchronisationCapability.ts | 3 ++- 7 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 .changeset/afraid-pans-sing.md create mode 100644 .changeset/jolly-falcons-stay.md diff --git a/.changeset/afraid-pans-sing.md b/.changeset/afraid-pans-sing.md new file mode 100644 index 00000000..12f42230 --- /dev/null +++ b/.changeset/afraid-pans-sing.md @@ -0,0 +1,5 @@ +--- +"draupnir": minor +--- + +Add the ability to change if ACLs should allow ip literals. diff --git a/.changeset/jolly-falcons-stay.md b/.changeset/jolly-falcons-stay.md new file mode 100644 index 00000000..388e7538 --- /dev/null +++ b/.changeset/jolly-falcons-stay.md @@ -0,0 +1,6 @@ +--- +"@the-draupnir-project/matrix-protection-suite": minor +--- + +Expose ability to configure if ACLs should allow IP literals. Defaults to false +as before. diff --git a/apps/draupnir/src/capabilities/ServerACLConsequencesRenderer.tsx b/apps/draupnir/src/capabilities/ServerACLConsequencesRenderer.tsx index 74dcfc3e..cf8fb814 100644 --- a/apps/draupnir/src/capabilities/ServerACLConsequencesRenderer.tsx +++ b/apps/draupnir/src/capabilities/ServerACLConsequencesRenderer.tsx @@ -145,6 +145,7 @@ describeCapabilityContextGlue< return capabilityProvider.factory(protectionDescription, { stateEventSender: draupnir.clientPlatform.toRoomStateEventSender(), protectedRoomsSet: draupnir.protectedRoomsSet, + allowIpLiterals: draupnir.config.serverAclAllowIpLiterals, }); }, }); @@ -161,6 +162,7 @@ describeCapabilityContextGlue< ): Capability { return capabilityProvider.factory(protectionDescription, { protectedRoomsSet: draupnir.protectedRoomsSet, + allowIpLiterals: draupnir.config.serverAclAllowIpLiterals, } as ServerACLSynchronisationCapabilityContext); }, }); diff --git a/apps/draupnir/src/config.ts b/apps/draupnir/src/config.ts index 77ee9a56..67d8869e 100644 --- a/apps/draupnir/src/config.ts +++ b/apps/draupnir/src/config.ts @@ -94,6 +94,8 @@ export interface IConfig { logMutedModules: string[]; verifyPermissionsOnStartup: boolean; disableServerACL: boolean; + /** Whether to allow ip literals in produced server ACLs (m.room.server_acl.allow_ip_literals) */ + serverAclAllowIpLiterals: boolean; noop: boolean; automaticallyRedactForReasons: string[]; // case-insensitive globs protectAllJoinedRooms: boolean; @@ -217,6 +219,7 @@ const defaultConfig: IConfig = { verifyPermissionsOnStartup: true, noop: false, disableServerACL: false, + serverAclAllowIpLiterals: false, automaticallyRedactForReasons: ["spam", "advertising"], protectAllJoinedRooms: false, backgroundDelayMS: 500, diff --git a/config/default.yaml b/config/default.yaml index 3f436712..82b007cf 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -88,6 +88,11 @@ noop: false # DO NOT change this to `true` unless you are very confident that you know what you are doing. disableServerACL: false +# Whether or not Draupnir should allow IP literals in `m.room.server_acl` events. +# This is a security risk as it allows for much easier spam by just using a ton of throwaway IP addresses. +# Dont enable this unless you know what you are doing and have a very good reason to do so. +serverAclAllowIpLiterals: false + # A case-insensitive list of ban reasons to have the bot also automatically redact the user's messages for. # # If the bot sees you ban a user with a reason that is an (exact case-insensitive) match to this list, diff --git a/packages/matrix-protection-suite/src/Protection/StandardProtections/ServerBanSynchronisation/ServerACLSynchronisationCapability.ts b/packages/matrix-protection-suite/src/Protection/StandardProtections/ServerBanSynchronisation/ServerACLSynchronisationCapability.ts index 36a8005f..32246312 100644 --- a/packages/matrix-protection-suite/src/Protection/StandardProtections/ServerBanSynchronisation/ServerACLSynchronisationCapability.ts +++ b/packages/matrix-protection-suite/src/Protection/StandardProtections/ServerBanSynchronisation/ServerACLSynchronisationCapability.ts @@ -42,7 +42,8 @@ class ServerACLQueue { public constructor( private readonly stateEventSender: RoomStateEventSender, private readonly serverName: StringServerName, - private readonly protectedRoomsSet: ProtectedRoomsSet + private readonly protectedRoomsSet: ProtectedRoomsSet, + private readonly allowIpLiterals: boolean ) { // nothing to do. } @@ -51,7 +52,11 @@ class ServerACLQueue { roomID: StringRoomID, projection: ServerBanIntentProjection ): Promise> { - const ACL = compileServerACL(this.serverName, projection.currentNode); + const ACL = compileServerACL( + this.serverName, + projection.currentNode, + this.allowIpLiterals + ); const stateRevision = this.protectedRoomsSet.setRoomState.getRevision(roomID); if (stateRevision === undefined) { @@ -131,9 +136,12 @@ class ServerACLQueue { export function compileServerACL( ourServerName: StringServerName, - projectionNode: ServerBanIntentProjectionNode + projectionNode: ServerBanIntentProjectionNode, + allowIpLiterals = false ): ServerACLBuilder { - const builder = new ServerACLBuilder(ourServerName).denyIpAddresses(); + const builder = allowIpLiterals + ? new ServerACLBuilder(ourServerName).allowIpAddresses() + : new ServerACLBuilder(ourServerName).denyIpAddresses(); builder.allowServer("*"); for (const serverName of projectionNode.deny) { builder.denyServer(serverName); @@ -151,12 +159,14 @@ export class ServerACLSynchronisationCapability public constructor( stateEventSender: RoomStateEventSender, - private readonly protectedRoomsSet: ProtectedRoomsSet + private readonly protectedRoomsSet: ProtectedRoomsSet, + allowIpLiterals = false ) { this.queue = new ServerACLQueue( stateEventSender, userServerName(this.protectedRoomsSet.userID), - protectedRoomsSet + protectedRoomsSet, + allowIpLiterals ); } @@ -207,6 +217,7 @@ export class ServerACLSynchronisationCapability export type ServerACLSynchronisationCapabilityContext = { stateEventSender: RoomStateEventSender; protectedRoomsSet: ProtectedRoomsSet; + allowIpLiterals?: boolean; }; describeCapabilityProvider({ @@ -220,7 +231,8 @@ describeCapabilityProvider({ ) { return new ServerACLSynchronisationCapability( context.stateEventSender, - context.protectedRoomsSet + context.protectedRoomsSet, + context.allowIpLiterals ?? false ); }, }); diff --git a/packages/matrix-protection-suite/src/Protection/StandardProtections/ServerBanSynchronisation/SimulatedServerBanSynchronisationCapability.ts b/packages/matrix-protection-suite/src/Protection/StandardProtections/ServerBanSynchronisation/SimulatedServerBanSynchronisationCapability.ts index bc13d895..4352c008 100644 --- a/packages/matrix-protection-suite/src/Protection/StandardProtections/ServerBanSynchronisation/SimulatedServerBanSynchronisationCapability.ts +++ b/packages/matrix-protection-suite/src/Protection/StandardProtections/ServerBanSynchronisation/SimulatedServerBanSynchronisationCapability.ts @@ -35,7 +35,8 @@ export class SimulatedServerBanSynchronisationCapability public constructor(private readonly protectedRoomsSet: ProtectedRoomsSet) { this.simulatedCapability = new ServerACLSynchronisationCapability( FakeStateSender, - this.protectedRoomsSet + this.protectedRoomsSet, + false ); this.outcomeFromIntentInRoom = this.simulatedCapability.outcomeFromIntentInRoom.bind(