DNSCrypt-Wrapper is the server-end of DNSCrypt proxy, which is a protocol to improve DNS security, now with xchacha20 cipher support. This image features certficate management & rotation.
Tag | Description | 🐳 |
---|---|---|
:latest |
DNSCrypt-Wrapper 0.3 on alpine:latest . |
docker container run [OPTIONS] nutshells/dnscrypt-wrapper [COMMAND] [ARG...]
- Learn more about
docker container run
and itsOPTIONS
here; - List all available
COMMAND
s:docker container run --rm --read-only nutshells/dnscrypt-wrapper help
- List all
ARG
s:docker container run --rm --read-only nutshells/dnscrypt-wrapper --help
A DNScrypt proxy server cannot go without a so-called provider key pair.
It's rather easy to generate a new pair by running the init
command as below:
<keys_dir>
is the host directory where you store the key pairs. The provider key pair should NEVER be changed as you may inform the world of the public key, unless the secret key is compromised.
docker container run -d -p 5353:12345/udp -p 5353:12345/tcp \
--name=dnscrypt-server --restart=unless-stopped --read-only \
--mount=type=bind,src=<keys_dir>,dst=/usr/local/etc/dnscrypt-wrapper \
nutshells/dnscrypt-wrapper \
init
Now, a server is initialized with default settings and running on port 5353
as a daemon.
Dig the public key fingerprint out of logs:
docker container logs dnscrypt-server | grep --color 'Provider public key: '
Then see if it works.
If you used to run a DNScrypt proxy server and have been keeping the keys securely, make sure they are put into <keys_dir>
and renamed to public.key
and secret.key
, then run the start
command instead.
Incidentally,
start
is the default one which could be just omitted.
Lost the public key fingerprint but couldn't find it from logs? Try the pubkey
command:
docker container run --rm --read-only \
--mount=type=bind,src=<keys_dir>,dst=/usr/local/etc/dnscrypt-wrapper \
nutshells/dnscrypt-wrapper \
pubkey
Get <provider_pub_key>
by following the instructions above,
and check this section to determin the default value of <provider_basename>
.
Please install
dnscrypt-proxy
anddig
first.
dnscrypt-proxy --local-address=127.0.0.1:53 \
--resolver-address=127.0.0.1:5353 \
--provider-name=2.dnscrypt-cert.<provider_basename> \
--provider-key=<provider_pub_key>
--loglevel=7
dig -p 53 +tcp google.com @127.0.0.1
As you can see from the examples of the previous sections: the container accepts original command-line options of ss-libev as arguments.
Here are a few more examples:
docker container run --rm --read-only nutshells/dnscrypt-wrapper --version
docker container run [OPTIONS] nutshells/dnscrypt-wrapper [COMMAND] [ARG...] -V
docker container run --rm --read-only nutshells/dnscrypt-wrapper --help
However, please be informed that some of the options are managed by the entrypoint script of the container. You will encounter an error while trying to set any of them, just use the environment variables instead; as for other exceptions, just follow the message to get rid of them.
Name | Default | Relevant Option | Description |
---|---|---|---|
RESOLVER_IP |
8.8.8.8 |
-r , --resolver-address |
Hostname or IP address of the upstream dns resolver. |
RESOLVER_PORT |
53 |
-r , --resolver-address |
Port number of the upstream dns resolver. |
PROVIDER_BASENAME |
example.com |
--provider-name |
Basename of the provider, which forms the whole provide name with a prefix 2.dnscrypt-cert. . |
CRYPT_KEYS_LIFESPAN |
365 |
--cert-file-expire-days |
For how long (in days) the crypt key & certs would be valid. Refer to this topic to automate the rotation. |
For instance, if you want to use OpenDNS as the upstream DNS resolver other than Google's Public DNS, the default one, just set an environment variable like this:
docker container run \
-e RESOLVER_IP=208.67.222.222 -e RESOLVER_PORT=5353 \
[OTHER_OPTIONS] ...
Path in Container | Description | Mount as Writeable |
---|---|---|
/usr/local/etc/dnscrypt-wrapper |
Directory where keys are stored | Y |
See the sample file.
It's a good idea to speed up the high-frequency queries by adding a caching upstream resolver, we choose dnsmasq for its lightweight and configurability. Though there're many other options, such as unbound.
Firstly, let's create a new bridge network named dnscrypt
:
Add
--driver overlay
if it's in swarm mode.
docker network create dnscrypt
Secondly, create a dnsmasq container (as an upstream resolver) into the network with an increased cache size:
Refer to this page for more about the
nutshells/dnsmasq-fast-lookup
image.
docker container run -d --network=dnscrypt --network-alias=upstream \
--name=upstream --restart=unless-stopped --read-only \
nutshells/dnsmasq-fast-lookup \
--domain-needed --bogus-priv \
--server=8.8.8.8 --no-resolv --no-hosts \
--cache-size=10240
Then start a dnscrypt server into the same network too:
To add an existing container into the network, use
docker network connect
please.
docker container run -d --network=dnscrypt \
-p 5353:12345/udp -p 5353:12345/tcp \
--name=dnscrypt-server --restart=unless-stopped --read-only \
--mount=type=bind,src=<keys_dir>,dst=/usr/local/etc/dnscrypt-wrapper \
-e RESOLVER_IP=upstream -e RESOLVER_PORT=12345 \
nutshells/dnscrypt-wrapper \
init
Done!
A compose file, which helps you to manage both of the containers concurrently, is highly recommended for this situation.
Alternatively, the --net=host
option provides the best network performance, use it if you know it exactly.
If you forgot to mount <keys_dir>
into the container,
and now you want to locate the secret key in the anonymous volume,
just do some inspection first:
docker container inspect -f '{{json .Mounts }}' dnscrypt-server | grep --color '"Source":'
Then backup it securely.
Unlike the lifelong provider key pair, a crypt key & two certs, which are time-limited and used to encrypt and authenticate DNS queries, will be generated only if they're missing or expiring on starting. Thus the container is supposed to be restarted before certs' expiration.
Two certs are issued right after the crypt key's generation, one of them uses xchacha20 cipher.
Let's say we're planning to rotate them about once a week.
Firstly, shrink the cert's lifespan to 7
days:
Actually the rotation starts when the validity remaining is under
30%
, which would be on day5
in this case.
docker container run -e CRYPT_KEYS_LIFESPAN=7 ...
Secondly, restart the container every single day by creating a daily cronjob:
0 4 * * * docker container restart dnscrypt-server
Get an interactive shell to a running container:
docker container exec -it dnscrypt-server /bin/ash
You may want to make some modifications to the image. Pull the source code from GitHub, customize it, then build one by yourself:
git clone --depth 1 https://github.com/quchao/nutshells.git
docker image build -q=false --rm=true --no-cache=true \
-t nutshells/dnscrypt-wrapper \
-f ./dnscrypt-wrapper/Dockerfile \
./dnscrypt-wrapper
Otherwise just pull the image from the official registry, start a container and get a shell to it, commit the changes afterwards.
docker container commit --change "Commit msg" dnscrypt-server nutshells/dnscrypt-wrapper
Status of this container-specified health check merely indicates whether the crypt certs are about to expire, you'd better restart the container to rotate the keys ASAP if it's shown as unhealthy.
To confirm the status, run this command:
docker container inspect --format='{{json .State.Health.Status}}' dnscrypt-server
And to check the logs:
docker container inspect --format='{{json .State.Health}}' dnscrypt-server | python -m json.tool
If you think this is annoying, just add the --no-healthcheck
option to disable it.
Follow GitHub's How-to guide for the basis.
Contributions are always welcome in many ways:
- Give a star to show your fondness;
- File an issue if you have a question or an idea;
- Fork this repo and submit a PR;
- Improve the documentation.
- Serve with the old key & certs for another hour after the rotation.
- Add instructions on how to speed it up by caching the upstream dns queries.
- Add a
HealthCheck
instruction to indicate the expiration status of certs. - Add a command for checking the expire status.
- Use another container to rotate the keys.
Unless specified, all codes of Project Nutshells are released under the MIT License.
Other relevant softwares:
Ware/Lib | License |
---|---|
Docker | |
DNSCrypt-Proxy | |
DNSCrypt-Wrapper | |
DNSCrypt-Server-Docker |