Rspamd proxy worker

This worker provides different functionality to build multiple layers systems and to handle Milter protocol. Here is a short list of functions provided by proxy worker:

  • Forwarding of messages to scanning layer
  • Directly interacting with MTA using Milter protocol
  • Perform load balancing, retransmitting and health checks for scanning layer
  • Add encryption and/or compression to the scan requests
  • Mirror some portion of traffic to some test server
  • Compare results of mirrored request
  • Perform messages scan by own (self-scan mode)

The hosts option for the upstream and mirror can specify IP addresses or Unix domain sockets as described in the upstreams documentation. If the port number is omitted, port 11333 is assumed.

Refer to rspamadm confighelp workers.rspamd_proxy for a full list of options.

Default configuration

The most widely useful feature of the proxy worker is its ability to speak Milter protocol and the default configuration was built with this in mind. By default, the proxy worker is enabled & listening on localhost:11332 in milter mode with localhost configured as an upstream (refer to $CONFDIR/

Hence users who require Milter protocol support in their installations are provided with such out-the-box.

Users who do not require Milter support can generally use normal workers directly & disable the proxy worker to save resources.

Milter support

From Rspamd 1.6, rspamd proxy worker supports milter protocol which is supported by some of the popular MTA, such as Postfix or Sendmail. The introduction of this feature also finally obsoletes the Rmilter project in honor of the new integration method.

Milter mode is enabled by the milter boolean worker option - when enabled, proxy speaks milter protocol only. If it is disabled, the proxy is usable with Rspamd’s native HTTP protocol and the legacy protocol used by Exim.

Milter support is presented in rspamd_proxy only, however, there are two possibilities to use milter protocol:

  • Proxy mode (for large instances) with a dedicated scan layer
  • Self-scan mode (for small instances)

If your setup does not allow your MTA to reject mails set discard_on_reject (>= 1.6.2) to true for discarding spam-mails.

Self-scan mode

In this mode, rspamd_proxy scans messages itself and talk to MTA directly using Milter protocol. The advantage of this mode is its simplicity. Here is a sample configuration for this mode:

# local.d/
upstream "local" {
  self_scan = yes; # Enable self-scan

# Proxy worker is listening on *:11332 by default
#bind_socket = localhost:11332;

Also you can disable1 normal worker to free up system resources as it is not necessary in self-scan mode:

# local.d/
enabled = false;

But there is a drawback: since rspamc uses normal worker by default you need to explicitly point it to controller worker port (11334)2:

rspamc -h input-file


1. The enabled option is available for workers since Rspamd 1.6.2, in previous versions you can use count = 0; instead.

2. When connecting to local IP rspamc uses controller port by default (1.7+).

Proxy mode

In this mode, there is a dedicated layer of Rspamd scanners with load-balancing and optional encryption and/or compression. For this setup, the configuration might be different. Here is a small sample of proxy mode with 4 scanners where 2 scanners are more powerful and receive more requests. Also the local worker is disabled:

# local.d/
upstream "local" {
  disabled = true;

upstream "scan" {
  default = yes;
  hosts = "round-robin:host1:11333:10,host2:11333:10,host3:11333:5,host4:11333:5";
  key = "..."; # Public key for encryption, generated by rspamadm keypair (optional)
  compression = yes; # Use zstd compression (optional)


Proxy can be used to test:

  • new versions of Rspamd;
  • new plugins;
  • new rules;
  • configuration changes;
  • ML models.

In this mode, Rspamd mirrors some portion of traffic to a test cluster. Results of their scans are ignored when returning reply to a client, however, optional compare scripts could be started to evaluate mirror results. Here is a sample configuration of this setup (we are not using milter mode in this sample):

# local.d/
# Main scan layer
upstream "scan" {
  default = "yes";
  hosts = "round-robin:host1:11333:10,host2:11333:10,host3:11333:5,host4:11333:5";
  key = "..."; # Public key for encryption, generated by rspamadm keypair
  compression = yes; # Use zstd compression

mirror "test" {
  hosts = "test:11333";
  probability = 0.1; # Mirror 10% of traffic
  key = "..."; # Public key for encryption, generated by rspamadm keypair
  compression = yes; # Use zstd compression

Compare scripts

Compare scripts are intended to perform some simple actions with the results returned by a mirror and main cluster machine. They cannot do async request, so all you can do is to write to logs or to files. Here is a simple example of such a script in the configuration:

# local.d/
  script =<<EOD
return function(results)
  local log = require "rspamd_logger"

  for k,v in pairs(results) do
    if type(v) == 'table' then
      log.infox("%s: %s", k, v['score'])
      log.infox("err: %s: %s", k, v)