Harden my pi running pihole? (install ufw)

I have been running pihole for some time on my pi zero and it works great. I've learned a lot since my humble beginnings and want to harden the security on my pi. I want to install Uncomplicated Firewall (ufw) and use it to secure the pi.

My concern is I will somehow break my pihole and hence want to post this message to ensure I am doing things correctly. Since the pihole runs dns and dhcp for my network its crucial I don't break it.

Expected Behaviour:

My intent is to start with denying all connections, then open just what I need.

  1. Start by installing Uncomplicated Firewall UFW
    sudo ufw: apt-get install ufw

  2. Deny all connections.
    ufw default deny incoming

  3. Restrict SSH to my local network
    ufw allow from xxx.yyy.zzz.0/24 to any port 22 proto tcp

  4. Open DNS port 53 to my local network
    ufw allow from xxx.yyy.zzz.0/24 to any port 53 proto tcp

  5. Open DNS port 53 to the internet
    ufw allow from any to any port 53 proto tcp

  6. Enable firewall
    ufw enable

Effectively, this should only allow SSH from my local network and open up DNS port 53 for my local network and the internet. If I do this, will it break the pi? Does the pihole need add'l ports to function properly?

Thank you.

Actual Behaviour:

Not yet implemented.

Debug Token:

Not yet implemented so not applicable.

1 Like

You should not open up the DNS port to the internet! If you have a rearson to access the Pi-hole from outside your network, you should use a VPN instead.

If you're using Pi-hole for DHCP you might need to allow port 67 (maybe 68 too). You should also make sure that localhost can access port 4711 so that things can connect to FTL.

1 Like

Thank you Mcat12 for your prompt reply.

So this modified setup should work ok. Note, I am using the pihole DCHP server

  1. Start by installing Uncomplicated Firewall UFW
    sudo ufw: apt-get install ufw

  2. Deny all connections.
    ufw default deny incoming

  3. Restrict SSH to my local network
    ufw allow from xxx.yyy.zzz.0/24 to any port 22 proto tcp

  4. I'm using DHCP so open port 67 to my local network and internet.
    ufw allow from xxx.yyy.zzz.0/24 to any port 67 proto tcp
    ufw allow from any to any port 67 proto tcp

  5. (a) Maybe this also for port 68
    ufw allow from xxx.yyy.zzz.0/24 to any port 68 proto tcp
    ufw allow from any to any port 68 proto tcp

  6. Open port 4711 so FTL can connect
    ufw allow from xxx.yyy.zzz.0/24 to any port 4711 proto tcp
    ufw allow from any to any port 4711 proto tcp

You shouldn't be opening DHCP to the internet either. Why would the internet want to be assigned an IP from your local DHCP server? Also, you need to open up DNS to the local network.

1 Like

Thanks. How does this look?

1. Start by installing Uncomplicated Firewall UFW
sudo ufw: apt-get install ufw

2. Deny all connections.
ufw default deny incoming

3. Restrict SSH to my local network only
ufw allow from xxx.yyy.zzz.0/24 to any port 22 proto tcp

4. Open DNS port 53 on local network only
ufw allow from xxx.yyy.zzz.0/24 to any port 53 proto tcp

5. I'm using DHCP so open port 67 on my local network only
ufw allow from xxx.yyy.zzz.0/24 to any port 67 proto tcp
Maybe this also: ufw allow from xxx.yyy.zzz.0/24 to any port 68 proto tcp

6. Open port 4711 so FTL can connect (local network only)
ufw allow from xxx.yyy.zzz.0/24 to any port 4711 proto tcp

3 Likes

That looks good. That being said, I've never used UFW :wink:

Thank you.

If you have time, please check it out.
https://wiki.ubuntu.com/UncomplicatedFirewall

Below one gives you a nice overview of all the daemons that are listening on particular ports:

sudo netstat -nltup

As you can see from below line:

udp 0 0 0.0.0.0:67 0.0.0.0:* 19335/dnsmasq

Its not 67 TCP that needs opening up but 67 UDP.

EDIT: I believe you dont need port 68.
I believe that one is used if Pi-hole were setup to acquire IP through DHCP.

Ohw, and I believe you need to open up DHCP to all 0.0.0.0 as when a client does the request for the first time, it doesnt have an IP address yet :wink:

Ohw2, and for DNS, you should open up 53 UDP too.
Both 53 TCP and UDP will work but UDP is supposed to be a little bit faster if have large volume of DNS requests.
But never ever open this one up to the public internet as it will be found and abused for amplification attacks.

It's been 3 years since this topic was active, and I've decided to make a final reply so everyone else can get the final steps based on the comprehensive analysis by deHakkelaar.

I have also added in some of my own tweaks as listed below:

  • Allow Port 80/TCP from the Local Area Network. This is required if you want to access Pi-Hole's lighttpd Web Admin Dashboard.
  • Set UFW's default policies (Deny incoming connections, allow outgoing connections)
  • Changed xxx.yyy.zzz.0/24 to 192.168.1.0/24 to cater to novices. You might need to change this based on your own network configuration i.e. 10.0.0.0/24



THE STEPS:

1. Start by installing Uncomplicated Firewall (UFW)

sudo apt install ufw

2. Set UFW default policies (Deny In, Allow Out)

sudo ufw default deny incoming
sudo ufw default allow outgoing

3. Open SSH port to the local network only

sudo ufw allow from 192.168.1.0/24 to any port 22 proto tcp

4. Open Pi-Hole's Web Dashboard (Port 80 by default) to the local network only

sudo ufw allow from 192.168.1.0/24 to any port 80 proto tcp

5. Open Pi-Hole's DNS (Port 53) to the local network only

sudo ufw allow from 192.168.1.0/24 to any port 53 proto udp

6. Open Pi-Hole's DHCP (Port 67) to the local network only
Note: Only do this if you are using Pi-Hole's DHCP server

sudo ufw allow from 0.0.0.0 to any port 67 proto udp

7. Open Port 4711 for Pi-Hole's FTL (from localhost only)

sudo ufw allow from 127.0.0.1 to any port 4711 proto tcp

8. Enable/reload UFW

sudo ufw enable

or

sudo ufw reload

I believe that's all. Let me know if you catch anything else thx. :grin:

You could also add 53 TCP as well for fallback.
You can query DNS via UDP as well as TCP:

pi@ph5:~ $ dig +short pi.hole @localhost
10.0.0.4

pi@ph5:~ $ dig +short +tcp pi.hole @localhost
10.0.0.4

Could also allow the whole 127.0.0.0/8 subnet for the API eg:

sudo ufw allow from 127.0.0.0/8 to any port 4711 proto tcp

See below:

pi@ph5:~ $ ip -br -4 a s lo
lo               UNKNOWN        127.0.0.1/8

This is both more restrictive as well as still lacking coverage for some required ports when compared to Pi-hole's prerequisites firewall section, and it seems to cover IPv4 only.

Your 192.168.1.0/24 is specific to your network and may have to be adopted by others.
To avoid this, I guess you could instead cater for the generic private address ranges, which should always work:

192.168.0.0/16
172.16.0.0/12
10.0.0.0/8
fd00::/8
fe80::/10

Yet depending on your goals for your specific network, that may still be viewed as too permissive / too restrictive.

I see, but from the documentations, it's stated that

FTL is our API engine and uses port 4711 on the localhost interface. This port should not be accessible from any other interface.

so I would assume that it's safer to limit our firewall's permissiveness to reduce the possible attack surface?

However, thanks to reply@Bucking_Horn I've been made aware of Pi-Hole's required ports documentation and realized that we should probably allow all ports ranging from 4711-4720? So our new command would look like this:

sudo ufw allow from 127.0.0.1 to any port 4711:4720 proto tcp

Did I get it right?

Addressing Bucking_Horn's reply, I have made some changes based on Pi-Hole's documentations.

Notes:

  • This configuration will only work for IPv4 networks only.
  • You might need to change the network range - 192.168.0.0/16 to suit your own network.

THE STEPS:

1. Start by installing Uncomplicated Firewall (UFW)

sudo apt install ufw

2. Set UFW default policies (Deny In, Allow Out)

sudo ufw default deny incoming
sudo ufw default allow outgoing

3. Open SSH port to the local network only

sudo ufw allow from 192.168.0.0/16 to any port 22 proto tcp

4. Open Pi-Hole's Web Dashboard (Port 80 by default) to the local network only

sudo ufw allow from 192.168.0.0/16 to any port 80 proto tcp

5. Open Pi-Hole's DNS (Port 53) to the local network only

sudo ufw allow from 192.168.0.0/16 to any port 53 proto tcp
sudo ufw allow from 192.168.0.0/16 to any port 53 proto udp

6. Open Pi-Hole's DHCP server (IPV4: 67) (IPV6: 547)
Note: Only do this if you are using Pi-Hole's DHCP server

sudo ufw allow from 0.0.0.0 to any port 67 proto udp

7. Open Port 4711 for Pi-Hole's FTL (from localhost only)

sudo ufw allow from 127.0.0.1 to any port 4711 proto tcp

8. Enable/reload UFW

sudo ufw enable

or

sudo ufw reload



Additional comments:

I've noticed that the firewall docs for UFW doesn't restrict connections to just the local network. I guess this would be fine if you don't port forward from your router but in my opinion, hardening a firewall would be to set more definitive rules in place I guess?

Oh and one more thing, does anyone know why pihole-FTL's ports 4711-4720 is not explicitly allowed in the UFW docs?

The "localhost interface" on most Linux distro's is named "lo":

pi@ph5:~ $ ip -br -4 address show lo
lo               UNKNOWN        127.0.0.1/8

And I believe those 127.0.0.0/8 addresses cant exist/wont work on the regular interfaces for host to host networking.
See below:

If want to post generic firewall rules to cater for everyone, like Bucking_Horn suggested, I would allow the whole IPv4 127.0.0.0/8 subnet + IPv6 ::1 .

We only use 4711, there is no auto-ranging anymore.

Edit:

2 Likes

Yep I think you're right. We should probably allow the entire 127.0.0.0/8 subnet. Either that, or we could write a ufw rule to allow all connections to port 4711 from the loopback interface?

sudo ufw allow in on lo to any port 4711 proto tcp

This rule even works for IPV6 networks.


Speaking of that, I don't think adding IPV6 rules would be necessary for now because most home users only use IPV4 networks. Furthermore, all ufw rules that I had written previously is very specific to IPV4 networks i.e.

sudo ufw allow from 192.168.0.0/16 to any port 22 proto tcp

is IPV4 only.


I don't think we'll be able to cater to IPV6 users too all in one post cuz if we do that, this post might get so long that it deserves to be an independent wiki :rofl:

Besides, I don't have much experience with IPV6 subnet notations so I'm a newb at hardening IPV6 networks.

Based on deHakkelaar's reply, I've added a rule for the entire loopback subnet.

Notes:

  • This configuration will only work for IPv4 networks only.
  • You might need to change the network range - 192.168.0.0/16 to suit your own network.

THE STEPS:

1. Start by installing Uncomplicated Firewall (UFW)

sudo apt install ufw

2. Set UFW default policies (Deny In, Allow Out)

sudo ufw default deny incoming
sudo ufw default allow outgoing

3. Open SSH port to the local network only

sudo ufw allow from 192.168.0.0/16 to any port 22 proto tcp

4. Open Pi-Hole's Web Dashboard (Port 80 by default) to the local network only

sudo ufw allow from 192.168.0.0/16 to any port 80 proto tcp

5. Open Pi-Hole's DNS (Port 53) to the local network only

sudo ufw allow from 192.168.0.0/16 to any port 53 proto tcp
sudo ufw allow from 192.168.0.0/16 to any port 53 proto udp

6. Open Pi-Hole's DHCP server (IPV4: 67) (IPV6: 547)
Note: Only do this if you are using Pi-Hole's DHCP server

sudo ufw allow from 0.0.0.0 to any port 67 proto udp

7. Open Port 4711 for Pi-Hole's FTL (from localhost only)

sudo ufw allow from 127.0.0.0/8 to any port 4711 proto tcp

8. Enable/reload UFW

sudo ufw enable

or

sudo ufw reload

are the ufw rules in this article https://docs.pi-hole.net/main/prerequisites/#ufw up to date ? The SSH port isnt even mentioned... someone could update the ufw part in the prerequisites.. Also what about the Port 4711 ?

Why should SSH or 4711 be added?

well u are right the ssh port is not necessary at all but still could be mentioned.

i just thought of this:

sudo ufw allow from 127.0.0.0/8 to any port 4711 proto tcp

isn't it necessary to allow it for the localhost?