This proxy server listen UDP and TCP traffic and redirect the request to a DNS over TLS resolver.
It has two ways of working. The first (Direct method) redirects the traffic from one connection to another (only available for TCP incoming connections) and the other (Not-Direct method) parses the DNS message before sending it to the resolver. If the "Not-Direct" method is set (Check how on the Configuration section) further management of the DNS message can be made. Like loggin, caching etc..
Configuration parameters are set in a single file, weather you are running on your host 💻 or docker 🐳.
# .env file
PROXY_CONFIG_UDP_PORT=8853
PROXY_CONFIG_TCP_PORT=8853
PROXY_CONFIG_METHOD=
PROXY_CONFIG_TCP_MAX_CONN_POOL=15
PROXY_CONFIG_CACHE_TTL=45
PROXY_RESOLVER_READ_TO=500
go build -o dns-proxy
source <(cat .env | awk '{print "export "$1}')
./dns-proxy
or simply run
source <(cat .env | awk '{print "export "$1}')
go run main.go config.go # no need to build
docker image build -t dns-proxy .
docker container run --rm -it --env-file .env -p 8853:8853/tcp -p 8853:8853/udp dns-proxy
dig google.com @127.0.0.1 -p 8853 # UDP
dig google.com @127.0.0.1 -p 8853 +tcp # TCP
- https://developers.cloudflare.com/1.1.1.1/dns-over-tls
openssl s_client -connect 1.1.1.1:853 -showcerts
- to check cloudflare's root-certificate To check cloudflare's root-certificate.- https://gobyexample.com/atomic-counters - for handling concurrent tcp contection-pool counter
- RFC 1035 (Specially section 4.2.2)
Imagine this proxy being deployed in an infrastructure. What would be the security concerns you would raise?
First of all the proxy receives unencrypted UDP and TCP traffic. So if this proxy is serving on a different infra than its clients that traffic may be sniffed. Same can happen locally but its more unlikely since the attacker should already have access to your machine.
How would you integrate that solution in a distributed, microservices-oriented and containerized architecture?
I see two possibles solution.
- I can make this daemon run as a side-cars along with the apps that doesn't support DNS over TLS as a possible solutions to encrypting my DNS requests. Running on the host directly on the host is another option but deploy a change on the proxy might be a bit harder to make.
- Or I can expose it a separate microservice and use it as my DNS for all the other microservices. (This one would face the first security concern mentioned in the 1st question)
- ✔️ Done
- (:heavy_plus_sign::heavy_minus_sign:) Partially Done
- ✖️ Not Done
Bonus:
- Allow multiple incoming requests at the same time (Bonus) ✔️
- Also handle UDP requests, while still querying tcp on the other side (Bonus) ✔️
Aditional improvements:
- More tests ! (Just a small part of the domain is tested)
go test ./...
✖️ - A limited pool of connections to prevent a DDoS attack, since each tcp connection runs a new thread. ✔️
- A cache that prevents querying the resolver if the petition has been made recently. ➕ ➖ ( Not implemented due to time reasons but yet used by the domain)
- Run the solution on a distroless container to reduce attack surface. ✔️
- Move
config.go
to its own package ✖️ - Play more with the parsed message
dnsmessage.Message
. Maybe add a blacklist, a logger of what's been requested. ✖️