DNS resolution is an important part in a healthy network environment. In region where DNS resolution is not reliable, encrypting DNS queries to trusted source may be a solution to recover network connectivity.
There are many ways to encrypt DNS traffic, for example, DNS over TLS, DNS over Https, DNSCrypt etc and even shadowsocks can do that. Here I outline an idea which uses the existed construction. It consists of many different components to work together so it is a bit complicated but on the other side, it allows plenty of customizations and flexibility.
Basically, I am using the TCP feature of DNS, DNS generally uses UDP but will turn to TCP for zone transfer or other larger responses. When DNS is in TCP, it opens the possibility to encrypt and tunnel it.
- unbound (dns server)
- vps (to reach trusted dns servers)
I am not going to detail how to config openwrt, shadowsocks, unbound and vps. There are many resources describing them but you may need time to make them work as you intended.
To visualize my idea, I draft a diagram and I am going to discuss it in steps with necessary config for each of them.
Wifi router receiving dns queries vis dnsmasq over udp/53.
In here, we can
- dnsmasq forwards all queries to unbound
- dnsmasq forwards a subset of queries to unbound
- Replace dnsmasq completely using unbound
I choose to implement b) but c) is probably the best option. To config dnsmasq to forward a subset of traffic: (add more domains if you want in forward.conf)
In /etc/dnsmasq.conf: conf-dir=/etc/dnsmasq.d
In /etc/dnsmasq.d/forward.conf: server=/bbc.co.uk/127.0.0.1#7913
Here, you will need to config unbound to listen at udp/7913 on lo first.
unbound receives DNS queries at udp/7913, it will forward to upstream DNS server using TCP. To config unbound to forward to upstream DNS: (a.b.c.d is the upstream unbound DNS server)
In /etc/unbound/unbound_srv.conf: do-tcp: yes tcp-upstream: yes
In /etc/unbound/unbound_ext.conf: forward-zone: name: "." forward-addr: a.b.c.d@7913 forward-first: no
Here, you will need to config ss-redir to listen at tcp/1080 on lo first.
To redirect locally generated traffic to ss-redir which listen at tcp/1080, we need to add a rule in OUTPUT chain of ip packet nat table:
/usr/sbin/iptables -t nat -A OUTPUT -p tcp --dport 7913 -j REDIRECT --to 1080
Step 5, 6:
Here, you will need to config ss-redir to encrypt traffic and forward to ss-server in vps at tcp/1080.
Here, you will need to config ss-server to listen at tcp/1080 on eth0.
Here, you will need to config unbound to listen at tcp/7913 on eth0. ss-redir will send the dns query into unbound via TCP.
Step 9, 10:
Finally, unbound will query the root DNS servers via UDP. It will return the answers to the client behind the openwrt router.