Forwarding Port 53 to an LXD container

(Мэтью Смит) #1

In case you are following, I have decided to nuke my server and start over (LXD proved to be the least of my problems following an ill-advised upgrade to Ubuntu 19.04) As such, I am using this as an opportunity to start from scratch. I like the idea of using the lxdbr0 and forwarding ports from the host to an lxd container. Ive created a container and installed PiHole. Pihole requires ports 53 and 80. I have set-up port forwarding as best I know how (ex. sudo lxc config device add PiHole DNSPort53 proxy listen=tcp: connect=tcp:localhost:53) and have been able to access port 80 within the container (the PiHole Admin GUI) but have been unable to successfully utilize port 53 within the container.

Does anyone know if this is even possible or is 53 “so baked in” to the host system that an request from outside the host to host:53 will be answered by host irrespective of LXD port forwarding rules?

Thank you!


port 53 has no sacred status, I use 2 Ubuntu 18.04 containers on 2 internet servers to manage an internet domain with bind.
I don’t use LXD proxy though, I have never taken the time to track how it’s done and if I don’t know how network magic is handled, I prefer to manage the network myself.

Ufw file 'before.rules'
# dns
-A PREROUTING -i $interface -p udp --dport 53 -j DNAT --to-destination $ipaddr
-A PREROUTING -i $interface -p tcp --dport 53 -j DNAT --to-destination $ipaddr

Ufw rules
sudo ufw route allow in on $interface to $ipaddr port 53 comment "from internet to DNS server"
sudo ufw route allow in on $interface to $ipaddr6 port 53 comment "from internet to DNS server"
sudo ufw route allow in on lxdbr0 out on $interface from $ipaddr to any port 53 comment "from DNS server to internet DNS servers"
sudo ufw route allow in on lxdbr0 out on $interface from $ipaddr6 to any port 53 comment "from DNS server to internet DNS servers"

The containers themselves are getting their internal address from the default LXD dnsmasq.
The 2 internet hosts are vanilla Ubuntu 16.04 with snap lxd and default systemd resolver.
all of this is working without any problem and the domain is green on all DNS checkers I tried it on.

(Мэтью Смит) #3

Thank you for the reply and suggestion. I’ll be honest, I’m not sure whats going on here and therefore I do know how to implement.

If you would be so kind, could you explain:

  1. How ufw knows to forward any knock on host:53 to PiHoleLXD:53? When I use lxdbr0, IP addresses are randomly assigned and not static
  2. when I attempt enter the UFW rules you supply verbatim, I get the following error:
    ERROR: Bad destination address
    I expected an error because to me the rule doesn’t tell UFW where to send the 53 request or where to listen for it (but I admit I don’t understand iptables as well as I should)

Thank you!

Oh, if it makes a difference, host is 19.04 server and containers are 18.04’s


the ‘forward’ from connections attempts on port 53 of the host is done through the prerouting rules in /etc/ufw/before.rules. The 4 following rules are to ensure that these exchanges are effectively authorized (these rules may not be necessary for you according to your default routing rules)

The rules I quoted are not to be taken as is, because your host interface and container IP address may be different of the ones I have on my system.
For the ufw rules you can set them in a script and add at the begining set interface=you_interface and so on. For the before.rules I’m afraid that you have to directly set the ip address and the interface name

And your container IP may be random with lxdbr0 bridge, but once it’s set it does not change again.

(Brian Mullan) #5

Unrelated question because I don’t use a pihole but why do you use sudo with the device proxy command … asking because on ubuntu I don’t and device proxy works ok.

Also is LXDs own dnsmasq still configured?

(Мэтью Смит) #6

First and foremost thank you for helping. I’ve done as you have suggested but have run into the following when trying to implement the new UFW “before” rules:

ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
ERROR: problem running ufw-init
iptables-restore: line 74 failed

Problem running '/etc/ufw/before.rules'

Here is my /etc/ufw/before.rules


Err, I think I left out a few details.
It’s necessary to add a specific section for NAT in the before.rules file.
Now, I don’t understand why your don’t have one since LXD setup add one such section for masquerading bridged adresses
But if you really have to add one, it should be something like that:

# NAT table rules
# Port Forwardings
# dns
-A PREROUTING -i enp2s0 --p udp --dport 53 -j DNAT --to-destination
-A PREROUTING -i enp2s0 -p tcp --dport 53 -j DNAT --to-destination
# general

# do not remove the 'COMMIT' line or these nat table rules won't
# be processed

and the rest of the file for normal forwarding rules.
But it’s strange that default LXD setup has not set something like that already at the beginning of the before.rules file…


As noted below, do not use sudo with any of the lxc commands.
For me, if I see sudo lxc, it is an indication that things will go wrong.
To avoid sudo, you add your non-root user account into the lxc Unix group.

A stock LXD container is already using port 53 (domain) for the local DNS server.
If you want to create a proxy device, you need to figure out how to disable the built-in systemd-resolved.

An LXD proxy device uses a process for each proxy device. If you run ps, you will see a forkproxy process for each connection. Compared to iptables, with a proxy device you get the easiness and integration. When you delete the container, the proxy device is gone as well.
With iptables though, it is all happening in the kernel. You should notice performance difference if you pass lots and lots of traffic.