Bind outbound SMTP to a specific network
Advice not extensively tested
This configuration advice is a community contribution which has only been verified as a solution when using network: host
, where you have direct access to the host interfaces.
It may be applicable in other network modes if the container has control of the outbound IPs to bind to. This is not the case with bridge networks that typically bind to a private range network for containers which are bridged to a public interface via Docker.
If your Docker host is running multiple IPv4 and IPv6 IP-addresses, it may be beneficial to bind outgoing SMTP connections to specific IP-address / interface.
- When a mail is sent outbound from DMS, it greets the MTA it is connecting to with a EHLO (DMS FQDN) which might be verified against the IP resolved, and that a
PTR
record for that IP resolves an address back to the same IP. - A similar check with SPF can be against the envelope-sender address which may verify a DNS record like MX / A is valid (or a similar restriction check from an MTA like Postfix has with
reject_unknown_sender
). - If the IP address is inconsistent for those connections from DMS, these DNS checks are likely to fail.
This can be configured by overriding the default Postfix configurations DMS provides. Create postfix-master.cf
and postfix-main.cf
files for your config volume (docker-data/dms/config
).
In postfix-main.cf
you'll have to set the smtp_bind_address
and smtp_bind_address6
to the respective IP-address on the server you want to use.
Example
smtp_bind_address = 198.51.100.42
smtp_bind_address6 = 2001:DB8::42
Inheriting the bind from main.cf
can misconfigure services
One problem when setting smtp_bind_address
in main.cf
is that it will be inherited by any services in master.cf
that extend the smtp
transport. One of these is smtp-amavis
, which is explicitly configured to listen / connect via loopback (localhost / 127.0.0.1
).
A postfix-master.cf
override can workaround that issue by ensuring smtp-amavis
binds to the expected internal IP:
smtp-amavis/unix/smtp_bind_address=127.0.0.1
smtp-amavis/unix/smtp_bind_address6=::1
A potentially better solution might be to instead explicitly set the smtp_bind_address
override on the smtp
transport service:
smtp/inet/smtp_bind_address = 198.51.100.42
smtp/inet/smtp_bind_address6 = 2001:DB8::42
If that avoids the concern with smtp-amavis
, you may still need to additionally override for the relay
transport as well if you have configured DMS to relay mail.
When your DMS container is using a bridge network, you'll instead need to restrict which IP address inbound and outbound traffic is routed through via the bridged interface.
For inbound traffic, you may configure this at whatever scope is most appropriate for you:
- Daemon: Change the default bind address configured in
/etc/docker/daemon.json
(default0.0.0.0
) - Network: Assign the
host_binding_ipv4
bridge driver option as shown in the belowcompose.yaml
snippet. - Container: Provide an explicit host IP address when publishing a port.
For outbound traffic, the bridge network will use the default route. You can change this by either:
- Manually routing networks on the host.
- Use the
host_ipv4
driver option for Docker networks to force the SNAT (source IP) that the bridged network will route outbound traffic through.- This IP address must belong to a network interface to be routed through it.
- IPv6 support via
host_ipv6
requires at least Docker v25.
Here is a compose.yaml
snippet that applies the inbound + outbound settings to the default bridge network Docker Compose creates (if it already exists, you will need to ensure it's re-created to apply the updated settings):
networks:
default:
driver_opts:
# Inbound IP (sets the host IP that published ports receive traffic from):
com.docker.network.bridge.host_binding_ipv4: 198.51.100.42
# Outbound IP (sets the host IP that external hosts will receive connections from):
com.docker.network.host_ipv4: 198.51.100.42
IP addresses for documentation
IP addresses shown in above examples (198.51.100.42
+ 2001:DB8::42
) are placeholders, they are IP addresses reserved for documentation by IANA (RFC-5737 (IPv4) and RFC-3849 (IPv6)). Replace them with the IP addresses you want DMS to send mail through.