chrisstaite / dote Goto Github PK
View Code? Open in Web Editor NEWA simple DNS wrapping server to forward UDP requests to a DNS over TLS server
License: MIT License
A simple DNS wrapping server to forward UDP requests to a DNS over TLS server
License: MIT License
Allow configuration to be specified in some way:
Shutdown the connections after each request because there won't ever be another request from that same client port because that's not how UDP works.
If we are binding to port 53 we need root permissions. We need to drop them.
Logging is either non-existent or printing out. Create a logger and use syslog.
Add a flag to daemonise the process.
Handle the case when a DNS errors, i.e. blacklist the forwarder for a while and try a different one.
hardware: armv5 based router
system: freshtomato
build system: tomatoware native
uname -a
Linux netgear 2.6.36.4brcmarm #7 SMP PREEMPT Wed Aug 11 16:39:01 CEST 2021 armv7l GNU/Linux
cmake -version
cmake version 3.20.5
build log:
[T][netgear:/tmp/mnt/data/compile/DoTe/b]$ cmake ..
CMake Deprecation Warning at CMakeLists.txt:2 (cmake_minimum_required):
Compatibility with CMake < 2.8.12 will be removed from a future version of
CMake.
Update the VERSION argument <min> value or use a ...<max> suffix to tell
CMake that the project does not need compatibility with older versions.
-- The CXX compiler identification is GNU 10.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /mmc/bin/distcc - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- The C compiler identification is GNU 10.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /mmc/bin/distcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Found OpenSSL: /mmc/lib/libcrypto.so (found version "1.1.1l")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/data/compile/DoTe/b
[T][netgear:/tmp/mnt/data/compile/DoTe/b]$ make
[ 1%] Building CXX object CMakeFiles/dote_static.dir/src/openssl/ssl_factory.cpp.o
[ 3%] Building CXX object CMakeFiles/dote_static.dir/src/openssl/context.cpp.o
[ 5%] Building CXX object CMakeFiles/dote_static.dir/src/openssl/ssl_connection.cpp.o
[ 7%] Building CXX object CMakeFiles/dote_static.dir/src/openssl/hostname_verifier.cpp.o
[ 9%] Building CXX object CMakeFiles/dote_static.dir/src/openssl/spki_verifier.cpp.o
[ 11%] Building CXX object CMakeFiles/dote_static.dir/src/openssl/certificate_utilities.cpp.o
[ 12%] Building CXX object CMakeFiles/dote_static.dir/src/openssl/base64.cpp.o
[ 14%] Building CXX object CMakeFiles/dote_static.dir/src/socket.cpp.o
[ 16%] Building CXX object CMakeFiles/dote_static.dir/src/forwarder_connection.cpp.o
[ 18%] Building CXX object CMakeFiles/dote_static.dir/src/forwarder_config.cpp.o
[ 20%] Building CXX object CMakeFiles/dote_static.dir/src/client_forwarders.cpp.o
[ 22%] Building CXX object CMakeFiles/dote_static.dir/src/verify_cache.cpp.o
[ 24%] Building CXX object CMakeFiles/dote_static.dir/src/loop.cpp.o
distcc[12793] ERROR: compile /mnt/data/compile/DoTe/src/loop.cpp on 192.168.2.20 failed
distcc[12793] (dcc_build_somewhere) Warning: remote compilation of '/mnt/data/compile/DoTe/src/loop.cpp' failed, retrying locally
distcc[12793] Warning: failed to distribute /mnt/data/compile/DoTe/src/loop.cpp to 192.168.2.20, running locally instead
In file included from /mnt/data/compile/DoTe/include/loop.h:4,
from /mnt/data/compile/DoTe/src/loop.cpp:2:
/mnt/data/compile/DoTe/include/i_loop.h:25:62: error: 'time_t' has not been declared
25 | virtual bool registerRead(int handle, Callback callback, time_t timeout) = 0;
| ^~~~~~
/mnt/data/compile/DoTe/include/i_loop.h:34:63: error: 'time_t' has not been declared
34 | virtual bool registerWrite(int handle, Callback callback, time_t timeout) = 0;
| ^~~~~~
In file included from /mnt/data/compile/DoTe/src/loop.cpp:2:
/mnt/data/compile/DoTe/include/loop.h:36:54: error: 'time_t' has not been declared
36 | bool registerRead(int handle, Callback callback, time_t timeout) override;
| ^~~~~~
/mnt/data/compile/DoTe/include/loop.h:45:55: error: 'time_t' has not been declared
45 | bool registerWrite(int handle, Callback callback, time_t timeout) override;
| ^~~~~~
/mnt/data/compile/DoTe/include/loop.h:76:49: error: 'time_t' was not declared in this scope; did you mean 'size_t'?
76 | const std::map<int, std::pair<Callback, time_t>>& functions,
| ^~~~~~
| size_t
/mnt/data/compile/DoTe/include/loop.h:76:49: error: template argument 2 is invalid
/mnt/data/compile/DoTe/include/loop.h:76:55: error: template argument 2 is invalid
76 | const std::map<int, std::pair<Callback, time_t>>& functions,
| ^~
/mnt/data/compile/DoTe/include/loop.h:76:55: error: template argument 4 is invalid
/mnt/data/compile/DoTe/include/loop.h:85:5: error: 'time_t' does not name a type; did you mean 'size_t'?
85 | time_t timeout(time_t now, std::map<int, std::pair<Callback, time_t>>& functions);
| ^~~~~~
| size_t
/mnt/data/compile/DoTe/include/loop.h:128:39: error: 'time_t' was not declared in this scope; did you mean 'timeout'?
128 | std::map<int, std::pair<Callback, time_t>> m_readFunctions;
| ^~~~~~
| timeout
/mnt/data/compile/DoTe/include/loop.h:128:39: error: template argument 2 is invalid
/mnt/data/compile/DoTe/include/loop.h:128:45: error: template argument 2 is invalid
128 | std::map<int, std::pair<Callback, time_t>> m_readFunctions;
| ^~
/mnt/data/compile/DoTe/include/loop.h:128:45: error: template argument 4 is invalid
/mnt/data/compile/DoTe/include/loop.h:130:39: error: 'time_t' was not declared in this scope; did you mean 'timeout'?
130 | std::map<int, std::pair<Callback, time_t>> m_writeFunctions;
| ^~~~~~
| timeout
/mnt/data/compile/DoTe/include/loop.h:130:39: error: template argument 2 is invalid
/mnt/data/compile/DoTe/include/loop.h:130:45: error: template argument 2 is invalid
130 | std::map<int, std::pair<Callback, time_t>> m_writeFunctions;
| ^~
/mnt/data/compile/DoTe/include/loop.h:130:45: error: template argument 4 is invalid
/mnt/data/compile/DoTe/src/loop.cpp: In member function 'void dote::Loop::populateFds(std::vector<pollfd>&)':
/mnt/data/compile/DoTe/src/loop.cpp:40:45: error: no matching function for call to 'dote::Loop::popluateFds(std::vector<pollfd>&, int&, int)'
40 | popluateFds(fds, m_readFunctions, POLLIN);
| ^
In file included from /mnt/data/compile/DoTe/src/loop.cpp:2:
/mnt/data/compile/DoTe/include/loop.h:113:17: note: candidate: 'template<class T> static void dote::Loop::popluateFds(std::vector<pollfd>&, const std::map<int, T>&, short int)'
113 | static void popluateFds(std::vector<pollfd>& fds,
| ^~~~~~~~~~~
/mnt/data/compile/DoTe/include/loop.h:113:17: note: template argument deduction/substitution failed:
/mnt/data/compile/DoTe/src/loop.cpp:40:45: note: mismatched types 'const std::map<int, T>' and 'int'
40 | popluateFds(fds, m_readFunctions, POLLIN);
| ^
/mnt/data/compile/DoTe/src/loop.cpp:41:47: error: no matching function for call to 'dote::Loop::popluateFds(std::vector<pollfd>&, int&, int)'
41 | popluateFds(fds, m_writeFunctions, POLLOUT);
| ^
In file included from /mnt/data/compile/DoTe/src/loop.cpp:2:
/mnt/data/compile/DoTe/include/loop.h:113:17: note: candidate: 'template<class T> static void dote::Loop::popluateFds(std::vector<pollfd>&, const std::map<int, T>&, short int)'
113 | static void popluateFds(std::vector<pollfd>& fds,
| ^~~~~~~~~~~
/mnt/data/compile/DoTe/include/loop.h:113:17: note: template argument deduction/substitution failed:
/mnt/data/compile/DoTe/src/loop.cpp:41:47: note: mismatched types 'const std::map<int, T>' and 'int'
41 | popluateFds(fds, m_writeFunctions, POLLOUT);
| ^
/mnt/data/compile/DoTe/src/loop.cpp: At global scope:
/mnt/data/compile/DoTe/src/loop.cpp:93:6: error: no declaration matches 'void dote::Loop::callCallback(const std::map<int, std::pair<std::function<void(int)>, long int> >&, int)'
93 | void Loop::callCallback(
| ^~~~
In file included from /mnt/data/compile/DoTe/src/loop.cpp:2:
/mnt/data/compile/DoTe/include/loop.h:75:17: note: candidate is: 'static void dote::Loop::callCallback(const int&, int)'
75 | static void callCallback(
| ^~~~~~~~~~~~
/mnt/data/compile/DoTe/include/loop.h:14:7: note: 'class dote::Loop' defined here
14 | class Loop : public ILoop
| ^~~~
/mnt/data/compile/DoTe/src/loop.cpp:104:6: error: no declaration matches 'bool dote::Loop::registerRead(int, dote::ILoop::Callback, time_t)'
104 | bool Loop::registerRead(int handle, Callback callback, time_t timeout)
| ^~~~
In file included from /mnt/data/compile/DoTe/src/loop.cpp:2:
/mnt/data/compile/DoTe/include/loop.h:36:10: note: candidate is: 'virtual bool dote::Loop::registerRead(int, dote::ILoop::Callback, int)'
36 | bool registerRead(int handle, Callback callback, time_t timeout) override;
| ^~~~~~~~~~~~
/mnt/data/compile/DoTe/include/loop.h:14:7: note: 'class dote::Loop' defined here
14 | class Loop : public ILoop
| ^~~~
/mnt/data/compile/DoTe/src/loop.cpp:115:6: error: no declaration matches 'bool dote::Loop::registerWrite(int, dote::ILoop::Callback, time_t)'
115 | bool Loop::registerWrite(int handle, Callback callback, time_t timeout)
| ^~~~
In file included from /mnt/data/compile/DoTe/src/loop.cpp:2:
/mnt/data/compile/DoTe/include/loop.h:45:10: note: candidate is: 'virtual bool dote::Loop::registerWrite(int, dote::ILoop::Callback, int)'
45 | bool registerWrite(int handle, Callback callback, time_t timeout) override;
| ^~~~~~~~~~~~~
/mnt/data/compile/DoTe/include/loop.h:14:7: note: 'class dote::Loop' defined here
14 | class Loop : public ILoop
| ^~~~
/mnt/data/compile/DoTe/src/loop.cpp: In member function 'virtual void dote::Loop::removeRead(int)':
/mnt/data/compile/DoTe/src/loop.cpp:140:21: error: request for member 'erase' in '((dote::Loop*)this)->dote::Loop::m_readFunctions', which is of non-class type 'int'
140 | m_readFunctions.erase(handle);
| ^~~~~
/mnt/data/compile/DoTe/src/loop.cpp: In member function 'virtual void dote::Loop::removeWrite(int)':
/mnt/data/compile/DoTe/src/loop.cpp:145:22: error: request for member 'erase' in '((dote::Loop*)this)->dote::Loop::m_writeFunctions', which is of non-class type 'int'
145 | m_writeFunctions.erase(handle);
| ^~~~~
/mnt/data/compile/DoTe/src/loop.cpp: At global scope:
/mnt/data/compile/DoTe/src/loop.cpp:153:8: error: no declaration matches 'time_t dote::Loop::timeout(time_t, std::map<int, std::pair<std::function<void(int)>, long int> >&)'
153 | time_t Loop::timeout(time_t now, std::map<int, std::pair<Callback, time_t>>& functions)
| ^~~~
In file included from /mnt/data/compile/DoTe/src/loop.cpp:2:
/mnt/data/compile/DoTe/include/loop.h:90:9: note: candidate is: 'int dote::Loop::timeout()'
90 | int timeout();
| ^~~~~~~
/mnt/data/compile/DoTe/include/loop.h:14:7: note: 'class dote::Loop' defined here
14 | class Loop : public ILoop
| ^~~~
/mnt/data/compile/DoTe/src/loop.cpp: In member function 'int dote::Loop::timeout()':
/mnt/data/compile/DoTe/src/loop.cpp:188:55: error: no matching function for call to 'dote::Loop::timeout(time_t&, int&)'
188 | time_t earliestRead = timeout(now, m_readFunctions);
| ^
/mnt/data/compile/DoTe/src/loop.cpp:185:5: note: candidate: 'int dote::Loop::timeout()'
185 | int Loop::timeout()
| ^~~~
/mnt/data/compile/DoTe/src/loop.cpp:185:5: note: candidate expects 0 arguments, 2 provided
/mnt/data/compile/DoTe/src/loop.cpp:189:57: error: no matching function for call to 'dote::Loop::timeout(time_t&, int&)'
189 | time_t earliestWrite = timeout(now, m_writeFunctions);
| ^
/mnt/data/compile/DoTe/src/loop.cpp:185:5: note: candidate: 'int dote::Loop::timeout()'
185 | int Loop::timeout()
| ^~~~
/mnt/data/compile/DoTe/src/loop.cpp:185:5: note: candidate expects 0 arguments, 2 provided
distcc[12793] ERROR: compile /mnt/data/compile/DoTe/src/loop.cpp on localhost failed
make[2]: *** [CMakeFiles/dote_static.dir/build.make:244: CMakeFiles/dote_static.dir/src/loop.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:115: CMakeFiles/dote_static.dir/all] Error 2
make: *** [Makefile:101: all] Error 2
If the DNS response comes back in blocks, we should handle that happening.
When testing on an EdgeRouter on a standard network, the CPU load goes up to 100% and requests take a very long time to get answered. This is likely related to issue #5.
Turns out that the call to X509_verify_cert within SSL_connect is the biggest user of CPU. We could perhaps cache the certificate and not verify it every time which would be far more efficient. Obviously, we should fully verify it periodically in case it has been revoked or the expiry of the certificate has been reached, but certainly it would be ok to cache it for say 10 minutes at a time?
It's lovely having some empty test files, but they really should have tests in them.
There's currently a fixed number of connections before caching. That should be configurable. Equally, it would be nice if the maximum number of requests to cache was a thing too.
Hi! first of all, thank you for this, I think it is a great solution!
I was wondering if it would be possible to compile it also for the USG. Currently the USG also uses EdgeOS, but the OpenSSL version is 1.0.1t, so when executing it, it can't locate the correct library: error while loading shared libraries: libssl.so.1.1
I could do it myself but I'm unsure on how to install cmake and the c++ compiler into the USG.
Thank you in advance!
Hello,
This is the script I'm running if I need an update:
#!/bin/sh
set -e
tmpdir="$(mktemp -d)"
curl -sSLo "${tmpdir}/dote" https://github.com/chrisstaite/DoTe/releases/latest/download/dote_arm64
cat > "${tmpdir}/Dockerfile" <<EOF
FROM pihole/pihole:latest
ENV DOTE_OPTS="-s 127.0.0.1:5053"
COPY dote /opt/dote
RUN chmod +x /opt/dote && echo -e "#!/bin/sh\n/opt/dote \\\$DOTE_OPTS -d\n" > /etc/cont-init.d/10-dote.sh
EOF
podman pull pihole/pihole:latest
podman build -t pihole:latest --format docker -f "${tmpdir}/Dockerfile" "${tmpdir}"
rm -rf "${tmpdir}"
set +e
podman stop pihole
podman rm pihole
podman run -d --network dns --restart always \
--name pihole \
-e TZ="Europe/Amsterdam" \
-v "/mnt/data/etc-pihole/:/etc/pihole/" \
-v "/mnt/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \
--dns=127.0.0.1 \
--hostname Marauder \
-e DOTE_OPTS="-s 127.0.0.1:5053 -m 10" \
-e VIRTUAL_HOST="pi.hole" \
-e PROXY_LOCATION="pi.hole" \
-e PIHOLE_DNS_="127.0.0.1#5053" \
-e ServerIP="192.168.205.101" \
-e IPv6="False" \
pihole:latest
But, my devices cannot connect to the internet. It seems DoTe is not running and thus not resolving. The system works if I change the DNS servers to for example 1.1.1.1 or 8.8.8.8.
What am I doing wrong?
EDNS0 padding makes the UDP packets larger for no reason and could have MTU issues on some networks or with some clients that don't support it.
I have created the following script to create the pihole container, but it seems that my UDM Pro has somewhat different behavior in a couple aspects. /dev/fd0
isn't present on my system (I'm on UniFi OS 1.10.4), and if I run the script below and list /opt
, only pihole is present. Shouldn't it be present after container initialization?
#!/bin/sh
cat > Dockerfile <<EOF
FROM pihole/pihole:latest
ENV DOTE_OPTS="-s 127.0.0.1:5053"
RUN echo -e "#!/bin/sh\ncurl -fsSLo /opt/dote https://github.com/chrisstaite/DoTe/releases/latest/download/dote_arm64\nchmod +x /opt/dote\n/opt/dote \\\$DOTE_OPTS -d\n" > /etc/cont-init.d/10-dote.sh
EOF
podman pull pihole/pihole:latest
podman build -t localhost/pihole:latest --format docker -f Dockerfile
rm Dockerfile
podman stop pihole
podman rm pihole
podman run -d --network dns --restart always \
--name pihole \
-e TZ="Europe/Zurich" \
-v "/mnt/data/etc-pihole/:/etc/pihole/" \
-v "/mnt/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \
-v "/mnt/data/pihole/hosts:/etc/hosts:ro" \
--dns=127.0.0.1 \
--hostname pihole \
-e DOTE_OPTS="-s 127.0.0.1:5053 -m 10" \
-e VIRTUAL_HOST="pihole" \
-e PROXY_LOCATION="pihole" \
-e ServerIP="192.168.6.253" \
-e PIHOLE_DNS_="127.0.0.1#5053" \
-e IPv6="False" \
localhost/pihole:latest
If I try executing the script steps inside the container, I get the following:
# docker exec -ti pihole bash
root@pihole:/# # curl -fsSLo /opt/dote https://github.com/chrisstaite/DoTe/releases/latest/download/dote_arm64
# chmod +x /opt/dote
# /opt/dote $DOTE_OPTS -d
/opt/dote: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.