From cb38dbec113d901986cb19ac70d33f22ac131276 Mon Sep 17 00:00:00 2001 From: coolquasar Date: Sun, 22 Nov 2020 18:17:58 +0100 Subject: [PATCH 1/5] Added support to run dnsproxy server/client in docker --- Docker/Dockerfile | 37 +++++++++++++++ Docker/README.md | 42 +++++++++++++++++ Docker/dnsproxy.sh | 41 +++++++++++++++++ Docker/docker-compose.yml | 27 +++++++++++ Docker/letsencrypt-wrapper.sh | 85 +++++++++++++++++++++++++++++++++++ Docker/start.sh | 3 ++ Docker/supervisord.conf | 20 +++++++++ 7 files changed, 255 insertions(+) create mode 100644 Docker/Dockerfile create mode 100644 Docker/README.md create mode 100755 Docker/dnsproxy.sh create mode 100644 Docker/docker-compose.yml create mode 100755 Docker/letsencrypt-wrapper.sh create mode 100755 Docker/start.sh create mode 100644 Docker/supervisord.conf diff --git a/Docker/Dockerfile b/Docker/Dockerfile new file mode 100644 index 000000000..59a422226 --- /dev/null +++ b/Docker/Dockerfile @@ -0,0 +1,37 @@ +FROM golang:1.14-alpine as builder + +RUN apk --update --no-cache add \ + build-base \ + git \ + && rm -rf /tmp/* /var/cache/apk/* + +WORKDIR ~ +RUN git clone https://github.com/AdguardTeam/dnsproxy + +WORKDIR dnsproxy/ + +RUN go build -mod=vendor -v + +FROM alpine:3.12 +LABEL maintainer="coolquasar@gmail.com" + +RUN apk update && \ + apk add bash supervisor certbot procps net-tools && \ + rm -rf /tmp/* /var/cache/apk/* + +COPY --from=builder /go/~/dnsproxy/dnsproxy /usr/bin + +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf + +COPY letsencrypt-wrapper.sh /srv/ +COPY dnsproxy.sh /srv/ +COPY start.sh /srv/ + +VOLUME ["/var/log", "/etc/letsencrypt"] + +EXPOSE "80" +EXPOSE "443" +EXPOSE "784"/udp +EXPOSE "853" + +ENTRYPOINT ["/srv/start.sh"] diff --git a/Docker/README.md b/Docker/README.md new file mode 100644 index 000000000..c9d9ecd32 --- /dev/null +++ b/Docker/README.md @@ -0,0 +1,42 @@ +## dnsproxy - Docker + +This part of the project is to run dnsproxy in docker as server or client. The docker image pulls the current dnsproxy code, builds it and creates an alpine based docker image + +Default version of docker-compose runs dnsproxy as quic server with upstream 1.1.1..1 + 1. Current version of dnsproxy docker supports `DNS-over-TLS, `DNS-over-HTTPS`, `DNSCrypt`, and `DNS-over-QUIC` + 2. Moreover, it can work as a `DNS-over-HTTPS`, `DNS-over-TLS` or `DNS-over-QUIC` server, or a simple passthrough server in a defined port + +Functionalities supported by the docker image will be sub-set of the functionalities supported by dnsproxy current code + +``` +# docker-compose up -d +``` + +### Following changes required in docker-compose.yml. to start dnsproxy as `DNS-over-HTTPS` +``` +SRVPORT: "443" +MODE: "server" +PROTO: "https" +``` + +### Following changes required in docker-compose.yml. to start dnsproxy as `DNS-over-QUIC` +``` +SRVPORT: "784" +MODE: "server" +PROTO: "quic" +``` + + +### Following changes required in docker-compose.yml. to start dnsproxy as `DNS-over-TLS` +``` +SRVPORT: "853" +MODE: "server" +PROTO: "tls" +``` +### Following changes required in docker-compose.yml. to start dnsproxy as `client` +``` +MODE: "client" +LOCALPORT: "1234" # Any local port number +``` + +Remove EDNS flag in docker-compose.yml, if EDNS support is not required diff --git a/Docker/dnsproxy.sh b/Docker/dnsproxy.sh new file mode 100755 index 000000000..58f42be50 --- /dev/null +++ b/Docker/dnsproxy.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +COMMAND="dnsproxy" +LISTENADDR=$LISTEN +SRVPORT=$SRVPORT +CERTPATH=/etc/letsencrypt/live/$DOMAIN/fullchain.pem +KEYPATH=/etc/letsencrypt/live/$DOMAIN/privkey.pem +UPSTREAM=$UPSTREAM_ADDR +RATELIMIT=$RATELIMIT +EDNSFLAG=$EDNS +EDNSIP=$EDNSIP +PORT=$LOCALPORT +PROTOCOL=$PROTO + +case $PROTOCOL in + "quic") SWITCHPORT="-q $SRVPORT --tls-crt=$CERTPATH --tls-key=$KEYPATH";; + "tls") SWITCHPORT="-t $SRVPORT --tls-crt=$CERTPATH --tls-key=$KEYPATH";; + "https") SWITCHPORT="--https-port $SRVPORT --tls-crt=$CERTPATH --tls-key=$KEYPATH";; + "dnscrypt") SWITCHPORT="-y $SRVPORT --tls-crt=$CERTPATH --tls-key=$KEYPATH";; +esac + +case $MODE in + "server") LISTENSWITCH="-l $LISTENADDR"; + if [[ ! -f $CERTPATH ]] + then + echo "Waiting for letsencrypt cert to be created" + sleep 30; + fi;; + + "client") LISTENSWITCH=" "; + SWITCHPORT=" ";; +esac + +if [[ $EDNSFLAG == "" ]] +then + $COMMAND $LISTENSWITCH $SWITCHPORT -u $UPSTREAM -r $RATELIMIT -p $PORT +else + $COMMAND $LISTENSWITCH $SWITCHPORT -u $UPSTREAM -r $RATELIMIT --edns -p $PORT +fi + +#dnsproxy -l 0.0.0.0 -q 785 --tls-crt=/etc/letsencrypt/live/$DOMAIN/fullchain.pem --tls-key=/etc/letsencrypt/live/$DOMAIN/privkey.pem -u 192.168.2.1:53 -r 100 --edns -p $PORT diff --git a/Docker/docker-compose.yml b/Docker/docker-compose.yml new file mode 100644 index 000000000..d6885c25f --- /dev/null +++ b/Docker/docker-compose.yml @@ -0,0 +1,27 @@ +version: '3' + +services: + dnsproxy: + image: dnsproxy/AdguardHome:latest + container_name: dnsproxy + restart: always + #volumes: + #- /etc/letsencrypt:/etc/letsencrypt # Uncomment this line to reuse existing cert and key + environment: + LISTEN: "0.0.0.0" + SRVPORT: "784" + DOMAIN: "example.org" # Your domain name required + EMAIL: "email@example.org" + UPSTREAM_ADDR: "1.1.1.1:53" + RATELIMIT: "30" + EDNS: "ON" + LOCALPORT: "1111" # Any local port # + MODE: "server" + PROTO: "quic" + DRYRUN: "--dry-run" # Uncomment this option to test letsencrypt cert generation process + ports: + - 80:80 # Port 80 is mandatory for letsencrypt to generate cert/keys successfully + - 443:443 + - 784:784/udp + - 853:853 + - 1111:1111/udp diff --git a/Docker/letsencrypt-wrapper.sh b/Docker/letsencrypt-wrapper.sh new file mode 100755 index 000000000..425552379 --- /dev/null +++ b/Docker/letsencrypt-wrapper.sh @@ -0,0 +1,85 @@ +#!/bin/bash + +if [[ $DEBUG ]]; then + set -x +fi + +logger() { + echo "[letsencrypt] :: $(date +%x-%X) :: $@" | tee -a /var/log/letsencrypt-wrapper.log +} + +get_first_time() { + local d=$1 + if certbot certonly $DRYRUN --agree-tos --email $EMAIL \ + -n --standalone -w /etc/letsencrypt -d $d + then + logger "First certificate got for $d" + else + logger "ERROR on first time certificate for $d" + exit 2 + fi +} + +renew_certs() { + certbot renew $DRYRUN -n --standalone -w /etc/letsencrypt -d "${1}" +} + +check_env() { + if ! [[ $DOMAIN ]]; then + logger "ERROR! Missing domains to be used! Set DOMAIN environment variable." + exit 1 + fi + if ! [[ $EMAIL ]]; then + logger "ERROR! Missing email address to use to register the domain(s) certificates." + fi +} + +should_force() { + if ! [[ -f "/etc/letsencrypt/live/${1}/.doh-force" ]]; then + return 0 + fi + logger "Not skipping - found file /etc/letsencrypt/live/${1}/.doh-force" + return 1 +} + +le_vol_mounted() { + if grep "/etc/letsencrypt/live/${1}" <(mount) > /dev/null; then + logger "A letsencrypt volume is mounted for domain ${1}" + should_force $1 && return 0 + elif grep "/etc/letsencrypt" <(mount) > /dev/null; then + logger "The whole /etc/letsencrypt is mounted" + if [[ -d "/etc/letsencrypt/live/${1}" ]]; then + should_force $1 && return 0 + fi + fi + return 1 +} + +main() { + check_env + for d in $DOMAIN; do + if le_vol_mounted ${d}; then + # Assuming that if the volume is mounted from the host + # creation and renewal is in charge of others, + # except if the .doh-force file il present in the + # directory of the certificates. In such case, the container + # will take care of renewing them. + logger "Skipping domain ${1}" + continue + fi + if [[ -f /etc/letsencrypt/live/$d/privkey.pem ]]; then + logger "Renewing certificate for $d" + renew_certs $d + else + logger "Getting first time certificates for $d" + get_first_time $d + fi + done + logger "All done, sleeping for ${WAIT_TIME:-"1d"}." + sleep ${WAIT_TIME:-"1d"} +} + +while true +do + main +done diff --git a/Docker/start.sh b/Docker/start.sh new file mode 100755 index 000000000..274baf031 --- /dev/null +++ b/Docker/start.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf diff --git a/Docker/supervisord.conf b/Docker/supervisord.conf new file mode 100644 index 000000000..dbb834039 --- /dev/null +++ b/Docker/supervisord.conf @@ -0,0 +1,20 @@ +[supervisord] +nodaemon=true + +[program:letsencrypt] +command=/srv/letsencrypt-wrapper.sh +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/fd/2 +stderr_logfile_maxbytes=0 +username=root +autorestart=false + +[program:dnsproxy] +command=/srv/dnsproxy.sh +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/fd/2 +stderr_logfile_maxbytes=0 +username=root +autorestart=true From 5d2a7f197e1e734a9380d9fe7577c83d7429c970 Mon Sep 17 00:00:00 2001 From: coolquasar Date: Mon, 23 Nov 2020 17:46:26 +0100 Subject: [PATCH 2/5] Checking in latest changes --- Docker/client/docker-compose.yml | 46 ++++++++++++++++++++ Docker/dnsproxy.sh | 2 +- Docker/docker-compose.yml | 27 ------------ Docker/server/docker-compose.yml | 74 ++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 28 deletions(-) create mode 100644 Docker/client/docker-compose.yml delete mode 100644 Docker/docker-compose.yml create mode 100644 Docker/server/docker-compose.yml diff --git a/Docker/client/docker-compose.yml b/Docker/client/docker-compose.yml new file mode 100644 index 000000000..c7e41ead0 --- /dev/null +++ b/Docker/client/docker-compose.yml @@ -0,0 +1,46 @@ +version: '3' + +services: + dnsproxy_quic_client: + image: dnsproxy/AdguardHome:latest + container_name: dnsproxy_quic_client + restart: always + environment: + UPSTREAM_ADDR: "quic://dns-unfiltered.adguard.com:784" # change it to your prefered quic server + RATELIMIT: "30" + EDNS: "ON" + LOCALPORT: "1111" # Any local port # + MODE: "client" + PROTO: "quic" + ports: + - 1112:1111/udp + dnsproxy_https_client: + image: dnsproxy/AdguardHome:latest + container_name: dnsproxy_https_client + restart: always + environment: + UPSTREAM_ADDR: "https://dns.adguard.com/dns-query" # change it to your prefered https server + RATELIMIT: "30" + EDNS: "ON" + LOCALPORT: "1111" # Any local port # + MODE: "client" + ports: + - 1113:1111/udp + dnsproxy_tls_client: + image: dnsproxy/AdguardHome:latest + container_name: dnsproxy_tls_client + restart: always + environment: + UPSTREAM_ADDR: "tls://dns.adguard.com" # change it to your prefered tls server + RATELIMIT: "30" + EDNS: "ON" + LOCALPORT: "1111" # Any local port # + MODE: "client" + ports: + - 1114:1111/udp +networks: + default: + driver: bridge + ipam: + config: + - subnet: 172.16.57.0/24 diff --git a/Docker/dnsproxy.sh b/Docker/dnsproxy.sh index 58f42be50..5cb0bf350 100755 --- a/Docker/dnsproxy.sh +++ b/Docker/dnsproxy.sh @@ -24,7 +24,7 @@ case $MODE in if [[ ! -f $CERTPATH ]] then echo "Waiting for letsencrypt cert to be created" - sleep 30; + sleep 8; fi;; "client") LISTENSWITCH=" "; diff --git a/Docker/docker-compose.yml b/Docker/docker-compose.yml deleted file mode 100644 index d6885c25f..000000000 --- a/Docker/docker-compose.yml +++ /dev/null @@ -1,27 +0,0 @@ -version: '3' - -services: - dnsproxy: - image: dnsproxy/AdguardHome:latest - container_name: dnsproxy - restart: always - #volumes: - #- /etc/letsencrypt:/etc/letsencrypt # Uncomment this line to reuse existing cert and key - environment: - LISTEN: "0.0.0.0" - SRVPORT: "784" - DOMAIN: "example.org" # Your domain name required - EMAIL: "email@example.org" - UPSTREAM_ADDR: "1.1.1.1:53" - RATELIMIT: "30" - EDNS: "ON" - LOCALPORT: "1111" # Any local port # - MODE: "server" - PROTO: "quic" - DRYRUN: "--dry-run" # Uncomment this option to test letsencrypt cert generation process - ports: - - 80:80 # Port 80 is mandatory for letsencrypt to generate cert/keys successfully - - 443:443 - - 784:784/udp - - 853:853 - - 1111:1111/udp diff --git a/Docker/server/docker-compose.yml b/Docker/server/docker-compose.yml new file mode 100644 index 000000000..f92a95ff7 --- /dev/null +++ b/Docker/server/docker-compose.yml @@ -0,0 +1,74 @@ +version: '3' + +services: + dnsproxy_https: + image: dnsproxy/AdguardHome:latest + container_name: dnsproxy_https + restart: always + volumes: + - dns_cert_keys:/etc/letsencrypt + environment: + LISTEN: "0.0.0.0" + SRVPORT: "443" + DOMAIN: "example.org" + EMAIL: "email@example.org" + UPSTREAM_ADDR: "1.1.1.1:53" + RATELIMIT: "100" + EDNS: "ON" + LOCALPORT: "1111" # Any local port # + MODE: "server" + PROTO: "https" + ports: + - 80:80 # Port 80 is mandatory for letsencrypt to generate cert/keys successfully + - 443:443 + - 1114:1111/udp + dnsproxy_quic: + image: jithub/dnsproxy:latest + container_name: dnsproxy_quic + restart: always + depends_on: + - dnsproxy_https + volumes: + - dns_cert_keys:/etc/letsencrypt + environment: + LISTEN: "0.0.0.0" + SRVPORT: "784" + DOMAIN: "jiteuhub.ddns.net" + EMAIL: "email@example.org" + UPSTREAM_ADDR: "1.1.1.1:53" + RATELIMIT: "100" + EDNS: "ON" + LOCALPORT: "1111" # Any local port # + MODE: "server" + PROTO: "quic" + ports: + - 784:784/udp + - 1112:1111/udp + dnsproxy_tls: + image: jithub/dnsproxy:latest + container_name: dnsproxy_tls + restart: always + depends_on: + - dnsproxy_https + volumes: + - dns_cert_keys:/etc/letsencrypt # Uncomment this line to reuse existing cert and key + environment: + LISTEN: "0.0.0.0" + SRVPORT: "853" + DOMAIN: "jiteuhub.ddns.net" + EMAIL: "email@example.org" + UPSTREAM_ADDR: "1.1.1.1:53" + RATELIMIT: "100" + EDNS: "ON" + LOCALPORT: "1111" # Any local port # + MODE: "server" + PROTO: "tls" + ports: + - 853:853 + - 1113:1111/udp + + # Create this volume by running "docker volume create dns_cert_keys" command +volumes: + dns_cert_keys: + external: + name: dns_cert_keys From b020997a106c8a1c1fd7b5a5f56750fdc3f077e2 Mon Sep 17 00:00:00 2001 From: coolquasar Date: Mon, 23 Nov 2020 17:53:33 +0100 Subject: [PATCH 3/5] Updates the README.md with more relevant comments. I hope it helps --- Docker/README.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Docker/README.md b/Docker/README.md index c9d9ecd32..048b6c365 100644 --- a/Docker/README.md +++ b/Docker/README.md @@ -8,32 +8,45 @@ Default version of docker-compose runs dnsproxy as quic server with upstream 1.1 Functionalities supported by the docker image will be sub-set of the functionalities supported by dnsproxy current code +### To start the dnsproxy as `DNS-over-TLS, `DNS-over-HTTPS` and `DNS-over-QUIC` server ``` +# cd dnsproxy/Docker/server +# docker volume create dns_cert_keys # docker-compose up -d ``` -### Following changes required in docker-compose.yml. to start dnsproxy as `DNS-over-HTTPS` +If dnsproxy server creation fails, run this command, and chances are it will be okay +``` +# docker-compose up -d --force-recreate +``` + +### To start the dnsproxy as client, with upstream to Adguard `DNS-over-TLS, `DNS-over-HTTPS` and `DNS-over-QUIC` server +``` +# cd dnsproxy/Docker/client +# docker-compose up -d +``` + +### Following changes required in server/docker-compose.yml. to start dnsproxy as `DNS-over-HTTPS` ``` SRVPORT: "443" MODE: "server" PROTO: "https" ``` -### Following changes required in docker-compose.yml. to start dnsproxy as `DNS-over-QUIC` +### Following changes required in server/docker-compose.yml. to start dnsproxy as `DNS-over-QUIC` ``` SRVPORT: "784" MODE: "server" PROTO: "quic" ``` - -### Following changes required in docker-compose.yml. to start dnsproxy as `DNS-over-TLS` +### Following changes required in server/docker-compose.yml. to start dnsproxy as `DNS-over-TLS` ``` SRVPORT: "853" MODE: "server" PROTO: "tls" ``` -### Following changes required in docker-compose.yml. to start dnsproxy as `client` +### Following changes required in client/docker-compose.yml. to start dnsproxy as `client` ``` MODE: "client" LOCALPORT: "1234" # Any local port number From e4268121a0a12e32c7bda7c58597721cc5f99325 Mon Sep 17 00:00:00 2001 From: coolquasar Date: Mon, 23 Nov 2020 17:56:31 +0100 Subject: [PATCH 4/5] Updated typo-graphy in docker image name --- Docker/server/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Docker/server/docker-compose.yml b/Docker/server/docker-compose.yml index f92a95ff7..c43c623f7 100644 --- a/Docker/server/docker-compose.yml +++ b/Docker/server/docker-compose.yml @@ -23,7 +23,7 @@ services: - 443:443 - 1114:1111/udp dnsproxy_quic: - image: jithub/dnsproxy:latest + image: dnsproxy/AdguardHome:latest container_name: dnsproxy_quic restart: always depends_on: @@ -45,7 +45,7 @@ services: - 784:784/udp - 1112:1111/udp dnsproxy_tls: - image: jithub/dnsproxy:latest + image: dnsproxy/AdguardHome:latest container_name: dnsproxy_tls restart: always depends_on: From 69e6046b8033b41d9af3c5c095f5e655ace858c6 Mon Sep 17 00:00:00 2001 From: coolquasar Date: Mon, 23 Nov 2020 18:00:23 +0100 Subject: [PATCH 5/5] Added step to create docker image --- Docker/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Docker/README.md b/Docker/README.md index 048b6c365..b421ef006 100644 --- a/Docker/README.md +++ b/Docker/README.md @@ -6,9 +6,15 @@ Default version of docker-compose runs dnsproxy as quic server with upstream 1.1 1. Current version of dnsproxy docker supports `DNS-over-TLS, `DNS-over-HTTPS`, `DNSCrypt`, and `DNS-over-QUIC` 2. Moreover, it can work as a `DNS-over-HTTPS`, `DNS-over-TLS` or `DNS-over-QUIC` server, or a simple passthrough server in a defined port +Create the docker image +``` +# cd dnsproxy/Docker +# docker build -t dnsproxy/AdguardHome:latest $PWD +``` + Functionalities supported by the docker image will be sub-set of the functionalities supported by dnsproxy current code -### To start the dnsproxy as `DNS-over-TLS, `DNS-over-HTTPS` and `DNS-over-QUIC` server +### To start the dnsproxy as `DNS-over-TLS`, `DNS-over-HTTPS` and `DNS-over-QUIC` server ``` # cd dnsproxy/Docker/server # docker volume create dns_cert_keys