Upload files to "deployments/services/email/Proxmox Mail Gateway"
Automatic Documentation Deployment / Sync Docs to https://kb.bunny-lab.io (push) Successful in 4s
Automatic Documentation Deployment / Sync Docs to https://kb.bunny-lab.io (push) Successful in 4s
This commit is contained in:
+315
@@ -0,0 +1,315 @@
|
|||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Mailcow
|
||||||
|
- Proxmox Mail Gateway
|
||||||
|
- SMTP
|
||||||
|
- Email
|
||||||
|
---
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
This workflow describes how to configure Mailcow to trust Proxmox Mail Gateway (PMG) as an upstream SMTP relay after PMG has been placed in front of Mailcow for inbound filtering. It prevents Mailcow from applying sender-domain validation and duplicate spam filtering to messages that PMG has already accepted, including messages released from the PMG quarantine.
|
||||||
|
|
||||||
|
In the current Bunny Lab design, this trust applies to the inbound delivery path from `192.168.3.15` to `192.168.3.61`. Mailcow continues to send outbound mail directly to the Internet and does not relay outbound mail through PMG.
|
||||||
|
|
||||||
|
!!! info "Assumptions"
|
||||||
|
- Mailcow is already deployed at `192.168.3.61`.
|
||||||
|
- PMG is already deployed at `192.168.3.15`.
|
||||||
|
- Public inbound SMTP port `25` is forwarded to PMG.
|
||||||
|
- PMG relays accepted inbound mail to Mailcow on `192.168.3.61:25`.
|
||||||
|
- Mailcow remains responsible for mailbox hosting, authenticated submission, DKIM signing, and outbound delivery.
|
||||||
|
- You have `root` access to the Mailcow host.
|
||||||
|
|
||||||
|
!!! warning "Trust Only the PMG Host"
|
||||||
|
Add only `192.168.3.15/32` to Mailcow's trusted networks. Do not trust the entire `192.168.3.0/24` subnet unless every system on that subnet is authorized to relay mail through Mailcow without authentication.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
```text
|
||||||
|
Internet
|
||||||
|
|
|
||||||
|
v
|
||||||
|
pfSense WAN :25
|
||||||
|
|
|
||||||
|
v
|
||||||
|
PMG 192.168.3.15:25
|
||||||
|
|
|
||||||
|
v
|
||||||
|
Mailcow 192.168.3.61:25
|
||||||
|
|
|
||||||
|
v
|
||||||
|
User Mailbox
|
||||||
|
```
|
||||||
|
|
||||||
|
PMG is the primary inbound spam and virus filtering authority. Mailcow should accept the SMTP session from PMG as a trusted relay and avoid repeating edge filtering or rejecting PMG-generated envelope senders.
|
||||||
|
|
||||||
|
## Symptoms
|
||||||
|
Use this workflow when PMG receives and processes mail correctly, but Mailcow rejects or defers the final delivery.
|
||||||
|
|
||||||
|
Common symptoms include:
|
||||||
|
|
||||||
|
- A released PMG quarantine message remains in the PMG deferred queue
|
||||||
|
- Clicking **Flush** in PMG does not deliver the message
|
||||||
|
- PMG repeatedly attempts delivery to `192.168.3.61:25`
|
||||||
|
- Mailcow rejects a PMG-generated envelope sender such as `postmaster@lab-mail-gw-01.bunny-lab.io`
|
||||||
|
- PMG reports an SMTP response similar to:
|
||||||
|
|
||||||
|
```text
|
||||||
|
450 4.1.8 Sender address rejected: Domain not found
|
||||||
|
```
|
||||||
|
|
||||||
|
The visible message sender may be valid even when Mailcow rejects the PMG-generated envelope sender used during quarantine release.
|
||||||
|
|
||||||
|
## Confirm the PMG Source Address
|
||||||
|
Mailcow must trust the source address it actually sees on the SMTP connection. Confirm that address before changing the configuration.
|
||||||
|
|
||||||
|
On the Mailcow host, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /opt/mailcow-dockerized
|
||||||
|
docker compose logs --since 5m postfix-mailcow
|
||||||
|
```
|
||||||
|
|
||||||
|
Flush or resend a test message from PMG, then locate the connection line.
|
||||||
|
|
||||||
|
Expected connection source:
|
||||||
|
|
||||||
|
```text
|
||||||
|
connect from lab-mail-gw-01[192.168.3.15]
|
||||||
|
```
|
||||||
|
|
||||||
|
If Mailcow sees a different address because of NAT, a load balancer, or another SMTP proxy, use that observed address instead of `192.168.3.15`.
|
||||||
|
|
||||||
|
## Configure Mailcow Forwarding Hosts
|
||||||
|
Configure PMG as a trusted forwarding host in the Mailcow WebUI.
|
||||||
|
|
||||||
|
- Navigate to "**System > Configuration > Options > Forwarding Hosts**"
|
||||||
|
- Add `192.168.3.15`
|
||||||
|
- Set the forwarding-host spam filter option to **Inactive**
|
||||||
|
- Save the configuration
|
||||||
|
|
||||||
|
!!! note "Forwarding Host Behavior"
|
||||||
|
The forwarding-host entry tells Mailcow that PMG is the immediate upstream SMTP relay. Keeping the forwarding-host spam filter inactive avoids applying a second aggressive spam-filtering layer to mail that PMG has already inspected.
|
||||||
|
|
||||||
|
## Configure Postfix Trusted Networks
|
||||||
|
The forwarding-host entry does not replace Postfix `mynetworks`. Add PMG to `mynetworks` so Postfix treats SMTP sessions from PMG as trusted and evaluates `permit_mynetworks` before sender-domain restrictions.
|
||||||
|
|
||||||
|
### Inspect the Active Configuration
|
||||||
|
On the Mailcow host, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /opt/mailcow-dockerized
|
||||||
|
docker compose exec postfix-mailcow postconf mynetworks
|
||||||
|
```
|
||||||
|
|
||||||
|
The validated Bunny Lab configuration is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
|
||||||
|
```
|
||||||
|
|
||||||
|
Preserve every existing loopback and Mailcow Docker network. The PMG address must be appended as a single-host CIDR.
|
||||||
|
|
||||||
|
### Update the Persistent Postfix Override
|
||||||
|
Edit the Mailcow Postfix override file:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nano /opt/mailcow-dockerized/data/conf/postfix/extra.cf
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the complete `mynetworks` value:
|
||||||
|
|
||||||
|
```ini title="/opt/mailcow-dockerized/data/conf/postfix/extra.cf"
|
||||||
|
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! warning "Preserve Existing Networks"
|
||||||
|
Defining `mynetworks` replaces the automatically derived value. Do not remove `127.0.0.0/8`, `172.22.1.0/24`, or `[::1]/128` from the validated Bunny Lab configuration.
|
||||||
|
|
||||||
|
### Restart Mailcow Postfix
|
||||||
|
Apply the persistent override:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /opt/mailcow-dockerized
|
||||||
|
docker compose restart postfix-mailcow
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validate the Trusted Relay Configuration
|
||||||
|
Confirm the active Postfix configuration after the restart:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /opt/mailcow-dockerized
|
||||||
|
docker compose exec postfix-mailcow postconf mynetworks
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected result:
|
||||||
|
|
||||||
|
```text
|
||||||
|
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirm the active SMTP restriction order includes `permit_mynetworks`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /opt/mailcow-dockerized
|
||||||
|
docker compose exec postfix-mailcow postconf \
|
||||||
|
smtpd_sender_restrictions \
|
||||||
|
smtpd_recipient_restrictions \
|
||||||
|
smtpd_relay_restrictions
|
||||||
|
```
|
||||||
|
|
||||||
|
The exact restriction lists may change between Mailcow releases. Confirm that `permit_mynetworks` remains present and that the effective configuration recognizes `192.168.3.15/32` as trusted.
|
||||||
|
|
||||||
|
## Retry Deferred PMG Mail
|
||||||
|
After Mailcow trusts PMG, retry the deferred message from the PMG WebUI.
|
||||||
|
|
||||||
|
- Navigate to "**Administration > Queue Administration > Deferred Mail**"
|
||||||
|
- Select the deferred message
|
||||||
|
- Click **Flush**
|
||||||
|
|
||||||
|
Alternatively, run the following on PMG:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
postqueue -f
|
||||||
|
```
|
||||||
|
|
||||||
|
To retry one specific queue item:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
postsuper -r <QUEUE_ID>
|
||||||
|
postqueue -f
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validate Mail Delivery
|
||||||
|
Monitor Mailcow while PMG retries the message:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /opt/mailcow-dockerized
|
||||||
|
docker compose logs -f postfix-mailcow
|
||||||
|
```
|
||||||
|
|
||||||
|
Mailcow should accept the SMTP transaction and return a successful queue response similar to:
|
||||||
|
|
||||||
|
```text
|
||||||
|
250 2.0.0 Ok: queued as <MAILCOW_QUEUE_ID>
|
||||||
|
```
|
||||||
|
|
||||||
|
On PMG, confirm the deferred queue no longer contains the message:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
postqueue -p
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirm the message is present in the destination Mailcow mailbox.
|
||||||
|
|
||||||
|
!!! success "Trusted PMG Delivery Confirmed"
|
||||||
|
The workflow is complete when Mailcow accepts mail from `192.168.3.15`, the PMG deferred queue clears, and the destination mailbox receives the message.
|
||||||
|
|
||||||
|
## Security Boundaries
|
||||||
|
Adding `192.168.3.15/32` to `mynetworks` permits PMG to relay mail through Mailcow without SMTP authentication. This is appropriate only while PMG remains a controlled gateway host.
|
||||||
|
|
||||||
|
Maintain the following boundaries:
|
||||||
|
|
||||||
|
- Restrict the trusted entry to `192.168.3.15/32`
|
||||||
|
- Prevent other hosts from impersonating the PMG source address
|
||||||
|
- Keep Mailcow port `25` restricted to expected SMTP sources where practical
|
||||||
|
- Confirm PMG is not configured as an unrestricted open relay
|
||||||
|
- Continue routing authenticated client submission directly to Mailcow on ports `465` and `587`
|
||||||
|
- Continue routing public inbound SMTP port `25` to PMG rather than directly to Mailcow
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
### Mailcow Still Returns `450 4.1.8`
|
||||||
|
Confirm Mailcow is using the updated configuration:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /opt/mailcow-dockerized
|
||||||
|
docker compose exec postfix-mailcow postconf mynetworks
|
||||||
|
```
|
||||||
|
|
||||||
|
If `192.168.3.15/32` is missing, verify `/opt/mailcow-dockerized/data/conf/postfix/extra.cf` and restart `postfix-mailcow`.
|
||||||
|
|
||||||
|
### Mailcow Sees a Different Source Address
|
||||||
|
Inspect the Mailcow Postfix logs:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /opt/mailcow-dockerized
|
||||||
|
docker compose logs --since 5m postfix-mailcow
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the IP address shown in the `connect from ...[IP_ADDRESS]` line. Do not assume Mailcow sees the PMG management address when NAT or an SMTP proxy exists between the systems.
|
||||||
|
|
||||||
|
### PMG Flushes the Message but the Mailbox Does Not Receive It
|
||||||
|
Determine whether Mailcow accepted the message.
|
||||||
|
|
||||||
|
If Mailcow returned `250 2.0.0`, the PMG-to-Mailcow relay succeeded. Continue troubleshooting inside Mailcow by reviewing Postfix, Rspamd, and Dovecot logs.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /opt/mailcow-dockerized
|
||||||
|
docker compose logs --since 10m postfix-mailcow rspamd-mailcow dovecot-mailcow
|
||||||
|
```
|
||||||
|
|
||||||
|
If Mailcow returned a `4xx` or `5xx` response, use the complete SMTP response as the controlling error and resolve that policy or recipient failure before retrying again.
|
||||||
|
|
||||||
|
### Mailcow Applies Spam Filtering Again
|
||||||
|
Confirm the PMG entry under "**System > Configuration > Options > Forwarding Hosts**" has its spam filter set to **Inactive**.
|
||||||
|
|
||||||
|
PMG should remain the primary inbound filtering authority in this deployment.
|
||||||
|
|
||||||
|
### Mail Clients or Outbound Delivery Stop Working
|
||||||
|
This workflow does not change client access or outbound delivery.
|
||||||
|
|
||||||
|
Confirm the existing service ownership remains:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Inbound SMTP: Internet -> PMG -> Mailcow
|
||||||
|
Outbound SMTP: Mailcow -> Internet
|
||||||
|
SMTP Submission: Clients -> Mailcow
|
||||||
|
IMAP and POP3: Clients -> Mailcow
|
||||||
|
Webmail and Admin: Internet -> Traefik -> Mailcow
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not redirect ports `465`, `587`, `993`, `995`, `110`, `143`, or `4190` to PMG.
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
Remove the PMG forwarding-host entry from the Mailcow WebUI only when PMG is no longer the upstream SMTP gateway.
|
||||||
|
|
||||||
|
Then edit:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nano /opt/mailcow-dockerized/data/conf/postfix/extra.cf
|
||||||
|
```
|
||||||
|
|
||||||
|
Restore the previous `mynetworks` value:
|
||||||
|
|
||||||
|
```ini title="/opt/mailcow-dockerized/data/conf/postfix/extra.cf"
|
||||||
|
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart Postfix:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd /opt/mailcow-dockerized
|
||||||
|
docker compose restart postfix-mailcow
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! warning "Coordinate the SMTP Path Before Rollback"
|
||||||
|
Do not remove PMG trust while public inbound SMTP still routes through PMG. Mailcow may begin rejecting legitimate messages relayed from PMG.
|
||||||
|
|
||||||
|
## Confirmed Final State
|
||||||
|
The validated Bunny Lab configuration is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
PMG Address: 192.168.3.15
|
||||||
|
Mailcow Address: 192.168.3.61
|
||||||
|
Mailcow Forwarder: 192.168.3.15
|
||||||
|
Forwarder Spam Check: Inactive
|
||||||
|
Postfix mynetworks: 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulting mail flow is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Inbound SMTP:
|
||||||
|
Internet -> pfSense WAN :25 -> PMG 192.168.3.15:25 -> Mailcow 192.168.3.61:25
|
||||||
|
|
||||||
|
Outbound SMTP:
|
||||||
|
Mailcow -> Internet
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user