ARC module

This module checks ARC signatures and seals for emails scanned. ARC signatures can establish that this specific message has been signed and then forwarded by a number of a trusted relays. There is a good overview of the ARC standard here:

Rspamd (from 1.6) supports both checking and signing for ARC signatures and seals. Internally, it uses dkim module for dealing with signatures.

The configuration of this module is very similar to both dkim and dkim_signing modules.


  • whitelist - a map of domains that should not be checked with ARC (e.g. if that domains have totally broken ARC signer)
  • whitelisted_signers_map - a map of the trusted ARC forwarders
  • adjust_dmarc (true by default) - a boolean flag that allows to fix DMARC when we observer a trusted ARC forwarder in the chain. It is useful for example, if we have some domain X that uses some signer Y to forward email, however, X defines a strict DMARC policy whilst Y alters message somehow in a legit way. But if we trust Y, then we can fix DMARC rejection for X with this option.

Principles of operation

The ARC signing module chooses signing domains and selectors according to a predefined policy which can be modified with various settings. Description of this policy follows:

  • To be eligible for signing, a mail must be received from an authenticated user OR a reserved IP address OR an address in the sign_networks map (if defined)
  • If envelope from address is not empty, the effective second level domain must match the MIME header From
  • If authenticated user is present, this should be suffixed with @domain where domain is what’s seen is envelope/header From address
  • Selector and path to key are selected from domain-specific config if present, falling back to global config


# local.d/arc.conf

# If false, messages with empty envelope from are not signed
allow_envfrom_empty = true;
# If true, envelope/header domain mismatch is ignored
allow_hdrfrom_mismatch = false;
# If true, multiple from headers are allowed (but only first is used)
allow_hdrfrom_multiple = false;
# If true, username does not need to contain matching domain
allow_username_mismatch = false;
# Default path to key, can include '$domain' and '$selector' variables
path = "${DBDIR}/arc/$domain.$selector.key";
# Default selector to use
selector = "arc";
# If false, messages from authenticated users are not selected for signing
sign_authenticated = true;
# If false, messages from local networks are not selected for signing
sign_local = true;
# Symbol to add when message is signed
symbol_signed = "ARC_SIGNED";
# Whether to fallback to global config
try_fallback = true;
# Domain to use for ARC signing: can be "header" or "envelope"
use_domain = "header";
# Whether to normalise domains to eSLD
use_esld = true;
# Whether to get keys from Redis
use_redis = false;
# Hash for ARC keys in Redis
key_prefix = "ARC_KEYS";
# map of domains -> names of selectors (since rspamd 1.5.3)
#selector_map = "/etc/rspamd/";
# map of domains -> paths to keys (since rspamd 1.5.3)
#path_map = "/etc/rspamd/";
# map of trusted domains. Symbol ARC_ALLOW_TRUSTED is added to messages
# with valid ARC chains from these domains. A failed DMARC result is removed/ignored.
# whitelisted_signers_map = ["", ""]

# From version 1.8.4, Rspamd uses a different set of sign_headers for ARC:
sign_headers = "(o)from:(o)sender:(o)reply-to:(o)subject:(o)date:(o)message-id:(o)to:(o)cc:(o)mime-version:(o)content-type:(o)content-transfer-encoding:resent-to:resent-cc:resent-from:resent-sender:resent-message-id:(o)in-reply-to:(o)references:list-id:list-owner:list-unsubscribe:list-subscribe:list-post:dkim-signature"

# Domain specific settings
domain { {
    # Private key path
    path = "${DBDIR}/arc/example.key";
    # Selector
    selector = "ds";

ARC keys in Redis

To use ARC keys stored in Redis you should add the following to configuration:

# local.d/arc.conf
use_redis = true;
key_prefix = "ARC_KEYS";
selector = "myselector";

… and populate the named hash with ARC keys; for example the following Lua script could be run with redis-cli --eval:

local key = [[-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----]]'HMSET', 'ARC_KEYS', '', key)

The selector will be chosen as per usual (a domain-specific selector will be used if configured, otherwise the global setting is used).

Using maps

One or both of selector_map or path_map can be used to look up selectors and paths to private keys respectively (using the ARC signing domain as the key). If entries are found, these will override default settings.

In the following configuration we define a templatised path for the ARC signing key, a default selector, and a map which could be used for overriding the default selector (and hence effective path to the signing key as well). Any eligible mail will be signed given there is a suitably-named key on disk.

# local.d/arc.conf
try_fallback = true;
path = "${DBDIR}/arc/$domain.$selector.key";
selector_map = "/etc/rspamd/";
selector = "arc";

In the following configuration, we attempt to sign only domains which are present in both selector_map and path_map:

# local.d/arc.conf
try_fallback = false;
selector_map = "/etc/rspamd/";
path_map = "/etc/rspamd/";

Format of the maps should be as shown:

$ head -1 /etc/rspamd/ dkim
$ head -1 /etc/rspamd/ /var/lib/rspamd/dkim/$selector.key