Home software-development PowerDNS filtering + VPN

PowerDNS filtering + VPN

by Tomasz Jarosik


I wanted to have few goals met when connecting to my VPN:
1. Devices connected to VPN must use custom DNS server
2. Some kind of filtering must be available to exclude malicious domains
3. Custom domains must be easily configurable, e.g. jenkins.jarosik.vpn

Building blocks

PowerDNS Authoritative server

First, we have to have a authoritative DNS server running, which will allow us to set up custom domains. We can follow setup for PowerDNS and run it on port 5300. Then, install and configure PowerDNS-admin to achieve something similar to the screenshot below. It’s all we to do to have custom domains. But we need more pieces to access the internet, as our current DNS server knows only about our custom domains. This is why we need PowerDNS’s Recursor server.


Recursor is a DNS server which goes first to root DNS servers to find an answer to a DNS query. Let’s run it on and port 53. And by itself (with default configuration) it will resolve all internet domains, but not our custom domains. Because of that, we must somehow configure it together with the Authoritative server. Fortunately, all we need to do is to add simple change to /etc/powerdns/recursor.conf:


The Recursor is running on port 53, Authoritative server is running on localhost:5300. Query to Recursor on port 53 will resolve both: internet and custom domains.

root@prod-nvme-dns:~# dig @localhost +noall +answer jenkins.jarosik.vpn
jenkins.jarosik.vpn.	3520	IN	A
root@prod-nvme-dns:~# dig @localhost +noall +answer www.google.com
www.google.com.		170	IN	A


Now let’s add some filtering. There are many sources online for phishing or malicious domains, usually in the format <ip> <domain> to be included in /etc/hosts file. To try that from Recursor, we can use export-etc-hosts=on in the recursor.conf file. However, if you want to include thousands of domains, the Recursor will be slow to restart / respond. To make the Recursor efficient, we can use lua script by specifying it in recursor.conf:


The lua script is provided below (based on this source: https://blog.powerdns.com/2016/01/19/efficient-optional-filtering-of-domains-in-recursor-4-0-0/

full_list_13-11-2019.lua in my case contains array of over 700k domains and the Recursor works fine. Remember, that the format of domain list must be valid lua, as described in the comments of the script.
If you have /etc/hosts like file format, you must convert it. You might use awk or python3 to do it, as you like.

Optionally, to remove non utf8 characters:

iconv -f utf-8 -t utf-8 -c full_list_13-11-2019.txt > full_list_13-11-2019-utf8.txt

VPN push to clients

Setting up the VPN from scratch is out-of-scope for this post, but you can find a great tutorial on how to do it here:

The change we need is this simple change to /etc/openvpn/server.conf:

push "dhcp-option DNS"

Test the changes

# tjarosik @ tjarosik-P51 in ~ [16:24:54] C:1
$ dig @ applesupport.co        

; <<>> DiG 9.10.3-P4-Ubuntu <<>> @ applesupport.co
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56332
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 4096
;applesupport.co.		IN	A

applesupport.co.	3600	IN	SOA	fake.applesupport.co. fake.applesupport.co. 1 7200 900 1209600 86400

;; Query time: 35 msec
;; WHEN: Sun Nov 17 16:25:04 GMT 2019
;; MSG SIZE  rcvd: 85

Also, if you try that page in a web browser, you will see ERR_NAME_NOT_RESOLVED

You may also like

Leave a Comment

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More