Skip to main content

ARC module

This module verifies and signs ARC (Authenticated Received Chain) signatures and seals for emails. ARC provides a mechanism for preserving email authentication results across trusted intermediaries, which is particularly useful for mailing lists and forwarding services that may modify messages in ways that break SPF and DKIM alignment.

The ARC standard is defined in RFC 8617. An overview presentation is available at https://dmarc.org/presentations/ARC-Overview-2016Q2-v03.pdf.

Rspamd supports both ARC verification and signing since version 1.6. It uses the dkim module internally for cryptographic operations.

Symbols

The module registers the following symbols:

SymbolScoreDescription
ARC_ALLOW-1.0Valid ARC chain found
ARC_REJECT2.0ARC chain validation failed
ARC_INVALID1.0ARC chain structure is invalid
ARC_DNSFAIL0.0DNS lookup failed during validation
ARC_NA0.0No ARC headers present
ARC_ALLOW_TRUSTED-2.0Valid ARC chain from a trusted forwarder (requires whitelisted_signers_map)
ARC_SIGNED0.0Message was signed with ARC

Configuration

Settings should be added to /etc/rspamd/local.d/arc.conf.

Basic settings

OptionTypeDefaultDescription
selectorstringarcDefault selector for ARC signing
pathstring${DBDIR}/arc/$domain.$selector.keyPath to signing key (supports $domain and $selector variables)
sign_symbolstringARC_SIGNEDSymbol added when message is signed
try_fallbackbooleantrueFall back to global config if domain-specific config not found

Domain selection

OptionTypeDefaultDescription
use_domainstringheaderDomain source: header (MIME From), envelope (SMTP From), recipient (SMTP To), auth (authenticated user), or explicit domain name
use_esldbooleantrueNormalize domains to effective second-level domain (eSLD)
use_domain_sign_networksstring-Override use_domain for sign_networks
use_domain_sign_localstring-Override use_domain for local IPs
use_domain_sign_inboundstring-Override use_domain for inbound mail
use_domain_customstring/function-Custom Lua function to determine signing domain

Signing eligibility

OptionTypeDefaultDescription
sign_authenticatedbooleantrueSign messages from authenticated users
sign_localbooleantrueSign messages from local IP addresses
sign_inboundbooleanfalseSign inbound messages (not local, not authenticated)
sign_networksmap-Map of networks eligible for signing
skip_spam_signbooleanfalseSkip signing if message is marked as spam
allowed_idstable-List of settings IDs that allow signing
forbidden_idstable-List of settings IDs that forbid signing

Header/envelope validation

OptionTypeDefaultDescription
allow_envfrom_emptybooleantrueAllow signing with empty envelope From
allow_hdrfrom_mismatchbooleanfalseAllow envelope/header From domain mismatch
allow_hdrfrom_mismatch_localbooleanfalseAllow mismatch for local IPs
allow_hdrfrom_mismatch_sign_networksbooleanfalseAllow mismatch for sign_networks
allow_hdrfrom_multiplebooleanfalseAllow multiple From headers (only first is used)
allow_username_mismatchbooleanfalseAllow authenticated user domain to differ from signing domain

Trusted forwarders and whitelisting

OptionTypeDefaultDescription
whitelisted_signers_mapmap-Map of trusted ARC forwarder domains
whitelistmap-Map of domains with broken ARC implementations to trust despite validation failures
adjust_dmarcbooleantrueAdjust DMARC score when trusted forwarder provides valid ARC chain

Redis integration

OptionTypeDefaultDescription
use_redisbooleanfalseLoad signing keys from Redis
key_prefixstringarc_keysRedis hash name for keys
selector_prefixstring-Redis hash name for selectors (optional)

Vault integration

OptionTypeDefaultDescription
use_vaultbooleanfalseLoad signing keys from HashiCorp Vault
vault_urlstring-Vault server URL
vault_tokenstring-Vault authentication token
vault_pathstringdkimPath in Vault for keys
vault_kv_versionnumber1Vault KV secrets engine version (1 or 2)
vault_domainsmap-Map of domains to look up in Vault

Public key verification

OptionTypeDefaultDescription
check_pubkeybooleanfalseVerify public key exists before signing
allow_pubkey_mismatchbooleanfalseContinue signing even if public key lookup fails

Authentication results

OptionTypeDefaultDescription
reuse_auth_resultsbooleanfalseReuse existing Authentication-Results header instead of generating new one

HTTP headers (for proxy integration)

OptionTypeDefaultDescription
use_http_headersbooleanfalseGet signing parameters from HTTP request headers
http_sign_headerstringPerformDkimSignHeader indicating signing should be performed
http_domain_headerstringDkimDomainHeader containing domain
http_selector_headerstringDkimSelectorHeader containing selector
http_key_headerstringDkimPrivateKeyHeader containing private key
allow_headers_fallbackbooleanfalseFall back to normal signing if headers missing

Basic configuration example

# local.d/arc.conf

# Default signing selector
selector = "arc";

# Path template for keys
path = "${DBDIR}/arc/$domain.$selector.key";

# Sign mail from authenticated users and local networks
sign_authenticated = true;
sign_local = true;

# Use header From domain for signing
use_domain = "header";
use_esld = true;

# Domain-specific configuration
domain {
example.com {
path = "${DBDIR}/arc/example.com.key";
selector = "arc2024";
}
}

Trusted ARC forwarders

The whitelisted_signers_map setting allows you to configure trusted ARC forwarders. When an email has a valid ARC chain that includes a signature from one of these trusted domains, Rspamd will:

  1. Add the ARC_ALLOW_TRUSTED symbol with a score of -2.0
  2. If adjust_dmarc is enabled (default), reduce the impact of DMARC failures

This is particularly useful for legitimate email forwarding services that may alter messages in ways that break DKIM signatures, but can be trusted based on their ARC signatures.

# local.d/arc.conf

# Inline array
whitelisted_signers_map = ["mailgun.org", "sendgrid.net", "amazonses.com"];

# Or file-based map
whitelisted_signers_map = "file:///etc/rspamd/maps/arc_trusted_signers.map";

# Adjust DMARC policy for trusted forwarders (enabled by default)
adjust_dmarc = true;

For file-based maps, create a simple text file with one domain per line:

mailgun.org
sendgrid.net
amazonses.com

Handling broken ARC implementations

Some email services have broken ARC implementations that fail validation despite being legitimate forwarders. The whitelist option allows ARC chain validation to continue despite failures from specified domains.

When a domain is in the whitelist:

  • ARC signature/seal validation failures for that domain are logged but treated as valid
  • The ARC chain validation continues to the next step
  • This preserves the security of the overall chain while accommodating known bugs
# local.d/arc.conf

# Domains with known broken ARC implementations
whitelist = ["broken-forwarder.com", "buggy-arc.example"];

# Or file-based map
whitelist = "file:///etc/rspamd/maps/arc_whitelist.map";

ARC keys in Redis

To store ARC signing keys in Redis:

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

Populate the hash with keys using the format selector.domain:

-- Run with: redis-cli --eval script.lua
local key = [[-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANe3EETkiI1Exyrb
...
-----END PRIVATE KEY-----]]
redis.call('HMSET', 'arc_keys', 'myselector.example.com', key)

Using maps for selectors and paths

Use selector_map and path_map to configure per-domain selectors and key paths:

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

Map format (domain followed by value):

example.net arc2024
example.org default

For paths:

example.net /var/lib/rspamd/arc/example.net.$selector.key
example.org /etc/rspamd/arc/example.org.key

To require explicit configuration for each domain (no fallback):

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

Vault integration

For HashiCorp Vault integration:

# local.d/arc.conf
use_vault = true;
vault_url = "https://vault.example.com:8200";
vault_token = "your-vault-token";
vault_path = "secret/dkim";
vault_kv_version = 2;

# Optional: restrict to specific domains
vault_domains = ["example.com", "example.org"];

Expected Vault secret structure at secret/dkim/example.com:

{
"selectors": [
{
"selector": "arc2024",
"domain": "example.com",
"key": "-----BEGIN PRIVATE KEY-----\n...",
"valid_start": 1704067200,
"valid_end": 1735689600
}
]
}

Sign headers

From version 1.8.4, Rspamd uses a specific set of headers for ARC signing. The default can be overridden:

# local.d/arc.conf
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";

The (o) prefix indicates optional headers (included only if present).