Adding trusted sender IPs to rspamd configuration

I have some forum software that despite learning all messages received in the past as ham still is too aggressively marked as SPAM, mainly because of the ONCE_RECEIVED_STRICT (7.5) [static] rule.

I would like to circumvent this by adding the originating server IP in the trusted network section for RSPAMD but have not idea how to do so on NethServer 8.

I want to add something along the lines of `trusted_networks = “127.0.0.0/8;a.b.c.d/32”;`. Any pointers on how to do so?

create bypass rules in the filter menu ?

I will try although that seems like a very general way bypassing all for the specified entity. I would have liked to add it to the trusted_networks to prevent the ONCE_RECEIVED_STRICT rule from being hit.

Another idea, the UI of rspamd itself, you can lower the score if you think it is too hight or if you want to try something specific. From a general point of view I find the score good, and I rely on it, most of time the sender is guilty to not respect the standart of smtp.

Yes, I know I can lower the score, but apparently ONCE_RECEIVED_STRICT is a very high valued (static) check compared to others, meaning most likely a spam sender, but in this case it is a legitimate sender.

I don’t think I will bother the forum admin with how to setup DKIM, SPF and DMARC although that for sure would make this score not trigger.

For now I have added my specific (bounce)mail address for this forum as a bypass rule.

Apparently it is a lua policy module and is not affected by normal whitelist files, the ones listed in rspamd configuration tab.

Apparently it is controlled by /etc/rspamd/local.d/once_received.conf file, what would be the best way to customize this file?

Current configuration seems to be:

$ podman exec -it rspamd rspamadm configdump once_received
*** Section once_received ***
good_host = "mail";
bad_host [
    "static",
    "dynamic",
]
symbol_strict = "ONCE_RECEIVED_STRICT";
symbol = "ONCE_RECEIVED";
symbol_mx = "DIRECT_TO_MX";

*** End of section once_received ***

Obviously I want to add the ip address to the good_host line and I want it to be persistent over updates and other (re)configuration changes.

Readme says to modify /etc/rspamd/override.d for Rspamd custom configuration, but does not give any hints how? Copy the original (including which relative path?) and make adjustments?

I think the adjusted file needs to be in the override.d directory like /etc/rspamd/override.d/once_received.conf
See also GitHub - NethServer/ns8-mail: NS8 Mail module with SMTP, IMAP, Spam/Virus filter

2 Likes

Okay, for now I have done to enter the rspamd podman container:

# runagent -m mail1
# podman exec -it rspamd sh

Then inside the container I created a local.d override for once_received.conf:

# echo `whitelist = "/etc/rspamd/once_received_whitelist.map";` > /etc/rspamd/local.d/once_received.conf

Then added the ip address I want to whitelist to the map:

echo "affetced-ip-address" >> /etc/rspamd/once_received_whitelist.map

Tested the configuration:

# rspamadm configtest
syntax OK
# rspamadm configdump once_received
*** Section once_received ***
good_host = "mail";
bad_host [
    "static",
    "dynamic",
]
symbol_strict = "ONCE_RECEIVED_STRICT";
symbol = "ONCE_RECEIVED";
symbol_mx = "DIRECT_TO_MX";
whitelist = "/etc/rspamd/once_received_whitelist.map";

*** End of section once_received ***

And reload the configuraition:

# rspamadm control reload
workers {
    28 {
        type = "rspamd_proxy";
        status = 0;
    }
    30 {
        type = "normal";
        status = 0;
    }
    29 {
        type = "controller";
        status = 0;
    }
    31 {
        type = "hs_helper";
        status = 0;
    }
}

Information was based on how the override system works in the rspamd FAQ and the RSPAMD once_received configuration options.

Now it is wait and see what the mail from this domain will do…

1 Like

You would need to put the files in the override.d directory to make it persistent as only the override.d directory is saved in a volume, see also ns8-mail/imageroot/systemd/user/rspamd.service at 34640e41f5c89cfafdbc463c3884c988cb94b9fe · NethServer/ns8-mail · GitHub

1 Like

Yes, but that would mean overriding whole configuration fragments where the subtlety of the rspamd override mechanism has a less invasive option to merge with default configuration using /etc/rspamd/local.d/.
I have created a NFR for it as I already noticed changes were lost after a rspamd container restart.

1 Like

I prefer to keep local.d/ contents under the control of the container image and allow customization only through override.d/.

What the admin is expected to do is simply follow the Rspamd guidelines, as you did. I agree it is a little more verbose, but this approach ensures that the admin’s changes always take precedence over possible updates or changes inside the container image.

Back to the issue itself: the proper way to address this use case is to define a dynamic configuration table in our image implementation. Dynamic Rspamd configuration files can be modified directly from the Rspamd UI, which makes them a better fit for advanced or environment-specific settings such as trusted networks or rules affecting ONCE_RECEIVED_STRICT.

If you agree with this approach, I’ll close your NFR and open a new one focused on introducing a dynamic configuration table.

2 Likes

I think you are missing the way rspamd is doing configuration and what you are currently inserting into local.d should be in module.d as I interpret their Configuration Precedence right.

Using local.d you can then do small additions/alterations that merge or override default configuration so you don’t have to do full overrides for complete configurations.

This is even their suggested main approach and suggested as best practice.

With regards to the mapping I think that this should also be a persistent volume, not sure if that is already the case.

No, I don’t agree, but I am not in the development team :slight_smile: . I am also not sure whether the discussion should take place here or in the NFR.

I think I got your point, and I summarized mine in the feature close comment here: https://github.com/NethServer/dev/issues/7799#issuecomment-3722545248

Yes, it is. The rspamd-data volume is already persistent and is used for that purpose.

This forum is the right place to discuss features and bugs and to converge on decisions. We generally use the issue tracker mainly for the implementation phase, once there is agreement on what to do. You can find a full description of this workflow here: https://handbook.nethserver.org/

1 Like

Unfortunately I cannot reopen the NFR to continue the discussion there but I think there is a better way (respecting your wishes) as well as sticking more closely to the rspamd design w/r to configuration overrides.

Since I cannot post to the feature request I will post it here:

This is a deliberate trade-off between preserving the upstream configuration structure and the Mail module’s container-based architecture, while still providing a supported and persistent customization path through override.d/.

What upstream configuration? AFAICT, based on mail-rspamd versions · nethserver · GitHub you are using plan alpine container and have etc/local.d under your control in ns8-mail. That could as well be mapped as modules.d instead or am I wrong here?

:thought_balloon: Another way to keep as close to the rspamd design philosophy (and allow for local.d volume) could be the following I think:

Take for instance your current etc/modules.d/antivirus.conf, originally (w/o comments) it is:

$ podman exec -it rspamd grep -Ev '^[[:space:]]*#' /etc/rspamd/modules.d/antivirus.conf
antivirus {
  .include(try=true,priority=5) "${DBDIR}/dynamic/antivirus.conf"
  .include(try=true,priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/antivirus.conf"
  .include(try=true,priority=10) "$LOCAL_CONFDIR/override.d/antivirus.conf"
}

I think this could (easily) be extended by adding defaults from another folder (e. g. etc/rspamd/nethserver.d for instance) and merge them with a lower priority so users can override them using /etc/rspamd/local.d/ when you make /etc/rspamd/modules.d/antivirus.conf contain this:

antivirus {
  .include(try=true,priority=5) "${DBDIR}/dynamic/antivirus.conf"
  .include(try=true,priority=1,duplicate=merge) "$LOCAL_CONFDIR/nethserver.d/antivirus.conf"
  .include(try=true,priority=2,duplicate=merge) "$LOCAL_CONFDIR/local.d/antivirus.conf"
  .include(try=true,priority=10) "$LOCAL_CONFDIR/override.d/antivirus.conf"
}

:red_exclamation_mark: Note the changes for priority here for local.d w/r to the default one (slight increase) and the addition of the nethserver.d specifics with a lower priority w/r to the local.d one so changes in local.d win from default suggestions from your side.

:rocket: If I am not mistaken this should merge the values you want to suggest from nethserver with the defaults as you do now and still make it possible to mount local.d as a volume and specify overridden values by the administrator of the system.

:folded_hands: I am hoping you can/will accept this and reopen the feature request to implement this as I think it is a win/win as explained above.

Thanks for taking the time to think this through and write up a concrete proposal, it’s appreciated.

When I refer to “upstream configuration”, I mean what is provided by Alpine’s Rspamd packages. In NS8 Mail the intent is to keep modules.d/ as shipped by Alpine, use local.d/ inside the image for the module’s own configuration, and expose override.d/ as the persistent hook for administrator customizations.

While we technically control local.d/ and could introduce additional layers (such as a nethserver.d/), doing so would diverge from Alpine’s layout and effectively create a Mail-specific configuration model. That adds complexity and makes it harder to reason about behavior using upstream Rspamd documentation.

Mapping local.d/ as a writable volume would also blur the distinction between vendor configuration and admin intent, which we explicitly try to keep separate in a containerized module to ensure predictable upgrades.

For the specific case you mentioned (excluding a sender or host from a policy like once_received), using override.d/ is the supported and expected approach today. There are already examples of admin-side customization following this model, such as the Howto for blocking TLDs and email addresses in NS8 Mail: NS8: How to Block Top-Level Domains (TLD) and Email Addresses

Dynamic configuration tables under /var/lib/rspamd can also be an option in some scenarios, especially when UI integration is useful, but I haven’t fully evaluated that path yet.

1 Like