3.2. Running configuration
The SMTP server (smtpd) handles all email going in and out, including the queue subsystem. As described in the SMTP server script manual it is primaily configured using hooks on the SMTP command phases; HELO, MAIL FROM, RCPT TO, etc. Similarily, the queue can be configured using pre- and post-delivery hooks as described in the queue script manual. Virtual queues are defined by the active queue policy (using concurrency and rate).
This is the reloadable part of the configuration,
which contains the bulk of the configuration data.
The default start configuration’s
environment.appconf
directive
loads it from /etc/halon/smtpd-app.yaml.
It is described by, and can be validated with, the
smtpd-app.schema.json.
It can be softly reloaded and deployed in a blue-green fashion using per-connection conditions from Visual Studio Code, command line interface or control sockets.
3.2.1. Script directives
The script is normally edited as individual files using Visual Studio Code or simply a text editor. Those are then checked and “packed” into an actual configuration file by the halonconfig script. For example, two script files called src/hooks/rcptto/smtplookup.hsl and src/hooks/queue/predelivery.hsl will result in:
scripting:
hooks:
rcptto:
- id: smtplookup
data: |
...
predelivery: |
...
and the “smtplookup” RCPT TO script can then be hooked into a server with:
servers:
- id: inbound
phases:
rcptto:
hook: smtplookup
The default configuration in /opt/halon/share/examples contains the folder structure for all the different hook types.
Since the SMTP server can have multiple virtual servers[]
(one inbound on port 25 and one outbound on port 587 for example),
the script hooks are designed so that there can be multiple scripts
of a given hook type which are then mapped to servers. There is however
just one set of pre- and post-delivery scripts controlling the queue.
- scripting.hooks.connect[]
An array of connect scripts. Attached to a virtual server via
servers[].phases.connect.hook
.
- scripting.hooks.helo[]
An array of HELO/EHLO scripts. Attached to a virtual server via
servers[].phases.helo.hook
.
- scripting.hooks.auth[]
An array of AUTH scripts. Attached to a virtual server via
servers[].phases.auth.hook
.
- scripting.hooks.mailfrom[]
An array of MAIL FROM scripts. Attached to a virtual server via
servers[].phases.mailfrom.hook
.
- scripting.hooks.rcptto[]
An array of RCPT TO scripts. Attached to a virtual server via
servers[].phases.rcptto.hook
.
- scripting.hooks.eod[]
An array of end-of-DATA scripts. Attached to a virtual server via
servers[].phases.eod.hook
.
- scripting.hooks.proxy[]
An array of proxy scripts. Attached to a virtual server via
servers[].phases.proxy.hook
.
- scripting.hooks.disconnect[]
An array of disconnect scripts. Attached to a virtual server via
servers[].phases.disconnect.hook
.
- scripting.hooks.predelivery
The pre-delivery script executed as the first step of loading an email into the active queue.
- scripting.hooks.postdelivery
The post-delivery script executed as the last step after a delivery attempt.
- scripting.files[]
An array of virtual files used by the script hooks. It is most commonly used for imported script modules, include files, CSV lists and plain text files. As with the script hooks, this is normally populated by the halonconfig script. It is however also possible to load files from disk (on reload) if allowed by
scripting.rootpath
.scripting: files: - id: blocklist.csv path: config/blocklist.csv
3.2.2. Server directives
The virtual servers first need to be defined in the startup configuration,
as they specify which port(s) and address(es) to listen to (which cannot be softly reloaded).
All other properties are then defined in this reloadable configuration. Many of the properties only applies to
servers of type smtp
, therefore the properties which applies to http
and plugin
servers are explicitly mentioned.
- servers[]
An array of virtual servers, which for example define which script hooks should be used. They are connected to the directives of the startup configuration via their IDs, as per the example below:
servers: - id: default transport: mailserver phases: rcptto: hook: smtplookup eod: hook: inbound concurrency: total: 10000 ip: 10 - id: relay transport: mx phases: rcptto: hook: relaytrusted eod: hook: outbound
servers: - id: default listeners: - port: 25 backlog: 2048 - id: relay listeners: - port: 587 address: 192.168.0.100
- servers[].id
The id of the server. It must match the same type as configured in the startup configuration.
- servers[].type
The type of the server. It must match the same type as configured in the startup configuration. The default is
smtp
.
- servers[].concurrency.ip
The maximum total number of SMTP connections that the server accepts from a single IP address. The default is unlimited.
- servers[].concurrency.total
Also applies to http servers
The maximum total number of SMTP connections that the server accepts. Halon uses an asynchronous model, and can therefore support a much larger number compared to servers that use a process- or thread-based model. You must revise the value of
environment.rlimit.nofile
so that the server has enough file descriptor resources available. The default is 1000.servers: - id: default concurrency: total: 20000
environment: rlimit: nofile: 50000
- servers[].concurrency.reserved.total
The number of reserved connection slots. This functionality is reserving slots within the total number of allowed connections (see
servers[].concurrency.total
).
- servers[].concurrency.reserved.remoteips
An array of IP addresses which are allowed to use the reserved slots.
- servers[].phases.connect.hook
Which
scripting.hooks.connect[]
to run on connect. The default is no script; to accept the connection.
- servers[].phases.connect.remoteptr
Should a forward-confirmed reverse DNS lookup be performed on the connecting IP, for use in script and trace information (Received header). The default is false.
- servers[].phases.helo.hook
Which
scripting.hooks.helo[]
to run on HELO/EHLO. The default is no script, to send a standard response.
- servers[].phases.helo.required
Should the client be required to send HELO/EHLO before proceeding. The default is false.
- servers[].phases.auth.hook
Which
scripting.hooks.auth[]
to run on AUTH. The default is no script, which disables AUTH.
- servers[].phases.auth.mechanisms
Which SASL mechanisms to announce. The default is the built-in types LOGIN and PLAIN. If additional mechanisms are announced, they need to be implemented by the
scripting.hooks.auth[]
script.
- servers[].phases.auth.tlsrequired
Should TLS be required for AUTH. The default is false.
- servers[].phases.auth.apikeys
Only applies to http servers
List of allowed API keys for the HTTP server (sent in the X-API-Key header).
- servers[].phases.mailfrom.hook
Which
scripting.hooks.mailfrom[]
to run on MAIL FROM. The default is no script; to accept the sender.
- servers[].phases.mailfrom.unqualified
If unqualified addresses (local part only) should be accepted. The default is false.
- servers[].phases.mailfrom.maxmessages
Maximum number of messages per connection (after which a 4xx error is returned). The default is to have no limit.
- servers[].phases.rcptto.hook
Which
scripting.hooks.rcptto[]
to run on RCPT TO. The default is no script; to accept the recipient.
- servers[].phases.rcptto.unqualified
If unqualified addresses (local part only) should be accepted. The default is false.
- servers[].phases.rcptto.maxrecipients
Maximum number of recipients per message (after which a 4xx error is returned). The default is 1000.
- servers[].phases.data.maxsize
Also applies to http servers
How large DATA response to accept. The default is 10485760 bytes (10 MiB).
- servers[].phases.data.maxhops
Number of Received headers allowed (loop detection). The default is 50.
- servers[].phases.data.maxheadersize
The max message header size (in bytes). The default is 524288 bytes (512 KiB).
- servers[].phases.data.receivedheader
Also applies to http servers
Add a Received header. This property may also be an object controling the format of the added Received header. The default is true.
- servers[].phases.data.receivedheader.from
Include the
from peer (...)
information. The default istrue
.
- servers[].phases.data.receivedheader.for
For messages with only one recipient add
for <mail-address>
information. The default isfalse
.
- servers[].phases.data.receivedheader.tls
For messages received with TLS add
tls
information (such as protocol version and ciphers). The default isfalse
.
- servers[].phases.data.fixheaders
Repair RFC822 messages with broken headers, by injecting a \r\n before the broken header, making it part of the message body. This is the default behvariour of most MTA’s. The default is
false
.
- servers[].phases.data.multipart
Also applies to http and plugin servers
If set to
false
, disable MIME multipart parsing. The message will still contain the RFC822 headers, but no MIME parts will be parsed.
- servers[].phases.data.multipart.maxparts
The maximum message mimeparts to allow (before rejecting the message as invalid). The default is
512
.
- servers[].phases.data.multipart.fixheaders
Repair MIME multipart messages with broken headers, by injecting a \r\n before the broken header, making it part of the message part body. The default is
false
.
- servers[].phases.eod.hook
Also applies to http and plugin servers
Which
scripting.hooks.eod[]
to run on end-of-DATA. The default is no script; to queue the email for all recipients.
- servers[].phases.proxy.patterns[]
An array of SMTP command “patterns” before which to run the
servers[].phases.proxy.hook
script. The SMTP commands are matched up to the length of the pattern, case-insensitive. For example, specifying just one letter (such as “q”) will run the proxy script before all SMTP commands starting with that letter (such as QUIT). The default is to run the proxy script before all commands.
- servers[].phases.proxy.hook
Which
scripting.hooks.proxy[]
to run on before commands matched byservers[].phases.proxy.patterns[]
. The default is no script.
- servers[].phases.disconnect.hook
Which
scripting.hooks.disconnect[]
to run on disconnect. The default is no script.
- servers[].hostname
Also applies to http and plugin servers
The hostname shown in the banner and HELO/EHLO. The default is to use the system hostname. This can be overridden by the
scripting.hooks.connect[]
andscripting.hooks.helo[]
scripts.
- servers[].proxy.xforwardedfor
Only applies to http servers
Allow a HTTP proxy to change the notion of
remoteip
by sending the X-Forwarded-For header.
- servers[].extensions.smtputf8
Enable support for the SMTPUTF8 extension. The default is false.
- servers[].extensions.chunking
Enable support for the CHUNKING extension. The default is true.
- servers[].extensions.pipelining
Enable support for the PIPELINING extension. The default is true. To enforce strict protocol synchronization rules use the
compatibility.synchronization
setting.
- servers[].extensions.xclient
An array of IP addresses or networks to allow XCLIENT from, or true to allow from anyone. The default is false; not from anyone. The following session properties may be updated ADDR, PORT, NAME, HELO and LOGIN.
- servers[].logging.protocol
Enable SMTP protocol logging (more verbose). The default is false.
- servers[].logging.hook
Also applies to http and plugin servers
Enable script hooks logging (pre and post-amble). The default is true.
- servers[].timeout.idle
Number of seconds of inactivity before disconnecting a client. The default is 300.
Note
Halon uses an asynchronous model, and can support a much larger number of connected clients compared to servers that use a process- or thread-based model. Therefore, there is usually no reason to lower this setting.
- servers[].commands.maxidle
The max amount of idle commands (RSET, NOOP) before disconnect The default is 100.
- servers[].commands.maxbad
The max amount of bad commands (syntax errors or bad commands) before disconnect The default is 10.
- servers[].tls.certs.cert
Also applies to https servers
Which
pki.private[]
to use for TLS. The default is no TLS.
- servers[].tls.certs.sni
An array with
pki.private[]
for use with SNI. The CN/SANs of the certificate will be used for matching. An optional list of subject names to use instead of the one(s) in the certificate can be provided. The default is no SNI.servers: - id: default tls: certs: cert: defaultpki sni: - cert: otherpki - cert: yetanotherpki subjects: - "test2.example.org"
- servers[].tls.protocols
Which TLS protocols to support. Available protocols are SSLv2, SSLv3, TLSv1, TLSv1.1, TLSv1.2, and TLSv1.3. Either specify a list of explicitly supported protocols or a list of ! unsupported protocol (meaning that all not excluded are supported, which may support future version of TLS). The default is !SSLv2,!SSLv3 (meaning that TLSv1 and later are supported).
- servers[].tls.ciphers
Which TLS ciphers to support (<=TLSv1.2). The ciphers supported in each group may differ between different version of OpenSSL and SSL/TLS versions (see the openssl ciphers command). The default is aNULL:-aNULL:HIGH:MEDIUM:+RC4:@STRENGTH.
- servers[].tls.ciphersuites
Which TLS cipher suites to support (TLSv1.3). The cipher suites supported in each group may differ between different version of OpenSSL and SSL/TLS versions (see the openssl ciphers command).
- servers[].tls.clientcert
An array of IP addresses or networks to request client certificates from, or true to request from anyone. The default is false; not from anyone.
- servers[].tls.implicit
An array of startup configuration
servers[].listeners[]
IDs to enable implicit TLS for, or true enable implicit TLS for all listeners on this virtual server. The default is false; no implicit TLS.To enable implcit TLS on port 465, but not 587, you need reference the listener on port 465 by its ID idof465:
- id: relay listeners: - port: 465 id: idof465 - port: 587
servers: - id: relay tls: implicit: - idof465
- servers[].productname
Also applies to http and plugin servers
The software name. The default is Halon. This is used in eg. Received headers.
- servers[].transport
Also applies to http and plugin servers
The default
transportgroups[].transports[]
to queue the email on. This can be overridden by thescripting.hooks.eod[]
script.
3.2.3. Transport directives
In Halon, every email is queued with a text label called “transport”, which normally
exists in the configuration as a definition for how the email should be delivered.
The parameters defined by the configured transport can be overridden in the pre- and
post-delivery script, as in the addresses[]
example.
- transportgroups[]
The transport groups are simply a logical grouping of transports in the configuration, and transports inherit parameters from the group. In addition to all the transport directives listed below, transport groups have an
id
, and an array oftransports
.
- transportgroups[].transports[]
Each of the transports have an
id
in addition to all the transport directives. The example below has two “outbound” MX transports; one with and other without DANE encryption. Then there are two other transports called “smarthost1” and “inbound” in a group called “default”.transportgroups: - id: mxes retry: count: 30 intervals: - interval: 60 - interval: 900 - interval: 3600 notify: true - interval: 7200 - interval: 10800 dsn: transport: mx connection: sourceip: ipv4: - "out1" - "out2" ipv6: - "out1v6" - "out2v6" transports: - id: mx session: tls: mode: optional - id: mxdane session: tls: mode: dane - id: default transports: - id: smarthost1 connection: server: "smtp-out.example.org" port: 587 sourceip: ipv6: false session: authentication: username: foo password: bar - id: inbound connection: server: "dovecot.example.com" port: 24 session: protocol: lmtp
The transport directives listed below are valid for both transport groups and transports.
- transportgroups[].connection.server
By default, an MX lookup is performed to determine the next hop destination. By setting the server directive, you can specify an IPv4, IPv6 or hostname as destination or alternativly an object containing
transportgroups[].connection.server.host
andtransportgroups[].connection.server.mx
. This is normally the case for “inbound” traffic to a mailbox server (maybe over LMTP) or “outbound” delivery via a so-called smarthost.
- transportgroups[].connection.server.host
This configuration option is to determine the next hop destination. The default is the recipients domain.
- transportgroups[].connection.server.mx
This configuration option is used to control if an MX or A/AAAA query is used for the
transportgroups[].connection.server.host
domain. The default is false.
- transportgroups[].connection.port
The TCP port to use for the SMTP/LMTP connection. The default is 25.
- transportgroups[].connection.proxyprotocol.server
The IP address of a outbound PROXY (haproxy) protocol server.
- transportgroups[].connection.proxyprotocol.port
The TCP port to use for the outbound PROXY (haproxy) protocol server. The default is 25.
- transportgroups[].connection.sourceip.ipv4
An array with one or more IPv4
addresses[]
IDs to use as local IP(s), or false to disable IPv4.
- transportgroups[].connection.sourceip.ipv6
An array with one or more IPv6
addresses[]
IDs to use as local IP(s), or false to disable IPv6.
- transportgroups[].connection.sourceip.random
Use a random source IP. If disabled it will use the first usable and non-suspended source IP from the ones configured. The default is true.
- transportgroups[].session.protocol
Only needed if lmtp is to be used. The default is smtp.
- transportgroups[].session.hostname
The HELO name to use. The default is to use the hostname of the
addresses[]
chosen as source IP, and to fall back to the system hostname.
- transportgroups[].session.extensions.chunking
Enable support for the CHUNKING extension. The default is true.
- transportgroups[].session.extensions.pipelining
Enable support for the PIPELINING extension. The default is true.
- transportgroups[].session.tls.mode
How to handle TLS for the connection. The default is not to use TLS (plain text). To do custom TLS verification per destination, use the pre-delivery script’s tls_X parameters. The script library contains an MTA-STS implementation.
optional: Use opportunistic, unverified TLS (fall back to plain text).
require: Require TLS, but don’t verify the peer.
dane: Verifiy the peer using DANE (DNSSEC), it not supported fallback to optional TLS. The most secure option.
dane_fallback_require: Prefer DANE, it not supported fallback to require TLS. Only makes sense for specific destinations.
dane_require: Require DANE. Only makes sense for specific destinations.
- transportgroups[].session.tls.implicit
Use implicit TLS (do not use STARTTLS). The default is false.
- transportgroups[].session.authentication.username
The username to use for password-based authentication (SASL). Normally used for sending via smarthosts. The default is to not authenticate.
- transportgroups[].session.authentication.password
- transportgroups[].retry.during
The time (?d?h?m?s formatted time, eg. 5d) during which an email will be re-delivered via the defer queue. Use
transportgroups[].retry.intervals[]
to specify each delivery attempt. This option is mutually exclusive withtransportgroups[].retry.count
.Expired messages in the active queue will be bounced if the during period elapses while in the active queue.
Note
Be aware that this time is calculated against the actual received time of an email. If an email is held in the hold queue or suspended this time is still elapsing.
- transportgroups[].retry.count
The number of times to attempt re-delivery of an email via the defer queue. Determines the time in queue together with the
transportgroups[].retry.intervals[]
. This option is mutually exclusive withtransportgroups[].retry.during
.
- transportgroups[].retry.intervals[]
An array of intervals (in seconds or ?d?h?m?s formatted time, eg. 1h30m) for how long the email should stay in the defer queue before retry. If there are fewer intervals than
transportgroups[].retry.count
, the last interval will be used for consecutive defers. As with most other transport parameters, this behvariour can be overridden via pre- and post-delivery script. By settingnotify
to true on an interval, a delayed notification will be delivered to the sender at this time.transportgroups: - id: mxes retry: count: 30 intervals: - interval: 1m - interval: 15m - interval: 1h notify: true - interval: 2h - interval: 3h
- transportgroups[].dsn.transport
Enable bounces on delivery failures via the specified transport ID.
3.2.4. Queue directives
- queues.concurrency.total
The maximum total number of outbound SMTP connections that the queue subsystem will make. This should be the basis for the virtual queues you define. Halon uses an asynchronous model, and can therefore support a much larger number compared to servers that use a process- or thread-based model. You must revise the value of
environment.rlimit.nofile
so that the server has enough file descriptor resources available. The default is 10000.queues: concurrency: total: 20000
environment: rlimit: nofile: 70000
- queues.maxmessages
The maximum number of messages in the queue subsystem (all states). When this limit is exceeded no more messages will be accepted over SMTP or HTTP. However internal messages will still be created. For more granual control use quotas. The default is unlimited.
- queues.pooling.size
The maximum number of idle connections that the queue subsystem will hold in its pooling cache for connection reuse before eviction takes place. You must revise the value of
environment.rlimit.nofile
so that the server has enough file descriptor resources available. Unlimited is 0 (not recommended). The default is 1000.
- queues.pooling.policy
The connection reuse policy. This can either be strict “remote” (based on both remoteip and remotemx matching), “remotemx” (based on only the remotemx matches, if available, otherwise remoteip) and “grouping” (based on only the grouping matches).
- queues.grouping
Queue groupings of either the recipientdomain or remotemx into a specific queue tree field called grouping. If not configured, the grouping field will be empty. Groupings are matched in order.
- queues.grouping.default
The grouping value if not
queues.grouping.groupings[]
match. This can either be “recipientdomain” or “remotemx”. This property is required.
- queues.grouping.groupings[]
List of groupings.
- queues.grouping.groupings[].id
The grouping ID. In all API’s the grouping id should be prefix with
%
. This property is required.
- queues.grouping.groupings[].unique
If the grouping should be unique per remoteip. The only valid option (enum) is
remoteip
. This will append the%grouping-name;<remoteip>
to the grouping name.
- queues.grouping.groupings[].remoteip[]
The values in the list can be IP addresses or subnets.
- queues.grouping.groupings[].remotemx[]
The values in the list can be domains, wild-card domains (
*.example.com
) or/regex/
patterns.
- queues.grouping.groupings[].recipientdomain[]
The values in the list can be domains, wild-card domains (
*.example.com
) or/regex/
patterns.
3.2.5. General directives
- postmaster.name
The name used in the From header of system generated email such as delivery reports.
- postmaster.address.localpart
The localpart of the email address used in the From header of system generated email such as delivery reports. The default is postmaster.
- postmaster.address.domain
The domain of the email address used in the From header of system generated email such as delivery reports. The default is the reporting MTA.
- addresses[]
This directive is used to define “named” IP addresses so that they can be referenced by their ID from configuration and script. This is not only useful for giving IP addresses descriptive IDs, but also since you can share script between multiple MTAs in a cluster without having to reference specific IPs that only exists on one instance.
addresses: - id: "out1" address: 198.51.100.5 hostname: smtp-out1.example.com - id: "out1v6" address: 2001:db8:85a3::8a2e:370:7334 hostname: smtp-out1.example.com - id: "out2" address: 198.51.100.6 hostname: smtp-out1.example.com - id: "out2v6" address: 2001:db8:85a3::8a2e:370:7335 hostname: smtp-out1.example.com - id: "bulk" address: 203.0.113.67 hostname: smtp-out2.example.com
They can then be referenced from for example script, like this pre-delivery snippet:
$sourceip = ["out", "out2", "outv6", "out2v6"]; if (GetMetaData()["spam"] == "yes") $sourceip = ["bulk"]; Try(["sourceip" => $sourceip]);
- addresses[].id
The ID of the IP address.
- addresses[].address
The IP address.
- addresses[].hostname
Will be used as HELO name if defined.
- addresses[].proxyprotocol.server
The IP address of a outbound PROXY (haproxy) protocol server.
- addresses[].proxyprotocol.port
The TCP port to use for the outbound PROXY (haproxy) protocol server. The default is 25.
3.2.6. List directives
These directives are used to define “named” lists which can then be referenced by prefixing their ID with “@” from the queue policy, queue suspend and queue delivery configurations. Lists may also be created using the C API.
- lists.jobid.{id}[]
The values in the list can either be job IDs or
/regex/
patterns matching job IDs.
- lists.grouping.{id}[]
The values in the list can either be groupings or
/regex/
patterns matching groupings.
- lists.localip.{id}[]
The values in the list can either be IP addresses or IP subnets (
192.168.0.0/24
).
- lists.remoteip.{id}[]
The values in the list can either be IP addresses or IP subnets (
192.168.0.0/24
).
- lists.transportid.{id}[]
The values in the list can either be transport IDs or
/regex/
patterns.
- lists.recipientdomain.{id}[]
The values in the list can be domains, wild-card domains (
*.example.com
) or/regex/
patterns.
- lists.remotemx.{id}[]
The values in the list can be domains, wild-card domains (
*.example.com
) or/regex/
patterns.
3.2.7. Resolver directives
- resolver.concurrency
The maximum number of concurrent (pending) DNS queries. This should be set according to the DNS server used. The default is 100.
- resolver.preference
The IP address family preference (A or AAAA), either
ipv4
oripv6
. The default isipv6
.
- resolver.exclude[]
A list of types
ipv4
,ipv6
(no IPv6 is available) ortlsa
(if DANE is not used) to exclude as an performance optimization. The default is not to skip any RR types.
- resolver.domain.cache.size
The number of domains to store in the in-memory LRU cache. The default is to cache
10000
domains.
- resolver.cache.size
The number of DNS queries to store in the in-memory LRU cache. The default is no caching.
- resolver.cache.ttl.min
Normalize the time-to-live values in the cache to have at least this value.
- resolver.cache.ttl.max
Normalize the time-to-live values in the cache to have at most this value.
- resolver.mx.exclude.ip[]
A list of IP addresses or networks that will be excluded from MX lookup results. This may be useful to prevent looping traffic (eg. MX resolving to 127.0.0.1).
- resolver.mx.exclude.mx[]
A list of domains or wild-card domains (
*.example.com
) that will be excluded from MX lookup results. This may be useful to prevent looping traffic (eg. MX resolving to localhost).
3.2.8. Other directives
- plugins[]
Specify a reloadable configuration to a plugin based on it’s id.
plugins: - id: test config: myval: true
- plugins[].id
The ID of the plugin.
- plugins[].config
The reloadable configuration. This property may be either a string or an YAML object. If this property is given as a string it must point to a YAML file on disk.
- pki.private[]
Array of private keys, possibly with X.509 certificates, for use with
servers[]
and script functions such as PKCS7, RSA, DKIM, client certificates, etc.The
id
andprivatekey
properties are required, andcertificate
is optional. The privatekey can however be defined in the startup configuration for the same ID, in which case it is not required. The private key and certificate should have either apath
ordata
property.pki: private: - id: selfsigned certificate: data: |- -----BEGIN CERTIFICATE----- ... privatekey: data: |- -----BEGIN PRIVATE KEY----- ...
Note
For privilege separation reasons, it’s normally recommended to define the private keys in the startup configuration instead of here, as it is read before the privilege drop.
- compatibility.barelf
The SMTP RFC requires <CR><LF> as end-of-line and end-of-data delimiters. However the use of bare <LF> is sometimes used in legacy clients, printers or various tools.
Halon always allows bare <LF> as end-of-line delimiter for SMTP commands.
Halon always converts any bare <LF> in the message DATA into <CR><LF>.
However, there is a known issue when there is a mismatch of the end-of-data delimiter (<CR><LF>.<CR><LF>) between the client and server, causing potential message injection attacks if both do not agree on when to terminate the message (smuggling).
Halon auto-detect by default (if not configured) if it should allow the combination of bare <LF>.<LF> as end-of-data sequence based on the first header line terminator. This assumes that non-conforming client will use <LF> as line delimiter for the entire data stream. Known smuggling attacks are not practially possible with the default auto-detect setting.
This setting may be set to
true
to always allow bare <LF> (no auto-detect)false
to never allow bare <LF>array[] of IP-addresses/networks to only allow bare <LF> from those hosts
- compatibility.synchronization
Enable this feature to enforce stricter protocol synchronization rules. This feature works in combination with
servers[].extensions.pipelining
.without PIPELINING (rfc5321) all commands are synchronization points
with PIPELINING (rfc2920) only check synchronization points at certain commands
Due to the nature of TCP and network delays, it’s not always possible to detect protocol violations. The default is false.
3.2.9. Example
Below is an unrealistically simple example of a running configuration with a few transports. The actual scripting is omitted, since it is normally packed by the tools.
servers:
- id: default
transport: mailserver
phases:
mailfrom:
hook: ldaplookup
eod:
hook: inbound
concurrency:
total: 10000
ip: 10
- id: relay
transport: mx
phases:
mailfrom:
hook: relaylist
eod:
hook: outbound
transportgroups:
- id: default
transports:
- id: mx
session:
tls:
mode: dane
dsn:
transport: mx
retry:
count: 30
intervals:
- interval: 60
- interval: 300
- interval: 3600
notify: true
- interval: 7200
- id: mailserver
connection:
server: mail.example.com
port: 25
retry:
count: 30
intervals:
- interval: 10
- interval: 60
- interval: 3600
queueus:
concurrency:
total: 10000
postmaster:
address: [email protected]
name: Postmaster
3.2.10. Additional configurations
There are several other running configuration files, listed below.
3.2.10.1. Queue policy
Specified by the environment.policyconf
directive
and documented in the queue section.
3.2.10.2. Queue suspend
Specified by the environment.suspendconf
directive
and documented in the queue section.
3.2.10.3. Queue delivery
Specified by the environment.deliveryconf
directive
and documented in the queue section.
3.2.10.4. Rate subsystem
Configuration for the rated program that is used for the rate() script function.
Specified by rated.yaml’s environment.appconf
directive.
It is described by, and can be validated with, the
rated-app.schema.json
JSON schema (included in our Visual Studio Code integration).
3.2.10.5. Content inspection
Configuration for the dlpd program that is used for the DLP script function.
Specified by dlpd.yaml’s environment.appconf
directive.
It is described by, and can be validated with, the
dlpd-app.schema.json
JSON schema (included in our Visual Studio Code integration).