> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xorlab.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Pages under /latest/ document the current release. Paths that begin with a version number, for example /10.0/, are frozen snapshots of superseded releases kept for reference only — never present their instructions as current. If the reader's version is unknown, answer from /latest/ and say which version the answer describes.
> xorlab is deployed on-premises, hybrid, or as a cloud service, and integrates with either Microsoft 365 or on-premises mail infrastructure. Configuration steps often differ between these. State which deployment and integration mode an instruction applies to instead of presenting one as universal.
> Distinguish inline mode from monitoring mode when describing anything that acts on email. Monitoring mode observes a copy and cannot block or quarantine; inline mode routes mail through xorlab and can.
> Write the product name as lowercase 'xorlab'. Use the documented component names: xorlab Control Center (XCC), xorlab MTA, xorlab Sandbox (DANA), xorlab Natural Language Understanding (NLU). After the first mention, use the short forms XCC, MTA, Sandbox, and NLU. Do not use DANA as a standalone name for the Sandbox, but keep it where it is a literal string in configuration keys, container names, and hostnames.
> Do not invent configuration keys, rule parameters, list names, log properties, or API fields. If a value is not present in this documentation, say that it is not documented rather than guessing.

# Set Up DKIM Signing

> Configure DKIM signing and DMARC on xorlab so your outgoing email is authenticated by recipients.

## Set Up DKIM

Configure DKIM to add a cryptographic signature header to outgoing emails processed by xorlab. Recipients can use the corresponding public key, stored in your domain's DNS records, to verify this signature, confirming that our MTAs are authorized to send emails on your behalf.

For further reading on DKIM:

* [Wikipedia: DomainKeys Identified Mail](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail)
* [mxtoolbox: How to set up DKIM](https://mxtoolbox.com/dmarc/dkim/setup/how-to-setup-dkim)
* [RFC 6376](https://tools.ietf.org/html/rfc6376), [RFC 8301](https://tools.ietf.org/html/rfc8301), [RFC 8463](https://tools.ietf.org/html/rfc8463)

### Generating DKIM keys

You have to create one public and a private key and use this key pair for each MTA. Keys can be generated locally or on one of the MTAs via SSH.

**Commands to generate keys:**

```shell theme={null}
# Install opendkim-tools
sudo apt install opendkim-tools
mkdir keys
cd keys
# Replace the example domain and the selector
opendkim-genkey -d example.com -b 2048 -r -s 202406
chmod 600 *.private
```

**Available flags**

| Flag | Description                                               |
| ---- | --------------------------------------------------------- |
| `-d` | Specifies the domain for which the key will be generated. |
| `-b` | Sets the length of the key (2048-bit is recommended).     |
| `-r` | Restricts the key usage to email signing only.            |
| `-s` | Defines the selector (recommended format: YYYYMM).        |

### Configure Opendkim

Once the keys are generated, you need to configure `opendkim` by creating six new files:

* `opendkim.local.conf`: General configuration.
* `signing.table`: Maps email domains to key IDs.
* `key.table`: Maps key IDs to domains and private keys.
* `trusted`: Lists trusted hosts whose emails should be signed.
* `*.private`: The private key used for signing.
* `*.txt`: DNS record containing the public key.

1. Go to the [Expert Editor](/latest/expert-editor) on xorlab
2. In `activeguard/mta/opendkim/`, create the folder: `local`
3. In `activeguard/mta/opendkim/local`, create the 6 configuration files
4. For each config file, copy/paste the content from the code blocks below
5. Adjust the parameters, if necessary.

**`activeguard/mta/opendkim/local/opendkim.local.conf`**

```text theme={null}
# signing (s) and verification (v)
Mode                    sv
 
# Identifies a set of "external" hosts that may send mail through
# the server as one of the signing domains without credentials as such
ExternalIgnoreList      refile:/etc/opendkim/local/trusted
# Identifies a set internal hosts whose mail should be signed rather than verified.
InternalHosts           refile:/etc/opendkim/local/trusted 
SigningTable            refile:/etc/opendkim/local/signing.table
KeyTable                /etc/opendkim/local/key.table      
SignatureAlgorithm      rsa-sha256
 
# Always oversign the From header (sign both the actual From and a null From) to prevent 
# the insertion of malicious headers between the sender and receiver. 
# The From header is oversigned by default in the Debian package because it is often 
# the key identity used by reputation systems and is therefore security-sensitive.
OversignHeaders         From
 
# Set only to false if opendkim complains about key permissions even though the
# are set to 600
RequireSafeKeys         true
```

### Signing table

**`activeguard/mta/opendkim/local/signing.table`**

```text theme={null}
# maps domain to key ID
*@xorlab.com xorlab
```

### Key table

<Warning>
  **Important**

  Do not alter the path in `key.table`.
</Warning>

**`activeguard/mta/opendkim/local/key.table`**

```text theme={null}
# maps key ID to domain, selector, and private key file
xorlab xorlab.com:202406:/etc/opendkim/keys/202406.private
```

### Trusted list

<Warning>
  **Important**

  Make sure that each IP and hostname of your internal infrastructure is included in the `trusted` file.
</Warning>

**`activeguard/mta/opendkim/local/trusted`**

```text theme={null}
# trusted should contain all IPs or hostnames of your servers from which mails should be 
# signed instead of verified
11.22.33.44

# CIDR support
10.0.0.0/8

# domains support
example.com
```

### DKIM record

**`activeguard/mta/opendkim/local/202406.txt`**

```text theme={null}
# DKIM DNS record,key is shortened for brevity
202406._domainkey    IN    TXT    ( "v=DKIM1; k=rsa; s=email; "
      "p=MIGfMA0GCS...IDAQAB" )  ; ----- DKIM key 202406 for xorlab.com
```

### Activate configurations

1. Connect to each MTA via SSH.
2. For each MTA, perform the following steps:
   1. Edit the file: `/etc/xorlab/activeguard/docker-compose.yml`
      * Go to `services`→ `mta` → `volumes`
      * Add the line `./mta/opendkim:/etc/opendkim/keys/`
   2. Create the folder: `/etc/xorlab/activeguard/mta/opendkim`
      * Copy your private key file into this folder
      * The name of the file must be the same as specified in the `key.table` file (Although the path is different).
   3. Set the permissions for the private key
      * Only opendkim process should access it (0600, with 2021:2021)
      * Use the following commands:
   ```bash theme={null}
   sudo chmod 0700 /etc/xorlab/activeguard/mta/opendkim
   sudo chmod 0600 /etc/xorlab/activeguard/mta/opendkim/*.private
   sudo chown -R 2021:2021 /etc/xorlab/activeguard/mta/opendkim
   ```
3. In the Expert Editor, click **Publish**. Then restart the MTAs so the new OpenDKIM configuration is loaded:
   * `cd /etc/xorlab/activeguard`
   * `docker compose down && docker compose up -d`

### Configuring DNS Records

To complete the DKIM setup, you must update the DNS TXT record for your domain. This record  can be found in the `.txt` file generated by `opendkim-tools`. It contains the public key and is used by receiving mail servers to verify your DKIM signatures.

```text theme={null}
dig +short TXT 20230601._domainkey.google.com
"v=DKIM1; k=rsa; p=MIIBIjANBgkq[...]DAQAB"
```

## DMARC Recommendations

DMARC Policies safeguard your domain against unauthorized use, like phishing or email spoofing.

DMARC uses DNS records to define how a receiving MTA should handle SPF and DKIM failures (`policy`), report these failures (`reporting`), and align the From (`5322.From`) with the Mail From (`Envelope From`, `5321.MailFrom`).

While your domain's DMARC policy doesn't affect the operation of the xorlab security platform, we strongly recommend configuring DMARC as part of good email security practices.

For more information, please refer to the following resources:

* [Wikipedia: DMARC](https://en.wikipedia.org/wiki/DMARC)
* [mxtoolbox: What is a DMARC DNS Record?](https://mxtoolbox.com/dmarc/details/what-is-a-dmarc-record)
* [RFC 7489](https://tools.ietf.org/html/rfc7489)

### DMARC tags

A text DMARC record consists of `name=value` tags, separated with semicolons.

| Tag Name | Description                                                                                                                                                                                                                                                                                                                                                                                                             | Comments                                                                                                                                                                             |
| :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `v`      | Protocol version                                                                                                                                                                                                                                                                                                                                                                                                        | **Required**<br />Value: `DMARC1`                                                                                                                                                    |
| `p`      | Policy                                                                                                                                                                                                                                                                                                                                                                                                                  | **Required**<br />Value: `none`, `quarantine`, `reject`<br />                                                                                                                        |
| `fo`     | Failure reporting options                                                                                                                                                                                                                                                                                                                                                                                               | Optional<br />Generate failure report when:<br />`0`: all evaluations fail (default)<br />`1`: any evaluation fails<br />`d`: DKIM evaluations fails<br />`s`: SPF evaluations fails |
| `pct`    | Percentage of messages from the Domain Owner’s mail stream to which the DMARC policy is to be applied                                                                                                                                                                                                                                                                                                                   | Optional<br />Value: an integer between `0` and `100` (default), inclusive                                                                                                           |
| `rf`     | Format to be used for message-specific failure reports                                                                                                                                                                                                                                                                                                                                                                  | Optional<br />Value: colon-separated plain-text list; default is [`AFRF`](https://tools.ietf.org/html/rfc6591)                                                                       |
| `ri`     | Interval in seconds requested between aggregate reports                                                                                                                                                                                                                                                                                                                                                                 | Optional<br />Value: plain-text 32-bit unsigned integer; default is `86400` (24h)                                                                                                    |
| `rua`    | Addresses to which aggregate feedback is to be sent                                                                                                                                                                                                                                                                                                                                                                     | Optional<br />Value: email address                                                                                                                                                   |
| `ruf`    | Addresses to which message-specific failure information is to be reported                                                                                                                                                                                                                                                                                                                                               | Optional<br />Value: email address                                                                                                                                                   |
| `sp`     | Requested Mail Receiver policy for all subdomains                                                                                                                                                                                                                                                                                                                                                                       | Optional<br />Value: see `p`                                                                                                                                                         |
| `aspf`   | SPF alignment. In **relaxed** mode, the SPF-authenticated domain and RFC5322.From domain must have the same Organizational Domain. In **strict** mode, only an exact DNS domain match is considered to produce Identifier Alignment                                                                                                                                                                                     | Optional<br />Value: `r` (relaxed; default), `s` (strict)                                                                                                                            |
| `adkim`  | DKIM alignment. In **relaxed** mode, the Organizational Domains of both the DKIM-authenticated signing domain (taken from the value of the `d=` tag in the signature) and that of the RFC5322.From domain must be equal if the identifiers are to be considered aligned. In **strict** mode, only an exact match between both of the Fully Qualified Domain Names (FQDNs) is considered to produce Identifier Alignment | Optional<br />Value: `r` (relaxed; default), `s` (strict)                                                                                                                            |

The descriptions in the table above are mostly direct quotations of [RFC 7489](https://tools.ietf.org/html/rfc7489)

### Examples

To observe:

```text theme={null}
# send aggregated feedback, but do not reject or quarantine emails
"v=DMARC1; p=none; pct=100; fo=s; rua=mailto:mailauth-reports@example.com;ruf=mailto:mailauth-reports@example.com;"
```

Reject:

```text theme={null}
# original Google setting, reject and report aggregated
v=DMARC1; p=reject; rua=mailto:mailauth-reports@google.com
```

In both examples, the DNS TXT record needs to be set for `_dmarc.example.com`.
