A Quick and Dirty DNS server using FreeBSD ( #100DaysToOffload Day 28)
In today's post i'm going to show you how to setup up something i should have done a long time ago. Knowing now how easy it could be. What is this thing? Setting up a in-home DHCP/DNS server. At first i was just looking for a DNS server thinking like a Pi-Hole but i knew i wanted to use FreeBSD as the OS. I want to use BSD's more mainly just to learn about them not because i think they are better(yet). FreeBSD is my choice simply because i've had the best experience with it. This would work from any of the BSD's but some step might differ a little. So Looking around i found out that the “Pi-Hole” only runs on linux. Looking a little further i found out that a Pi-Hole really is just a DNS server plus a block list. Doing this also means i don't have to maintain a host file on each device i own.
Enter dnsmasq
This little piece of software is just what i was looking for. Plus it's also a DHCP and TFTP server. And it's native to BSD's(It can also be found on linux).
The setup was quite easy. I am using a Raspberry Pi Model B rev 2(A second one i had laying around) for now but this is going to be upgraded to something else as it does struggle a little. But it is very usable and any slow downs are only noticeable when the TTL of the DNS record expires.
So step one was to flash the SD card with the FreeBSD image this i did using dd from my linux PC
dd if=FreeBSD-12.1-RELEASE-arm-armv6-RPI-B.img of=/dev/sdX
Pop that in the Pi and boot it up. I always do the initial Pi boot up with it connected to a display just in case something goes wrong and plus then i don't have to try and look at DHCP lease tables to find out what the IP address of it is.
After initial boot next task should be to change the default password(s) for root account and freebsd account. You can do that using the same passwd
command as on linux.
Next you really should set a static IP on any server and also set a hostname to do that on FreeBSD you edit /etc/rc.conf
and add these lines
hostname="hyperion"
ifconfig_ue0="inet 192.168.2.6 netmask 255.255.255.0"
defaultrouter="192.168.2.1"
ue0 above is the name of the network interface. This could be different on your system. You can find the interface name using the ifconfig
command.
Now i know i could have these changes take effect with a few command but i always reboot when making changes like this.
What i always do next is somewhat optional but HIGHLY recommended. Make SSH use public key authentication. I'll assume you know how to do this and move onto the setup of the actual DHCP/DNS server. At this point i would also disconnect the Pi from the display, Place it in it's final resting place and do the rest of the setup over SSH.
The only package we need to install is dnsmasq
pkg install dnsmasq
Once that is installed it's a matter of configuring it. dnsmasq is a caching DNS server by default but can also be a DHCP and TFTP server. I decided to also use it as the DHCP server on my network to ensure that all clients use it as DNS server. dnsmasq parses /etc/hosts and turns those into DNS records/responses.
Here is my config
# Never forward plain names (without a dot or domain part)
domain-needed
# Never forward addresses in the non-routed address spaces.
bogus-priv
no-resolv
server=9.9.9.10
server=149.112.112.10
dhcp-range=192.168.2.20,192.168.2.150,24h
dhcp-option=3,192.168.2.1
dhcp-authoritative
# Send microsoft-specific option to tell windows to release the DHCP lease
# when it shuts down. Note the "i" flag, to tell dnsmasq to send the
# value as a four-byte integer - that's what microsoft wants. See
# http://technet2.microsoft.com/WindowsServer/en/library/a70f1bb7-d2d4-49f0-96d6-4b7414ecfaae1033.mspx?mfr=true
dhcp-option=vendor:MSFT,2,1i
cache-size=300
conf-dir=/usr/local/etc/dnsmasq.d
# If a DHCP client claims that its name is "wpad", ignore that.
# This fixes a security hole. see CERT Vulnerability VU#598349
dhcp-name-match=set:wpad-ignore,wpad
dhcp-ignore-names=tag:wpad-ignore
# Always allocate the host with Ethernet address 11:22:33:44:55:66
# The IP address 192.168.0.60
#dhcp-host=11:22:33:44:55:66,192.168.0.60
# If this line is uncommented, dnsmasq will read /etc/ethers and act
# on the ethernet-address/IP pairs found there just as if they had
# been given as --dhcp-host options. Useful if you keep
# MAC-address/host mappings there for other purposes.
#read-ethers
Most of those options are explained or self-explanatory so i'll explain the less obvious ones.
no-resolv
by default dnsmasq gets it's list of upstream dns servers to pass onto clients by reading /etc/resolv.conf this disables that and makes it get it's upstream server from it's own config file.
server=9.9.9.10
server=149.112.112.10
These are the 2 upstream DNS server i use. They are provided by Quad9. These are the unsecured non-blocking servers as i will supply my own blocking list.
So then in /etc/resolve.conf
you just need to have
nameserver 127.0.0.1
and then disable resolvconf by creating /etc/resolvconf.conf
with the following content
resolvconf=NO
dhcp-option=3,192.168.2.1
this sets DHCP option 3(Default gateway) for all clients to 192.168.2.1
dhcp-authoritative
This makes dnsmasq forcefully become the only DHCP server on the network so it will takeover leases from other servers(if i understand that correctly)
I've left the addresses reservation lines because i may use them someday.
conf-dir=/usr/local/etc/dnsmasq.d
this makes dnsmasq parse all files under that folder
in that folder i have the block list found here
This list get updated everyday and is a large list blocking AD and malware domains.
So with that all in place all that is left to do is to enable/start the service
To enable add this to /etc/rc.conf
dnsmasq_enable="YES"
Then to start it right now
service dnsmasq start
That's it the server is now running and will answer DHCP and DNS requests. Any clients you have set with static network configurations you will need to update the DNS server on those to point to this newly setup server.
The other thing i did was create a small script to update the block list everyday and restart dnsmasq.
#!/usr/local/bin/bash
wget -O /usr/local/etc/dnsmasq.d/dnsmasq.blacklist.txt https://raw.githubusercontent.com/notracking/hosts-blocklists/master/dnsmasq/dnsmasq.blacklist.txt
service dnsmasq restart
and add that to /etc/crontab
0 1 * * * root /root/upblocklist.sh >/dev/null 2>&1
I have that set to go at 1AM every day as the blocklist repo is updated right around 12am in my time zone. You'll have to adjust this so you grab it after it's been updated.
And that is it. Like i said the Pi model B is not the best deivce to do this with. I think anything more recent with more than 1 CPU core would work just fine. My plan is to get a Rock64.
Well i hope this post was helpful to someone.
Until next time Stay safe!
Until next time. Stay safe!