├── .github └── workflows │ └── docker-image.yml ├── Dockerfile ├── LICENSE ├── README.md ├── dnscrypt-small.png ├── dnscrypt.png ├── docker-compose.yml ├── encrypted-dns.sh ├── encrypted-dns.toml.in ├── entrypoint.sh ├── kube ├── dnscrypt-deployment.yml ├── dnscrypt-init-job.yml └── dnscrypt-srv.yml ├── scripts └── install-centos.sh ├── unbound-check.sh ├── unbound.sh ├── undelegated.txt └── watchdog.sh /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Build the Docker image 18 | run: docker buildx build . --file Dockerfile --tag my-image-name:$(date +%s) 19 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | LABEL maintainer="Frank Denis" 3 | SHELL ["/bin/sh", "-x", "-c"] 4 | ENV SERIAL=1 5 | 6 | ENV CFLAGS=-O3 7 | ENV BUILD_DEPS="curl make build-essential git libevent-dev libexpat1-dev autoconf file libssl-dev flex bison" 8 | ENV RUNTIME_DEPS="bash util-linux coreutils findutils grep libssl3 ldnsutils libevent-2.1 expat ca-certificates runit runit-helper jed" 9 | 10 | RUN apt-get update && apt-get -qy dist-upgrade && apt-get -qy clean && \ 11 | apt-get install -qy --no-install-recommends $RUNTIME_DEPS && \ 12 | rm -fr /tmp/* /var/tmp/* /var/cache/apt/* /var/lib/apt/lists/* /var/log/apt/* /var/log/*.log 13 | 14 | RUN update-ca-certificates 2> /dev/null || true 15 | 16 | ENV UNBOUND_GIT_URL="https://github.com/NLnetLabs/unbound.git" 17 | ENV UNBOUND_GIT_REVISION="db53ebb7985b11f21207bc13b69c8485d3054d14" 18 | 19 | WORKDIR /tmp 20 | 21 | RUN apt-get update && apt-get install -qy --no-install-recommends $BUILD_DEPS && \ 22 | git clone --depth=1000 "$UNBOUND_GIT_URL" && \ 23 | cd unbound && \ 24 | git checkout "$UNBOUND_GIT_REVISION" && \ 25 | groupadd _unbound && \ 26 | useradd -g _unbound -s /etc -d /dev/null _unbound && \ 27 | ./configure --prefix=/opt/unbound --with-pthreads \ 28 | --with-username=_unbound --with-libevent && \ 29 | make -j"$(getconf _NPROCESSORS_ONLN)" install && \ 30 | mv /opt/unbound/etc/unbound/unbound.conf /opt/unbound/etc/unbound/unbound.conf.example && \ 31 | apt-get -qy purge $BUILD_DEPS && apt-get -qy autoremove && \ 32 | rm -fr /opt/unbound/share/man && \ 33 | rm -fr /tmp/* /var/tmp/* /var/cache/apt/* /var/lib/apt/lists/* /var/log/apt/* /var/log/*.log 34 | 35 | ENV RUSTFLAGS="-C link-arg=-s" 36 | 37 | RUN apt-get update && apt-get install -qy --no-install-recommends $BUILD_DEPS && \ 38 | curl -sSf https://sh.rustup.rs | bash -s -- -y --profile minimal --default-toolchain stable && \ 39 | export PATH="$HOME/.cargo/bin:$PATH" && \ 40 | echo "Compiling encrypted-dns" && \ 41 | cargo install encrypted-dns && \ 42 | mkdir -p /opt/encrypted-dns/sbin && \ 43 | mv ~/.cargo/bin/encrypted-dns /opt/encrypted-dns/sbin/ && \ 44 | strip --strip-all /opt/encrypted-dns/sbin/encrypted-dns && \ 45 | apt-get -qy purge $BUILD_DEPS && apt-get -qy autoremove && \ 46 | rm -fr ~/.cargo ~/.rustup && \ 47 | rm -fr /tmp/* /var/tmp/* /var/cache/apt/* /var/lib/apt/lists/* /var/log/apt/* /var/log/*.log 48 | 49 | RUN groupadd _encrypted-dns && \ 50 | mkdir -p /opt/encrypted-dns/empty && \ 51 | useradd -g _encrypted-dns -s /etc -d /opt/encrypted-dns/empty _encrypted-dns && \ 52 | mkdir -m 700 -p /opt/encrypted-dns/etc/keys && \ 53 | mkdir -m 700 -p /opt/encrypted-dns/etc/lists && \ 54 | chown _encrypted-dns:_encrypted-dns /opt/encrypted-dns/etc/keys && \ 55 | mkdir -m 700 -p /opt/dnscrypt-wrapper/etc/keys && \ 56 | mkdir -m 700 -p /opt/dnscrypt-wrapper/etc/lists && \ 57 | chown _encrypted-dns:_encrypted-dns /opt/dnscrypt-wrapper/etc/keys 58 | 59 | RUN mkdir -p \ 60 | /var/svc/unbound \ 61 | /var/svc/encrypted-dns \ 62 | /var/svc/watchdog 63 | 64 | COPY --chmod=644 encrypted-dns.toml.in /opt/encrypted-dns/etc/ 65 | COPY --chmod=644 undelegated.txt /opt/encrypted-dns/etc/ 66 | 67 | COPY --chmod=755 entrypoint.sh / 68 | 69 | COPY --chmod=755 unbound.sh /var/svc/unbound/run 70 | COPY --chmod=755 unbound-check.sh /var/svc/unbound/check 71 | 72 | COPY --chmod=755 encrypted-dns.sh /var/svc/encrypted-dns/run 73 | 74 | COPY --chmod=755 watchdog.sh /var/svc/watchdog/run 75 | 76 | RUN ln -sf /opt/encrypted-dns/etc/keys/encrypted-dns.toml /opt/encrypted-dns/etc/encrypted-dns.toml 77 | 78 | VOLUME ["/opt/encrypted-dns/etc/keys"] 79 | 80 | EXPOSE 443/udp 443/tcp 9100/tcp 81 | 82 | CMD ["/entrypoint.sh", "start"] 83 | 84 | ENTRYPOINT ["/entrypoint.sh"] 85 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2025, Frank Denis 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Gitter chat](https://badges.gitter.im/gitter.svg)](https://gitter.im/dnscrypt-operators/Lobby) 2 | [![DNSCrypt](https://raw.github.com/jedisct1/dnscrypt-server-docker/master/dnscrypt-small.png)](https://dnscrypt.info) 3 | 4 | # DNSCrypt server Docker image 5 | 6 | Run your own caching, non-censoring, non-logging, DNSSEC-capable, 7 | [DNSCrypt](https://dnscrypt.info)-enabled DNS resolver virtually anywhere! 8 | 9 | If you are already familiar with Docker, it shouldn't take more than 5 minutes 10 | to get your resolver up and running. 11 | 12 | Table of contents: 13 | 14 | - [DNSCrypt server Docker image](#dnscrypt-server-docker-image) 15 | - [Example installation procedures](#example-installation-procedures) 16 | - [Installation](#installation) 17 | - [Updating the container](#updating-the-container) 18 | - [Anonymized DNS](#anonymized-dns) 19 | - [Prometheus metrics](#prometheus-metrics) 20 | - [TLS (including HTTPS and DoH) forwarding](#tls-including-https-and-doh-forwarding) 21 | - [Filtering](#filtering) 22 | - [Join the network](#join-the-network) 23 | - [Usage with Docker Compose](#usage-with-docker-compose) 24 | - [Usage with Kubernetes](#usage-with-kubernetes) 25 | - [Customizing Unbound](#customizing-unbound) 26 | - [Changing the Unbound configuration file](#changing-the-unbound-configuration-file) 27 | - [Serving custom DNS records on a local network](#serving-custom-dns-records-on-a-local-network) 28 | - [Troubleshooting](#troubleshooting) 29 | - [Deleting everything](#deleting-everything) 30 | - [Details](#details) 31 | 32 | # Example installation procedures 33 | 34 | - [How to setup your own DNSCrypt server in less than 10 minutes on Scaleway](https://github.com/dnscrypt/dnscrypt-proxy/wiki/How-to-setup-your-own-DNSCrypt-server-in-less-than-10-minutes) 35 | - [DNSCrypt server with vultr.com](https://github.com/dnscrypt/dnscrypt-proxy/wiki/DNSCrypt-server-with-vultr.com) 36 | 37 | # Installation 38 | 39 | Think about a name. This is going to be part of your DNSCrypt provider name. 40 | If you are planning to make your resolver publicly accessible, this name will 41 | be public. 42 | By convention, it has to look like a domain name (`example.com`), but it doesn't 43 | have to be an actual, registered domain. 44 | 45 | Let's pick `example.com` here. 46 | 47 | You probably need to perform the following steps as `root`. 48 | 49 | Download, create and initialize the container: 50 | 51 | ```sh 52 | docker run --name=dnscrypt-server -p 443:443/udp -p 443:443/tcp \ 53 | --restart=unless-stopped \ 54 | -v /etc/dnscrypt-server/keys:/opt/encrypted-dns/etc/keys \ 55 | jedisct1/dnscrypt-server init -N example.com -E '192.168.1.1:443' 56 | ``` 57 | 58 | This will only accept connections via DNSCrypt on the standard port (443). Replace 59 | `192.168.1.1` with the actual external IP address (not the internal Docker one) 60 | clients will connect to. 61 | 62 | IPv6 addresses should be enclosed in brackets; for example: `[2001:0db8::412f]:443`. 63 | 64 | Multiple comma-separated IPs and ports can be specified, as in `-E '192.168.1.1:443,[2001:0db8::412f]:443'`. 65 | 66 | If you want to use a different port, replace all occurrences of `443` with the alternative port in the 67 | command above (including `-p ...`). But if you have an existing website that should be accessible on 68 | port `443`, the server can transparently relay non-DNS traffic to it (see below). 69 | 70 | `-v /etc/dnscrypt-server:/opt/encrypted-dns/etc/keys` means that the path `/opt/encrypted-dns/etc/keys`, internal to the container, is mapped to `/etc/dnscrypt-server/keys`, the directory we just created before. Do not change `/opt/encrypted-dns/etc/keys`. But if you created a directory in a different location, replace `/etc/dnscrypt-server/keys` accordingly in the command above. 71 | 72 | __Note:__ on MacOS, don't use `-v ...:...`. Remove that part from the command-line, as current versions of MacOS and Docker don't seem to work well with shared directories. 73 | 74 | The `init` command will print the DNS stamp of your server. 75 | 76 | Done. 77 | 78 | You can verify that the server is running with: 79 | 80 | ```sh 81 | docker ps 82 | ``` 83 | 84 | Note: if you previously created a container with the same name, and Docker complains that the name is already in use, remove it and try again: 85 | 86 | ```sh 87 | docker rm --force dnscrypt-server 88 | ``` 89 | 90 | ## Updating the container 91 | 92 | In order to install the latest version of the image, or change parameters, use the following steps: 93 | 94 | 1. Update the image 95 | 96 | ```sh 97 | docker pull jedisct1/dnscrypt-server 98 | ``` 99 | 100 | 2. Verify that the directory containing the keys actually has the keys (a `state` directory): 101 | 102 | ```sh 103 | ls -l /etc/dnscrypt-server/keys 104 | ``` 105 | 106 | If you have some content here, skip to step 3. 107 | 108 | Nothing here? Maybe you didn't use the `-v` option to map container files to a local directory when creating the container. 109 | In that case, copy the data directly from the container: 110 | 111 | ```sh 112 | docker cp dnscrypt-server:/opt/encrypted-dns/etc/keys ~/keys 113 | ``` 114 | 115 | 3. Stop the existing container: 116 | 117 | ```sh 118 | docker stop dnscrypt-server 119 | docker ps # Check that it's not running 120 | ``` 121 | 122 | 4. Rename the existing container: 123 | 124 | ```sh 125 | docker rename dnscrypt-server dnscrypt-server-old 126 | ``` 127 | 128 | 5. Use the `init` command again and start the new container: 129 | 130 | ```sh 131 | docker run --name=dnscrypt-server -p 443:443/udp -p 443:443/tcp \ 132 | --restart=unless-stopped \ 133 | -v /etc/dnscrypt-server/keys:/opt/encrypted-dns/etc/keys \ 134 | jedisct1/dnscrypt-server init -N example.com -E '192.168.1.1:443' 135 | # (adjust accordingly) 136 | 137 | docker ps # Check that it's running 138 | ``` 139 | 140 | 6. Delete old container: 141 | 142 | ```sh 143 | docker rm dnscrypt-server-old 144 | ``` 145 | 146 | 7. Done! 147 | 148 | Parameters differ from the ones used in the previous container. 149 | 150 | For example, if you originally didn't activate relaying 151 | but want to enable it, append `-A` to the command. Or if you want to enable 152 | metrics, append `-M 0.0.0.0:9100` to the end, and `-p 9100:9100/tcp` after 153 | `-p 443:443/tcp` (see below). 154 | 155 | ## Anonymized DNS 156 | 157 | The server can be configured as a relay for the Anonymized DNSCrypt protocol by adding the `-A` switch to the `init` command. 158 | 159 | The relay DNS stamp will be printed right after the regular stamp. 160 | 161 | ## Prometheus metrics 162 | 163 | Metrics are accessible inside the container as http://127.0.0.1:9100/metrics. 164 | 165 | They can be made accessible outside of the container by adding the `-M` option followed by the listening IP and port (for example: `-M 0.0.0.0:9100`). 166 | 167 | These metrics can be indexed with [Prometheus](https://prometheus.io/) and dashboards can be created with [Grafana](https://grafana.com/). 168 | 169 | ## TLS (including HTTPS and DoH) forwarding 170 | 171 | If the DNS server is listening to port `443`, but you still want to have a web (or DoH) service accessible on that port, add the `-T` switch followed by the backend server IP and port to the `init` command (for example: `-T 10.0.0.1:4443`). 172 | 173 | The backend server must support the HTTP/2 protocol. 174 | 175 | ## Filtering 176 | 177 | The server can be used block domains. For example, the `sfw.scaleway-fr` server uses that feature to provide a service that blocks websites possibly not suitable for children. 178 | 179 | In order to do so, create a directory that will contain the blacklists: 180 | 181 | ```sh 182 | mkdir -p /etc/dnscrypt-server/lists 183 | ``` 184 | 185 | And put the list of domains to block in a file named `/etc/dnscrypt-server/lists/blacklist.txt`, one domain per line. 186 | 187 | Then, follow the upgrade procedure, adding the following option to the `docker run` command: `-v /etc/dnscrypt-server/lists:/opt/encrypted-dns/etc/lists`. 188 | 189 | # Join the network 190 | 191 | If you want to help against DNS centralization and surveillance, 192 | announce your server and/or relay on the list of [public DNS DoH and DNSCrypt servers](https://dnscrypt.info/public-servers). 193 | 194 | The best way to do so is to send a pull request to the 195 | [dnscrypt-resolvers](https://github.com/DNSCrypt/dnscrypt-resolvers/) repository. 196 | 197 | # Usage with Kubernetes 198 | 199 | Kubernetes configurations are located in the `kube` directory. Currently these assume 200 | a persistent disk named `dnscrypt-keys` on GCE. You will need to adjust the volumes 201 | definition on other platforms. Once that is setup, you can have a dnscrypt server up 202 | in minutes. 203 | 204 | - Create a static IP on GCE. This will be used for the LoadBalancer. 205 | - Edit `kube/dnscrypt-init-job.yml`. Change `example.com` to your desired hostname 206 | and `127.0.0.1` to your static IP. 207 | - Edit `kube/dnscrypt-srv.yml` and change `loadBalancerIP` to your static IP in both locations. 208 | - Run `kubectl create -f kube/dnscrypt-init-job.yml` to setup your keys. 209 | - Run `kubectl create -f kube/dnscrypt-deployment.yml` to deploy the dnscrypt server. 210 | - Run `kubectl create -f kube/dnscrypt-srv.yml` to expose your server to the world. 211 | 212 | To get your public key just view the logs for the `dnscrypt-init` job. The public 213 | IP for your server is merely the `dnscrypt` service address. 214 | 215 | # Usage with Docker Compose 216 | 217 | You can setup a server very quickly with Docker Compose. 218 | 219 | - Run `docker-compose up` 220 | - Ctrl-C after keys are setup. 221 | - Edit `docker-compose.yml` to use the start command. 222 | - Run `docker-compose up` 223 | 224 | Now you will have a local server running on port 5443. 225 | 226 | # Customizing Unbound 227 | 228 | ## Changing the Unbound configuration file 229 | 230 | To add new configuration to Unbound, add files to the `/opt/unbound/etc/unbound/zones` 231 | directory. All files ending in `.conf` will be processed. In this manner, you 232 | can add any directives to the `server:` section of the Unbound configuration. 233 | 234 | ## Serving custom DNS records on a local network 235 | 236 | While Unbound is not a full authoritative name server, it supports resolving 237 | custom entries in a way that is serviceable on a small, private LAN. You can use 238 | unbound to resolve private hostnames such as `my-computer.example.com` within 239 | your LAN. 240 | 241 | To support such custom entries using this image, first map a volume to the zones 242 | directory. Add this to your `docker run` line: 243 | 244 | ```text 245 | -v /etc/dnscrypt-server/zones:/opt/unbound/etc/unbound/zones 246 | ``` 247 | 248 | The whole command to create and initialize a container would look something like 249 | this: 250 | 251 | ```sh 252 | docker run --name=dnscrypt-server \ 253 | -v /etc/dnscrypt-server/zones:/opt/unbound/etc/unbound/zones \ 254 | -p 443:443/udp -p 443:443/tcp --net=host \ 255 | jedisct1/dnscrypt-server init -N example.com -E '192.168.1.1:443' 256 | ``` 257 | 258 | Create a new `.conf` file: 259 | 260 | ```sh 261 | touch /etc/dnscrypt-server/zones/example.conf 262 | ``` 263 | 264 | Now, add one or more unbound directives to the file, such as: 265 | 266 | ```zone 267 | local-zone: "example.com." static 268 | local-data: "my-computer.example.com. IN A 10.0.0.1" 269 | local-data: "other-computer.example.com. IN A 10.0.0.2" 270 | ``` 271 | 272 | ## Troubleshooting 273 | 274 | If Unbound doesn't like one of the newly added directives, it 275 | will probably not respond over the network. In that case, here are some commands 276 | to work out what is wrong: 277 | 278 | ```sh 279 | docker logs dnscrypt-server 280 | docker exec dnscrypt-server /opt/unbound/sbin/unbound-checkconf 281 | ``` 282 | 283 | # Deleting everything 284 | 285 | In order to delete everything (containers and images), type: 286 | 287 | ```sh 288 | docker rm --force dnscrypt-server ||: 289 | docker rmi --force jedisct1/dnscrypt-server ||: 290 | ``` 291 | 292 | # Details 293 | 294 | - A minimal Ubuntu Linux as a base image. 295 | - Caching resolver: [Unbound](https://www.unbound.net/), with DNSSEC, prefetching, 296 | and no logs. The number of threads and memory usage are automatically adjusted. 297 | Latest stable version, compiled from source. qname minimisation is enabled. 298 | - [encrypted-dns-server](https://github.com/jedisct1/encrypted-dns-server). 299 | Compiled from source. 300 | 301 | Keys and certificates are automatically rotated every 8 hour. 302 | -------------------------------------------------------------------------------- /dnscrypt-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DNSCrypt/dnscrypt-server-docker/f3496ae1a3711551677b7dbf89461623058a2cd2/dnscrypt-small.png -------------------------------------------------------------------------------- /dnscrypt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DNSCrypt/dnscrypt-server-docker/f3496ae1a3711551677b7dbf89461623058a2cd2/dnscrypt.png -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "4" 2 | services: 3 | dnscrypt: 4 | image: jedisct1/dnscrypt-server:latest 5 | container_name: dnscrypt 6 | restart: always 7 | command: "init -N example.com -E '127.0.0.1:5443'" 8 | # command: "start" 9 | ports: 10 | - '5443:5443/udp' 11 | - '5443:5443/tcp' 12 | volumes: 13 | - keys:/opt/encrypted-dns/etc/keys 14 | environment: 15 | - TZ='UTC' 16 | volumes: 17 | keys: 18 | -------------------------------------------------------------------------------- /encrypted-dns.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | CONF_DIR="/opt/encrypted-dns/etc" 4 | KEYS_DIR="/opt/encrypted-dns/etc/keys" 5 | CONFIG_FILE="${CONF_DIR}/encrypted-dns.toml" 6 | 7 | if [ ! -f "$KEYS_DIR/provider_name" ]; then 8 | exit 1 9 | fi 10 | 11 | chown -R _encrypted-dns:_encrypted-dns /opt/dnscrypt-wrapper/etc/keys 2>/dev/null || : 12 | chown -R _encrypted-dns:_encrypted-dns /opt/encrypted-dns/etc/keys 2>/dev/null || : 13 | 14 | exec /opt/encrypted-dns/sbin/encrypted-dns --config "$CONFIG_FILE" 15 | -------------------------------------------------------------------------------- /encrypted-dns.toml.in: -------------------------------------------------------------------------------- 1 | #################################################### 2 | # # 3 | # Encrypted DNS Server configuration # 4 | # # 5 | #################################################### 6 | 7 | 8 | 9 | ################################## 10 | # Global settings # 11 | ################################## 12 | 13 | 14 | ## IP addresses and ports to listen to, as well as their external IP 15 | ## If there is no NAT involved, `local` and `external` can be the same. 16 | ## As many addresses as needed can be configured here, IPv4 and/or IPv6. 17 | ## You should at least change the `external` IP address. 18 | 19 | ### Example with both IPv4 and IPv6 addresses: 20 | # listen_addrs = [ 21 | # { local = "0.0.0.0:443", external = "198.51.100.1:443" }, 22 | # { local = "[::]:443", external = "[2001:db8::1]:443" } 23 | # ] 24 | 25 | listen_addrs = [ 26 | @LISTEN_ADDRESSES@ 27 | ] 28 | 29 | 30 | ## Upstream DNS server and port 31 | 32 | upstream_addr = "127.0.0.1:553" 33 | 34 | 35 | ## File name to save the state to 36 | 37 | state_file = "/opt/encrypted-dns/etc/keys/state/encrypted-dns.state" 38 | 39 | 40 | ## UDP timeout in seconds 41 | 42 | udp_timeout = 10 43 | 44 | 45 | ## TCP timeout in seconds 46 | 47 | tcp_timeout = 10 48 | 49 | 50 | ## Maximum active UDP sockets 51 | 52 | udp_max_active_connections = 1000 53 | 54 | 55 | ## Maximum active TCP connections 56 | 57 | tcp_max_active_connections = 100 58 | 59 | 60 | ## Optional IP address to connect to upstream servers from. 61 | ## Leave commented/undefined to automatically select it. 62 | 63 | # external_addr = "0.0.0.0" 64 | 65 | 66 | ## Built-in DNS cache capacity 67 | 68 | cache_capacity = 150000 69 | 70 | 71 | ## DNS cache: minimum TTL 72 | 73 | cache_ttl_min = 3600 74 | 75 | 76 | ## DNS cache: max TTL 77 | 78 | cache_ttl_max = 86400 79 | 80 | 81 | ## DNS cache: error TTL 82 | 83 | cache_ttl_error = 600 84 | 85 | 86 | ## DNS cache: to avoid bursts of traffic for popular queries when an 87 | ## RRSET expires, hold a TTL received from an upstream server for 88 | ## `client_ttl_holdon` seconds before decreasing it in client responses. 89 | 90 | client_ttl_holdon = 60 91 | 92 | 93 | ## Run as a background process 94 | 95 | daemonize = false 96 | 97 | 98 | ## Log file 99 | 100 | # log_file = "/tmp/encrypted-dns.log" 101 | 102 | 103 | ## PID file 104 | 105 | # pid_file = "/tmp/encrypted-dns.pid" 106 | 107 | 108 | ## User name to drop privileges to, when started as root. 109 | 110 | user = "_encrypted-dns" 111 | 112 | 113 | ## Group name to drop privileges to, when started as root. 114 | 115 | group = "_encrypted-dns" 116 | 117 | 118 | ## Path to chroot() to, when started as root. 119 | ## The path to the state file is relative to the chroot base. 120 | 121 | # chroot = "/var/empty" 122 | 123 | 124 | ## Queries sent to that name will return the client IP address. 125 | ## This can be very useful for debugging, or to check that relaying works. 126 | 127 | # my_ip = "my.ip" 128 | 129 | 130 | #################################### 131 | # DNSCrypt settings # 132 | #################################### 133 | 134 | [dnscrypt] 135 | 136 | ## Provider name (with or without the `2.dnscrypt-cert.` prefix) 137 | 138 | provider_name = "@PROVIDER_NAME@" 139 | 140 | 141 | ## Does the server support DNSSEC? 142 | 143 | dnssec = true 144 | 145 | 146 | ## Does the server always returns correct answers (no filtering, including ad blocking)? 147 | 148 | no_filters = true 149 | 150 | 151 | ## Set to `true` if the server doesn't keep any information that can be used to identify users 152 | 153 | no_logs = true 154 | 155 | 156 | ## Key cache capacity, per certificate 157 | 158 | key_cache_capacity = 10000 159 | 160 | 161 | 162 | ############################### 163 | # TLS settings # 164 | ############################### 165 | 166 | [tls] 167 | 168 | ## Where to proxy TLS connections to (e.g. DoH server) 169 | 170 | # upstream_addr = "127.0.0.1:4343" 171 | 172 | @TLS_PROXY_CONFIGURATION@ 173 | 174 | 175 | 176 | ####################################### 177 | # Server-side filtering # 178 | ####################################### 179 | 180 | [filtering] 181 | 182 | ## List of domains to block, one per line 183 | 184 | @DOMAIN_BLACKLIST_CONFIGURATION@ 185 | 186 | 187 | ## List of undelegated TLDs 188 | ## This is the list of nonexistent TLDs that queries are frequently observed for, 189 | ## but will never resolve to anything. The server will immediately return a 190 | ## synthesized NXDOMAIN response instead of hitting root servers. 191 | 192 | undelegated_list = "/opt/encrypted-dns/etc/undelegated.txt" 193 | 194 | 195 | ## Ignore A and AAAA queries for unqualified host names. 196 | 197 | ignore_unqualified_hostnames = true 198 | 199 | 200 | 201 | ######################### 202 | # Metrics # 203 | ######################### 204 | 205 | [metrics] 206 | 207 | type = "prometheus" 208 | listen_addr = "@METRICS_ADDRESS@" 209 | path = "/metrics" 210 | 211 | 212 | 213 | ################################ 214 | # Anonymized DNS # 215 | ################################ 216 | 217 | [anonymized_dns] 218 | 219 | # Enable relaying support for Anonymized DNS 220 | 221 | enabled = @ANONDNS_ENABLED@ 222 | 223 | 224 | # Allowed upstream ports 225 | # This is a list of commonly used ports for encrypted DNS services 226 | 227 | allowed_ports = [ 443, 553, 853, 1443, 2053, 4343, 4434, 4443, 5353, 5443, 8443, 15353 ] 228 | 229 | 230 | # Allow all ports >= 1024 in addition to the list above 231 | 232 | allow_non_reserved_ports = false 233 | 234 | 235 | # Blacklisted upstream IP addresses 236 | 237 | blacklisted_ips = [ @ANONDNS_BLACKLISTED_IPS@ ] 238 | 239 | 240 | 241 | 242 | ################################ 243 | # Access control # 244 | ################################ 245 | 246 | [access_control] 247 | 248 | # Enable access control 249 | 250 | enabled = false 251 | 252 | # Only allow access to client queries including one of these random tokens 253 | # Tokens can be configured in the `query_meta` section of `dnscrypt-proxy` as 254 | # `query_meta = ["token:..."]` -- Replace ... with the token to use by the client. 255 | # Example: `query_meta = ["token:Y2oHkDJNHz"]` 256 | 257 | tokens = ["Y2oHkDJNHz", "G5zY3J5cHQtY", "C5zZWN1cmUuZG5z"] 258 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | set -e 4 | 5 | action="$1" 6 | 7 | LEGACY_KEYS_DIR="/opt/dnscrypt-wrapper/etc/keys" 8 | LEGACY_LISTS_DIR="/opt/dnscrypt-wrapper/etc/lists" 9 | LEGACY_STATE_DIR="${LEGACY_KEYS_DIR}/state" 10 | KEYS_DIR="/opt/encrypted-dns/etc/keys" 11 | STATE_DIR="${KEYS_DIR}/state" 12 | LISTS_DIR="/opt/encrypted-dns/etc/lists" 13 | CONF_DIR="/opt/encrypted-dns/etc" 14 | CONFIG_FILE="${KEYS_DIR}/encrypted-dns.toml" 15 | CONFIG_FILE_TEMPLATE="${CONF_DIR}/encrypted-dns.toml.in" 16 | SERVICES_DIR="/etc/runit/runsvdir/svmanaged" 17 | 18 | init() { 19 | if [ "$(is_initialized)" = yes ]; then 20 | start 21 | exit $? 22 | fi 23 | 24 | anondns_enabled="false" 25 | anondns_blacklisted_ips="" 26 | 27 | metrics_address="127.0.0.1:9100" 28 | 29 | while getopts "h?N:E:T:AM:" opt; do 30 | case "$opt" in 31 | h | \?) usage ;; 32 | N) provider_name=$(echo "$OPTARG" | sed -e 's/^[ \t]*//' | tr A-Z a-z) ;; 33 | E) ext_addresses=$(echo "$OPTARG" | sed -e 's/^[ \t]*//' | tr A-Z a-z) ;; 34 | T) tls_proxy_upstream_address=$(echo "$OPTARG" | sed -e 's/^[ \t]*//' | tr A-Z a-z) ;; 35 | A) anondns_enabled="true" ;; 36 | M) metrics_address=$(echo "$OPTARG" | sed -e 's/^[ \t]*//' | tr A-Z a-z) ;; 37 | esac 38 | done 39 | [ -z "$provider_name" ] && usage 40 | case "$provider_name" in 41 | .*) usage ;; 42 | 2.dnscrypt-cert.*) ;; 43 | *) provider_name="2.dnscrypt-cert.${provider_name}" ;; 44 | esac 45 | 46 | [ -z "$ext_addresses" ] && usage 47 | case "$ext_addresses" in 48 | .*) usage ;; 49 | 0.*) 50 | echo "Do not use 0.0.0.0, use an actual external IP address" >&2 51 | exit 1 52 | ;; 53 | esac 54 | listen_addresses=$(get_listen_addresses "$ext_addresses") 55 | 56 | tls_proxy_configuration="" 57 | if [ -n "$tls_proxy_upstream_address" ]; then 58 | tls_proxy_configuration="upstream_addr = \"${tls_proxy_upstream_address}\"" 59 | fi 60 | 61 | domain_blacklist_file="${LISTS_DIR}/blacklist.txt" 62 | domain_blacklist_configuration="" 63 | if [ -s "$domain_blacklist_file" ]; then 64 | chown _encrypted-dns:_encrypted-dns "$domain_blacklist_file" 65 | domain_blacklist_configuration="domain_blacklist = \"${domain_blacklist_file}\"" 66 | fi 67 | 68 | echo "Provider name: [$provider_name]" 69 | 70 | echo "$provider_name" >"${KEYS_DIR}/provider_name" 71 | chmod 644 "${KEYS_DIR}/provider_name" 72 | 73 | sed \ 74 | -e "s#@PROVIDER_NAME@#${provider_name}#" \ 75 | -e "s#@LISTEN_ADDRESSES@#${listen_addresses}#" \ 76 | -e "s#@TLS_PROXY_CONFIGURATION@#${tls_proxy_configuration}#" \ 77 | -e "s#@DOMAIN_BLACKLIST_CONFIGURATION@#${domain_blacklist_configuration}#" \ 78 | -e "s#@ANONDNS_ENABLED@#${anondns_enabled}#" \ 79 | -e "s#@ANONDNS_BLACKLISTED_IPS@#${anondns_blacklisted_ips}#" \ 80 | -e "s#@METRICS_ADDRESS@#${metrics_address}#" \ 81 | "$CONFIG_FILE_TEMPLATE" >"$CONFIG_FILE" 82 | 83 | mkdir -p -m 700 "${STATE_DIR}" 84 | chown _encrypted-dns:_encrypted-dns "${STATE_DIR}" 85 | 86 | if [ -f "${KEYS_DIR}/secret.key" ]; then 87 | echo "Importing the previous secret key [${KEYS_DIR}/secret.key]" 88 | /opt/encrypted-dns/sbin/encrypted-dns \ 89 | --config "$CONFIG_FILE" \ 90 | --import-from-dnscrypt-wrapper "${KEYS_DIR}/secret.key" \ 91 | --dry-run >/dev/null || exit 1 92 | mv -f "${KEYS_DIR}/secret.key" "${KEYS_DIR}/secret.key.migrated" 93 | fi 94 | 95 | /opt/encrypted-dns/sbin/encrypted-dns \ 96 | --config "$CONFIG_FILE" --dry-run | 97 | tee "${KEYS_DIR}/provider-info.txt" 98 | 99 | echo 100 | echo ----------------------------------------------------------------------- 101 | echo 102 | echo "Congratulations! The container has been properly initialized." 103 | echo "Take a look up above at the way dnscrypt-proxy has to be configured in order" 104 | echo "to connect to your resolver. Then, start the container with the default command." 105 | } 106 | 107 | provider_info() { 108 | ensure_initialized 109 | echo 110 | cat "${KEYS_DIR}/provider-info.txt" 111 | echo 112 | } 113 | 114 | legacy_compat() { 115 | if [ -f "${KEYS_DIR}/provider-info.txt" ] && [ -f "${KEYS_DIR}/provider_name" ]; then 116 | return 0 117 | fi 118 | if [ -f "${LEGACY_KEYS_DIR}/provider-info.txt" ] && [ -f "${LEGACY_KEYS_DIR}/provider_name" ]; then 119 | echo "Using [${LEGACY_KEYS_DIR}] for keys" >&2 120 | mkdir -p -m 755 "${KEYS_DIR}" 121 | mv -f "${KEYS_DIR}/provider-info.txt" "${KEYS_DIR}/provider-info.txt.migrated" 2>/dev/null || : 122 | ln -s "${LEGACY_KEYS_DIR}/provider-info.txt" "${KEYS_DIR}/provider-info.txt" 2>/dev/null || : 123 | mv -f "${KEYS_DIR}/provider_name" "${KEYS_DIR}/provider_name.migrated" 2>/dev/null || : 124 | ln -s "${LEGACY_KEYS_DIR}/provider_name" "${KEYS_DIR}/provider_name" 2>/dev/null || : 125 | mv -f "${KEYS_DIR}/secret.key" "${KEYS_DIR}/secret.key.migrated" 2>/dev/null || : 126 | ln -s "${LEGACY_KEYS_DIR}/secret.key" "${KEYS_DIR}/secret.key" 2>/dev/null || : 127 | mkdir -p -m 700 "${LEGACY_STATE_DIR}" 128 | chown _encrypted-dns:_encrypted-dns "${KEYS_DIR}" "${STATE_DIR}" "${LEGACY_STATE_DIR}" 129 | mv -f "$STATE_DIR" "${STATE_DIR}.migrated" 2>/dev/null || : 130 | ln -s "$LEGACY_STATE_DIR" "${STATE_DIR}" 2>/dev/null || : 131 | fi 132 | if [ -f "${LEGACY_LISTS_DIR}/blacklist.txt" ]; then 133 | echo "Using [${LEGACY_LISTS_DIR}] for lists" >&2 134 | mkdir -p -m 755 "${LISTS_DIR}" 135 | mv -f "${LISTS_DIR}/blacklist.txt" "${LISTS_DIR}/blacklist.txt.migrated" 2>/dev/null || : 136 | ln -s "${LEGACY_LISTS_DIR}/blacklist.txt" "${LISTS_DIR}/blacklist.txt" 2>/dev/null || : 137 | chown _encrypted-dns:_encrypted-dns "${LISTS_DIR}" "${LEGACY_LISTS_DIR}/blacklist.txt" 138 | fi 139 | } 140 | 141 | is_initialized() { 142 | if [ -f "$CONFIG_FILE" ] && [ -f "${STATE_DIR}/encrypted-dns.state" ] && [ -f "${KEYS_DIR}/provider-info.txt" ] && [ -f "${KEYS_DIR}/provider_name" ]; then 143 | echo yes 144 | else 145 | legacy_compat 146 | if [ -f "$CONFIG_FILE" ] && [ -f "${STATE_DIR}/encrypted-dns.state" ] && [ -f "${KEYS_DIR}/provider-info.txt" ] && [ -f "${KEYS_DIR}/provider_name" ]; then 147 | echo yes 148 | else 149 | echo no 150 | fi 151 | fi 152 | } 153 | 154 | ensure_initialized() { 155 | if [ "$(is_initialized)" = no ]; then 156 | if [ -d "$LEGACY_KEYS_DIR" ]; then 157 | echo "Please provide an initial configuration (init -N -E )" >&2 158 | fi 159 | exit 1 160 | fi 161 | } 162 | 163 | start() { 164 | ensure_initialized 165 | if [ -f "${KEYS_DIR}/secret.key" ]; then 166 | echo "Importing the previous secret key [${KEYS_DIR}/secret.key]" 167 | /opt/encrypted-dns/sbin/encrypted-dns \ 168 | --config "$CONFIG_FILE" \ 169 | --import-from-dnscrypt-wrapper "${KEYS_DIR}/secret.key" \ 170 | --dry-run >/dev/null || exit 1 171 | mv -f "${KEYS_DIR}/secret.key" "${KEYS_DIR}/secret.key.migrated" 172 | fi 173 | /opt/encrypted-dns/sbin/encrypted-dns \ 174 | --config "$CONFIG_FILE" --dry-run | 175 | tee "${KEYS_DIR}/provider-info.txt" 176 | 177 | find /var/svc -mindepth 1 -maxdepth 1 -type d | while read -r service; do 178 | ln -s -f "$service" "${SERVICES_DIR}/" 179 | done 180 | 181 | exec /etc/runit/2 /dev/null 2>/dev/null 182 | } 183 | 184 | shell() { 185 | exec /bin/bash 186 | } 187 | 188 | is_ipv6() { 189 | case "$1" in 190 | \[[a-fA-F0-9:.]*\]:[0-9]*) 191 | echo yes 192 | ;; 193 | [0-9.]*:[0-9]*) 194 | echo no 195 | ;; 196 | *) 197 | echo "IP and port should be specified as 'ipv4_addr:port' or '[ipv6_addr]:port'" >&2 198 | exit 1 199 | ;; 200 | esac 201 | } 202 | 203 | get_listen_addresses() { 204 | listen_addresses="" 205 | ext_addresses="$1" 206 | OIFS="$IFS" 207 | IFS="," 208 | for ext_address in $ext_addresses; do 209 | localport=$(echo "$ext_address" | sed -E 's/.*:([0-9]*)$/\1/') 210 | if [ -z "$localport" ]; then 211 | localport="443" 212 | fi 213 | entry="{ local = " 214 | v6=$(is_ipv6 "$ext_address") 215 | if [ "$v6" = "yes" ]; then 216 | entry="${entry}\"[::]:${localport}\"" 217 | else 218 | entry="${entry}\"0.0.0.0:${localport}\"" 219 | fi 220 | entry="${entry}, external = \"${ext_address}\" }" 221 | if [ -n "$listen_addresses" ]; then 222 | listen_addresses="${listen_addresses}, " 223 | fi 224 | listen_addresses="${listen_addresses}${entry}" 225 | done 226 | IFS="$OIFS" 227 | echo "${listen_addresses}" 228 | } 229 | 230 | usage() { 231 | cat < -E :[,:...] 236 | initialize the container for a server accessible at ip on port 237 | , for a provider named . This is required only once. 238 | 239 | If TLS connections to the same port have to be redirected to a HTTPS server 240 | (e.g. for DoH), add -T : 241 | 242 | To enable Anonymized DNS relaying, add -A. 243 | 244 | * start (default command): start the resolver and the dnscrypt server proxy. 245 | Ports 443/udp and 443/tcp have to be publicly exposed. 246 | 247 | * provider-info: prints the provider name and provider public key. 248 | 249 | * shell: run a shell. 250 | 251 | This container has a single volume that you might want to securely keep a 252 | backup of: /opt/encrypted-dns/etc/keys 253 | EOT 254 | exit 1 255 | } 256 | 257 | case "$action" in 258 | start) start ;; 259 | init) 260 | shift 261 | init "$@" 262 | ;; 263 | provider-info) provider_info ;; 264 | shell) shell ;; 265 | *) usage ;; 266 | esac 267 | -------------------------------------------------------------------------------- /kube/dnscrypt-deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | namespace: default 5 | labels: 6 | service: dnscrypt 7 | name: dnscrypt 8 | spec: 9 | strategy: 10 | type: Recreate 11 | replicas: 1 12 | selector: 13 | matchLabels: 14 | service: dnscrypt 15 | template: 16 | metadata: 17 | labels: 18 | service: dnscrypt 19 | spec: 20 | containers: 21 | - image: zquestz/dnscrypt-server:latest 22 | imagePullPolicy: Always 23 | name: dnscrypt 24 | ports: 25 | - containerPort: 5443 26 | protocol: UDP 27 | - containerPort: 5443 28 | protocol: TCP 29 | volumeMounts: 30 | - name: dnscrypt-keys 31 | mountPath: /opt/encrypted-dns/etc/keys 32 | command: ["/entrypoint.sh", "start"] 33 | resources: 34 | requests: 35 | memory: "64Mi" 36 | restartPolicy: Always 37 | volumes: 38 | - name: dnscrypt-keys 39 | gcePersistentDisk: 40 | pdName: dnscrypt-keys 41 | fsType: ext4 42 | -------------------------------------------------------------------------------- /kube/dnscrypt-init-job.yml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: dnscrypt-init 5 | spec: 6 | template: 7 | metadata: 8 | name: dnscrypt-init 9 | spec: 10 | containers: 11 | - name: dnscrypt-init 12 | image: zquestz/dnscrypt-server:latest 13 | imagePullPolicy: Always 14 | command: ["/entrypoint.sh", "init", "-A", "-M", "0.0.0.0:9100", "-N", "example.com", "-E", "127.0.0.1:5443"] 15 | volumeMounts: 16 | - name: dnscrypt-keys 17 | mountPath: /opt/encrypted-dns/etc/keys 18 | restartPolicy: Never 19 | volumes: 20 | - name: dnscrypt-keys 21 | gcePersistentDisk: 22 | pdName: dnscrypt-keys 23 | fsType: ext4 24 | -------------------------------------------------------------------------------- /kube/dnscrypt-srv.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: dnscrypt-tcp 5 | namespace: default 6 | annotations: 7 | cloud.google.com/network-tier: Standard 8 | spec: 9 | ports: 10 | - protocol: TCP 11 | port: 5443 12 | targetPort: 5443 13 | selector: 14 | service: dnscrypt 15 | type: LoadBalancer 16 | loadBalancerIP: 0.0.0.0 17 | externalTrafficPolicy: Local 18 | --- 19 | apiVersion: v1 20 | kind: Service 21 | metadata: 22 | name: dnscrypt-udp 23 | namespace: default 24 | annotations: 25 | cloud.google.com/network-tier: Standard 26 | spec: 27 | ports: 28 | - protocol: UDP 29 | port: 5443 30 | targetPort: 5443 31 | selector: 32 | service: dnscrypt 33 | type: LoadBalancer 34 | loadBalancerIP: 0.0.0.0 35 | externalTrafficPolicy: Local 36 | -------------------------------------------------------------------------------- /scripts/install-centos.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | 5 | yum -y update 6 | 7 | SERVER="$(hostname)" 8 | export SERVER 9 | SERVER_IP="$(ip route get 1 | awk '{print $NF;exit}')" 10 | export SERVER_IP 11 | echo "$SERVER" 12 | echo "$SERVER_IP" 13 | 14 | ( 15 | exec 2>/dev/null 16 | 17 | if ! [ -x "$(command -v docker)" ]; then 18 | yum install -y docker 19 | fi 20 | 21 | docker stop dnscrypt-server 22 | docker stop watchtower 23 | docker rm dnscrypt-server 24 | docker rm watchtower 25 | docker container prune -f 26 | docker volume prune -f 27 | docker image prune -f 28 | 29 | yum remove -y firewalld 30 | yum remove -y iptables-services 31 | ) 32 | 33 | mkdir -p /etc/dnscrypt-server/lists 34 | if [ -d /root/keys ]; then 35 | mv /root/keys /etc/dnscrypt-server 36 | fi 37 | mkdir -p /etc/dnscrypt-server/keys 38 | 39 | if [ -f /etc/dnscrypt-server/keys/state/encrypted-dns.state ]; then 40 | docker run \ 41 | --ulimit nofile=90000:90000 \ 42 | -v /etc/dnscrypt-server/keys:/opt/encrypted-dns/etc/keys \ 43 | -v /etc/dnscrypt-server/lists:/opt/encrypted-dns/etc/lists \ 44 | --name=dnscrypt-server -p 443:443/udp -p 443:443/tcp \ 45 | -d jedisct1/dnscrypt-server start 46 | else 47 | docker run \ 48 | --ulimit nofile=90000:90000 \ 49 | -v /etc/dnscrypt-server/keys:/opt/encrypted-dns/etc/keys \ 50 | -v /etc/dnscrypt-server/lists:/opt/encrypted-dns/etc/lists \ 51 | --name=dnscrypt-server -p 443:443/udp -p 443:443/tcp \ 52 | jedisct1/dnscrypt-server init -N "$SERVER" -E "${SERVER_IP}:443" 53 | docker start dnscrypt-server 54 | fi 55 | 56 | cat /etc/dnscrypt-server/keys/provider-info.txt 57 | 58 | docker update --restart=unless-stopped dnscrypt-server 59 | 60 | docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower dnscrypt-server 61 | docker update --restart=unless-stopped watchtower 62 | 63 | ln -sf /etc/dnscrypt-server/keys /root 64 | 65 | echo 3 >/proc/sys/vm/drop_caches 66 | 67 | if [ ! -L /etc/motd ]; then 68 | rm -f /etc/motd 69 | ln -s /etc/dnscrypt-server/keys/provider-info.txt /etc/motd 70 | reboot 71 | fi 72 | -------------------------------------------------------------------------------- /unbound-check.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | drill -DQ -p 553 NS . @127.0.0.1 && 4 | drill -tDQ -p 553 NS . @127.0.0.1 5 | -------------------------------------------------------------------------------- /unbound.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | KEYS_DIR="/opt/encrypted-dns/etc/keys" 4 | ZONES_DIR="/opt/unbound/etc/unbound/zones" 5 | 6 | reserved=134217728 7 | availableMemory=$((1024 * $( (grep -F MemAvailable /proc/meminfo || grep -F MemTotal /proc/meminfo) | sed 's/[^0-9]//g'))) 8 | if [ $availableMemory -le $((reserved * 2)) ]; then 9 | echo "Not enough memory" >&2 10 | exit 1 11 | fi 12 | availableMemory=$((availableMemory - reserved)) 13 | msg_cache_size=$((availableMemory / 4)) 14 | rr_cache_size=$((availableMemory / 3)) 15 | nproc=$(nproc) 16 | if [ "$nproc" -gt 1 ]; then 17 | threads=$((nproc - 1)) 18 | else 19 | threads=1 20 | fi 21 | 22 | provider_name=$(cat "$KEYS_DIR/provider_name") 23 | 24 | sed \ 25 | -e "s/@MSG_CACHE_SIZE@/${msg_cache_size}/" \ 26 | -e "s/@PROVIDER_NAME@/${provider_name}/" \ 27 | -e "s/@RR_CACHE_SIZE@/${rr_cache_size}/" \ 28 | -e "s/@THREADS@/${threads}/" \ 29 | -e "s#@ZONES_DIR@#${ZONES_DIR}#" \ 30 | >/opt/unbound/etc/unbound/unbound.conf </dev/null || : 152 | fi 153 | 154 | mkdir -p /opt/unbound/etc/unbound/zones 155 | 156 | exec /opt/unbound/sbin/unbound 157 | -------------------------------------------------------------------------------- /undelegated.txt: -------------------------------------------------------------------------------- 1 | 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa 2 | 0.in-addr.arpa 3 | 1 4 | 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa 5 | 10.in-addr.arpa 6 | 100.100.in-addr.arpa 7 | 100.51.198.in-addr.arpa 8 | 101.100.in-addr.arpa 9 | 102.100.in-addr.arpa 10 | 103.100.in-addr.arpa 11 | 104.100.in-addr.arpa 12 | 105.100.in-addr.arpa 13 | 106.100.in-addr.arpa 14 | 107.100.in-addr.arpa 15 | 108.100.in-addr.arpa 16 | 109.100.in-addr.arpa 17 | 110.100.in-addr.arpa 18 | 111.100.in-addr.arpa 19 | 112.100.in-addr.arpa 20 | 113.0.203.in-addr.arpa 21 | 113.100.in-addr.arpa 22 | 114.100.in-addr.arpa 23 | 115.100.in-addr.arpa 24 | 116.100.in-addr.arpa 25 | 117.100.in-addr.arpa 26 | 118.100.in-addr.arpa 27 | 119.100.in-addr.arpa 28 | 120.100.in-addr.arpa 29 | 121.100.in-addr.arpa 30 | 122.100.in-addr.arpa 31 | 123.100.in-addr.arpa 32 | 124.100.in-addr.arpa 33 | 125.100.in-addr.arpa 34 | 126.100.in-addr.arpa 35 | 127.100.in-addr.arpa 36 | 127.in-addr.arpa 37 | 16.172.in-addr.arpa 38 | 168.192.in-addr.arpa 39 | 17.172.in-addr.arpa 40 | 18.172.in-addr.arpa 41 | 19.172.in-addr.arpa 42 | 2.0.192.in-addr.arpa 43 | 20.172.in-addr.arpa 44 | 21.172.in-addr.arpa 45 | 22.172.in-addr.arpa 46 | 23.172.in-addr.arpa 47 | 24.172.in-addr.arpa 48 | 25.172.in-addr.arpa 49 | 254.169.in-addr.arpa 50 | 255.255.255.255.in-addr.arpa 51 | 26.172.in-addr.arpa 52 | 27.172.in-addr.arpa 53 | 28.172.in-addr.arpa 54 | 29.172.in-addr.arpa 55 | 30.172.in-addr.arpa 56 | 31.172.in-addr.arpa 57 | 64.100.in-addr.arpa 58 | 65.100.in-addr.arpa 59 | 66.100.in-addr.arpa 60 | 67.100.in-addr.arpa 61 | 68.100.in-addr.arpa 62 | 69.100.in-addr.arpa 63 | 70.100.in-addr.arpa 64 | 71.100.in-addr.arpa 65 | 72.100.in-addr.arpa 66 | 73.100.in-addr.arpa 67 | 74.100.in-addr.arpa 68 | 75.100.in-addr.arpa 69 | 76.100.in-addr.arpa 70 | 77.100.in-addr.arpa 71 | 78.100.in-addr.arpa 72 | 79.100.in-addr.arpa 73 | 8.b.d.0.1.0.0.2.ip6.arpa 74 | 8.e.f.ip6.arpa 75 | 80.100.in-addr.arpa 76 | 81.100.in-addr.arpa 77 | 82.100.in-addr.arpa 78 | 83.100.in-addr.arpa 79 | 84.100.in-addr.arpa 80 | 85.100.in-addr.arpa 81 | 86.100.in-addr.arpa 82 | 87.100.in-addr.arpa 83 | 88.100.in-addr.arpa 84 | 89.100.in-addr.arpa 85 | 9.e.f.ip6.arpa 86 | 90.100.in-addr.arpa 87 | 91.100.in-addr.arpa 88 | 92.100.in-addr.arpa 89 | 93.100.in-addr.arpa 90 | 94.100.in-addr.arpa 91 | 95.100.in-addr.arpa 92 | 96.100.in-addr.arpa 93 | 97.100.in-addr.arpa 94 | 98.100.in-addr.arpa 95 | 99.100.in-addr.arpa 96 | a.e.f.ip6.arpa 97 | airdream 98 | api 99 | b.e.f.ip6.arpa 100 | bbrouter 101 | belkin 102 | blinkap 103 | corp 104 | d.f.ip6.arpa 105 | davolink 106 | dearmyrouter 107 | dhcp 108 | dlink 109 | domain 110 | envoy 111 | example 112 | f.f.ip6.arpa 113 | grp 114 | gw== 115 | home 116 | hub 117 | internal 118 | intra 119 | intranet 120 | invalid 121 | ksyun 122 | lan 123 | loc 124 | local 125 | localdomain 126 | localhost 127 | localnet 128 | modem 129 | mynet 130 | myrouter 131 | novalocal 132 | onion 133 | openstacklocal 134 | priv 135 | private 136 | prv 137 | router 138 | telus 139 | test 140 | totolink 141 | wlan_ap 142 | workgroup 143 | zghjccbob3n0 144 | 145 | -------------------------------------------------------------------------------- /watchdog.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | sleep 300 4 | 5 | for service in unbound encrypted-dns; do 6 | sv check "$service" || sv force-restart "$service" 7 | done 8 | --------------------------------------------------------------------------------