DNS server on Proxmox Mail Gateway
One of the most effective means to detecting spam currently is the use of DnsBlocklists. These lists are used to query the IP of the connecting SMTP server, or IPs and hostnames occurring in the mail body.
Some of the DNS Blocklists used by SpamAssassin (and thus also Proxmox Mail Gateway) allow only a certain number of requests per DNS server and don't respond once your DNS server has reached it's quota. This is reflected in the mail logs and SpamAssassin hits of a mail. If you see 'URIBL_BLOCKED', 'RCVD_IN_DNSWL_BLOCKED' or 'SURBL_BLOCKED' in your mail logs or the mail headers, this is an indication that your system has reached the quota.
If you're using a shared DNS server (e.g. your ISPs, or a publicly available one like 22.214.171.124, 126.96.36.199, 188.8.131.52) it is quite likely that the Mail Gateway's requests will be blocked.
Installing a dedicated DNS server on the Proxmox Mail Gateway can help in such situations.
Keep in mind that the DNS Blocklists can only count the requests per public IP, i.e. if you have both your internal DNS and Proxmox Mail Gateway natted to the same public IP setting up a recursive DNS server will not help.
If you keep reaching the limit despite having a dedicated recursive server for your Proxmox Mail Gateway you should consider getting a dedicated feed, which is provided by most DNS Blocklist providers for a fee. This also helps keeping this important infrastructure up and running.
We will use the Unbound recursive DNS server.
Installing and using unbound
apt install unbound dnsutils
to install the
unbound server - the
dnsutils package contains
dig, which can be used for testing.
Check that unbound is indeed listening on port 53:
# ss -tulnp | grep :53 udp UNCONN 0 0 127.0.0.1:53 0.0.0.0:* users:(("unbound",pid=137,fd=5)) udp UNCONN 0 0 [::1]:53 [::]:* users:(("unbound",pid=137,fd=3)) tcp LISTEN 0 128 127.0.0.1:53 0.0.0.0:* users:(("unbound",pid=137,fd=6)) tcp LISTEN 0 128 [::1]:53 [::]:* users:(("unbound",pid=137,fd=4))
You can verify that DNS resolution works by using the
# dig a proxmox.com @127.0.0.1 +short 184.108.40.206
Afterwards you need to configure your Proxmox Mail Gateway installation to use the local dns-server listening on
127.0.0.1 (or optionally
::1) as resolver.
In the following article we assume that your domain is
yourdomain.example - you need to adapt the posted configuration.
On a standard installation this is done by simply placing:
nameserver 127.0.0.1 search yourdomain.example
When Proxmox Mail Gateway is running as a Container on Proxmox VE, then you need to edit the container's DNS Settings to use
127.0.0.1 as DNS Server (and adapt your search domain to
If you have installed the resolvconf package you should not need to change everything, since the unbound package in Debian brings integration with
Should your system use
systemd-resolved make sure that
127.0.0.1 is listed as
Current DNS Server
Alternatively you can simply disable and stop the service
systemctl disable systemd-resolved systemctl stop systemd-resolved
After installing you can either reboot you Proxmox Mail Gateway, or restart the services relevant for mail-processing:
systemctl restart pmg-smtp-filter pmgpolicy postfix
Forwarding requests for your internal zone to your internal DNS
In some environments the internally used DNS has all knowledge about your domain, and should be consulted for it, instead of unbound getting the publicly available data via DNS delegation from the root-servers.
You can configure unbound to ask your internal DNS-server (for this example the internal DNS-server has the IP 192.0.2.53) for your internal domains (yourdomain.example and yourseconddomain.example).
Create a dedicated config-snippet
stub-zone: name: "yourdomain.example" stub-addr: 192.0.2.53
stub-zone: name: "yourseconddomain.example" stub-addr: 192.0.2.53
Afterwards restart unbound and verify that DNS-requests for yourdomain.example are delegated to 192.0.2.53 (by checking the DNS logs there):
systemctl restart unbound dig test.yourdomain.example @127.0.0.1
Optional: Using the local unbound only for DNS Blocklist requests
Should your environment require you to use an internal DNS server for all requests, because you have a very modified setup or are employing some other blocking for regulatory reasons you can also try to forward all other requests to your internal DNS Server and only ask the DNS Blocklist zones recursively.
This setup is not recommended for general use, since it increases the complexity which makes debugging harder.
In the example we will use recursive queries for the following domains and forward all other requests to 192.0.2.53:
The list is taken from the Spam Assassin Entry on DNS Blocklists.
You should enhance the list by all domains you are using in your setup (especially the one's configured for
Since unbound cannot do recursive lookups for specific zones if it is forwarding all other requests we will configure 2 unbound instances:
- one listening on port
5003for recursive lookups - the DNSBL instance
- one forwarding requests for the DNSBL domains to port 5003, and all other requests to your internal DNS Server.
For the DNSBL instance - create a config-file which does only include the necessary config-options
#unbound instance listening on port 5003 for DNSBL lookups include: "/etc/unbound/unbound.conf.d/qname-minimisation.conf" include: "/etc/unbound/unbound.conf.d/root-auto-trust-anchor-file.conf" port: 5003 remote-control: control-port: 8954
Additionally you need to create a systemd-unit (
[Unit] Description=Unbound DNS server for DNSBL lookups Documentation=man:unbound(8) After=network.target Before=nss-lookup.target Wants=nss-lookup.target
[Service] Type=simple Restart=on-failure EnvironmentFile=-/etc/default/unbound EnvironmentFile=-/etc/default/unbound-rbl ExecStartPre=-/usr/lib/unbound/package-helper chroot_setup ExecStartPre=-/usr/lib/unbound/package-helper root_trust_anchor_update ExecStart=/usr/sbin/unbound -c /etc/unbound/unbound-rbl.conf -d $DAEMON_OPTS ExecReload=/usr/sbin/unbound-control -c /etc/unbound/unbound-rbl.conf reload
and enable it with
systemctl enable unbound-rbl systemctl start unbound-rbl
For the instance listening on port 53 you need to create a config-snippet in
server: do-not-query-localhost: no # depending on your internal DNS-servers capabilities these options might be necessary # harden-dnssec-stripped: no # module-config: "iterator" forward-zone: name: "uceprotect.net" forward-addr: 127.0.0.1@5003 forward-zone: name: "mailspike.net" forward-addr: 127.0.0.1@5003 forward-zone: name: "sorbs.net" forward-addr: 127.0.0.1@5003 forward-zone: name: "bl.spamcop.net" forward-addr: 127.0.0.1@5003 forward-zone: name: "spamhaus.org" forward-addr: 127.0.0.1@5003 forward-zone: name: "surbl.org" forward-addr: 127.0.0.1@5003 forward-zone: name: "uribl.com" forward-addr: 127.0.0.1@5003 forward-zone: name: "dnswl.org" forward-addr: 127.0.0.1@5003 forward-zone: name: "." forward-addr: 192.0.2.53
Test the setup by doing lookups to:
- a testpoint of a DNSBL and verify that the query does not arrive at your internal server
- a testpoint of an arbitrary address (which should arrive at your internal server):
# dig any test.uribl.com.multi.uribl.com @127.0.0.1 +short # should not show up as query on 192.0.2.53 127.0.0.14 "permanent testpoint" # dig a proxmox.com @127.0.0.1 +short #should show up as query on 192.0.2.53 220.127.116.11