Deployment guide

dnscrypt-proxy

Overview

dnscrypt-proxy is a flexible DNS proxy that encrypts your DNS traffic. It sits between your clients and the public internet. It accepts ordinary DNS queries on port 53 and forwards every one of them to a public upstream resolver over an encrypted transport, so your internet provider and any network on the path can no longer see or tamper with the names you look up. It supports the modern encrypted DNS protocols, including DNSCrypt v2, DNS over HTTPS, Anonymized DNSCrypt and Oblivious DoH.

This guide covers the deployment and configuration of dnscrypt-proxy on Ubuntu 24.04 on Azure, using SecureAnyCloud Azure Marketplace images. The image installs dnscrypt-proxy 2.1.18 from the official prebuilt release binary. It runs under systemd as an unprivileged dnscrypt-proxy user with only the CAP_NET_BIND_SERVICE capability, so that it can bind the standard privileged DNS port.

It answers DNS on port 53 over both UDP and TCP on all interfaces. It forwards to upstreams that are chosen automatically, by lowest latency, from a cryptographically signed public resolver list. There is no web interface and no database. A single flat TOML file (/etc/dnscrypt-proxy/dnscrypt-proxy.toml) is the whole configuration.

Secure by default. Upstream selection is restricted to resolvers that validate DNSSEC, keep no logs, and apply no filtering, so you get authentic, private, unfiltered answers. The image ships with no shared or default credential of any kind, because dnscrypt-proxy has no login.

The resolver binds all interfaces so that it can serve a whole network, but the stock Azure Network Security Group opens only SSH. Port 53 is therefore not reachable from the internet until you deliberately open it. Because dnscrypt-proxy has no built-in allow-from access control list, the Network Security Group is your access control. Open UDP and TCP 53 only to the client subnets that you control, never to the whole internet, so that the resolver is never abused as an open resolver.

What you get:

  • dnscrypt-proxy 2.1.18 from the official prebuilt release binary, run under systemd as the unprivileged dnscrypt-proxy user (dnscrypt-proxy.service)
  • A DNS endpoint on 0.0.0.0:53 (UDP and TCP) that forwards every query to an encrypted upstream (DNSCrypt v2 or DNS over HTTPS)
  • Automatic selection of DNSSEC-validating, no-log, non-filtering encrypted resolvers from a minisign-signed public resolver list
  • The whole configuration in one readable file, /etc/dnscrypt-proxy/dnscrypt-proxy.toml, with ready-to-edit example blocklists, allow lists, cloaking and forwarding rules alongside it
  • The systemd-resolved stub listener disabled so that dnscrypt-proxy owns port 53 cleanly, while the OS keeps resolving names through its own upstream list

Prerequisites

Before you deploy, make sure you have:

  • An active Azure subscription, an SSH public key, and a VNet and subnet in the target region
  • A subscription to the dnscrypt-proxy listing on Azure Marketplace
  • Network Security Group rules allowing TCP 22 (admin) and UDP 53 + TCP 53 (DNS) only from the client subnets that will use the resolver

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for a departmental resolver. dnscrypt-proxy is extremely light, and larger sizes are only needed for very high query volumes.

1

Deploy from the Azure Portal

Search for dnscrypt-proxy in the Marketplace, select the SecureAnyCloud publisher, and click Create. Configure the Network Security Group to allow TCP 22 for administration, and UDP 53 and TCP 53 from the clients that will use the resolver. Keep port 53 scoped to your own client subnets, never 0.0.0.0/0.

2

Deploy from the Azure CLI

RG="dns-prod"; LOCATION="eastus"; VM_NAME="dnscrypt1" IMAGE_URN="sac1647283583153:dnscrypt-proxy-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:dnscrypt-proxy-ubuntu-24-04:default:latest
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$IMAGE_URN" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1001

Do not open port 53 with a blanket az vm open-port. Instead, add a scoped Network Security Group rule for UDP and TCP 53 that lists only your client subnets as the source (see Step 7).

3

First boot

On first boot, the image writes a per-instance informational note to /root/dnscrypt-proxy-info.txt, refreshes the signed resolver list into its cache, and starts dnscrypt-proxy. This completes within seconds. SSH in as azureuser and read the note:

sudo cat /root/dnscrypt-proxy-info.txt

The note records the version, the listen address, this VM's IP, the config path and the encrypted-only upstream policy. dnscrypt-proxy has no password, so the note holds no secret.

4

Confirm the service is running

dnscrypt-proxy.service is active, dnscrypt-proxy -version reports 2.1.18, and the service runs as the unprivileged dnscrypt-proxy user. ss confirms that it is listening on :53 for DNS over both UDP and TCP on all interfaces.

systemctl is-active dnscrypt-proxy.service /opt/dnscrypt-proxy/dnscrypt-proxy -version sudo ss -tulnp | grep ':53 '
5

Resolve a name through the encrypted resolver

Send an ordinary DNS query to the resolver on the loopback address. dnscrypt-proxy forwards it to an encrypted upstream and returns the answer. DNS over TCP works too, and clients fall back to it for large responses.

dig +noall +answer @127.0.0.1 example.com A dig +tcp +noall +answer @127.0.0.1 cloudflare.com A

Both queries return normal A records. Your client sees plain DNS on port 53, while dnscrypt-proxy fetches the answer over an encrypted transport on your behalf.

6

Confirm the upstreams are encrypted

Encrypted upstreams are the property that matters for a privacy resolver. dnscrypt-proxy logs each live upstream and the protocol that it speaks (DNSCrypt or DoH) as it measures latency, and it picks the fastest. The -resolve subcommand shows a full diagnostic for a name, including whether the answer is DNSSEC validated.

sudo journalctl -u dnscrypt-proxy --no-pager | grep -E 'OK \(DNSCrypt\)|OK \(DoH\)|lowest initial latency' | tail -5 /opt/dnscrypt-proxy/dnscrypt-proxy -config /etc/dnscrypt-proxy/dnscrypt-proxy.toml -resolve example.com | grep -iE 'Resolver|Name servers|DNSSEC'

Every upstream is OK (DNSCrypt) or OK (DoH), and never plain DNS. DNSSEC signed : yes confirms that the answer was cryptographically validated end to end.

7

Secure by default and restrict the Network Security Group

The shipped configuration only ever selects encrypted, DNSSEC-validating, no-log, non-filtering upstreams. Review the policy, then lock down access. dnscrypt-proxy has no built-in allow-from access control list, so the Network Security Group is your access control.

grep -E '^(listen_addresses|require_dnssec|require_nolog|require_nofilter|dnscrypt_servers|doh_servers) ' /etc/dnscrypt-proxy/dnscrypt-proxy.toml

In the Azure Portal, add an inbound Network Security Group rule for UDP 53 and TCP 53 whose Source is your own client subnets (for example your VNet address space or a specific 10.0.0.0/24). Set the source to your admin IP for TCP 22. Never set the source of the port 53 rule to Any or 0.0.0.0/0. An internet-reachable resolver with no allow list is an open resolver and can be abused for amplification.

8

Point your clients at the resolver

When the Network Security Group allows your subnets, point your clients or your VNet's DNS setting at this VM's private IP on port 53. To make the whole virtual network use the resolver, set it as the VNet's custom DNS server:

# From your workstation, using the Azure CLI (VNET_RG / VNET_NAME are your VNet's): # az network vnet update -g <VNET_RG> -n <VNET_NAME> --dns-servers <this-vm-private-ip> # Then reboot (or re-apply DHCP on) the client VMs so they pick up the new resolver.
echo "Set your VNet custom DNS to this VM's private IP, or configure clients directly."

Individual Linux clients can test against the resolver directly with dig @<this-vm-private-ip> example.com.

9

Choose specific upstreams or protocols

By default, dnscrypt-proxy selects automatically from all resolvers that match the encrypted, DNSSEC, no-log and no-filter requirements. To pin a specific set, uncomment and edit server_names in the config, then restart. To use only DNS over HTTPS (or only DNSCrypt), set the matching *_servers toggles.

# edit /etc/dnscrypt-proxy/dnscrypt-proxy.toml, for example:
# server_names = ['cloudflare', 'google', 'quad9-doh-ip4-port443-nofilter-pri']
# or restrict to a single protocol:
# dnscrypt_servers = false
# DoH only
# then apply the change:
#
sudo systemctl restart dnscrypt-proxy echo "See https://github.com/DNSCrypt/dnscrypt-proxy/wiki for the full server list and options."

The configuration is validated on start. If there is a syntax error, the service fails to start and logs the reason, so check systemctl status dnscrypt-proxy after any edit.

10

Optional blocklists, allow lists and cloaking

dnscrypt-proxy ships with ready-to-edit example rule files in /etc/dnscrypt-proxy. Enable name blocklists, IP blocklists, cloaking (local overrides) or per-name forwarding by pointing the matching section of the config at a rules file.

ls /etc/dnscrypt-proxy/example-*.txt

Copy an example to a working file (for example blocked-names.txt), reference it from the [blocked_names] section of the config, and restart. With these rules, you can filter ad or malware domains, pin internal names, or forward a private zone to an internal resolver, all without an external service.

11

Security recommendations

Scope the Network Security Group. Allow UDP 53 and TCP 53 only from the client subnets that you control. dnscrypt-proxy has no allow-from ACL, so the NSG is the only thing standing between your resolver and the internet.

Keep the encrypted-only upstream policy. Leave require_dnssec, require_nolog and require_nofilter set to true so that answers stay authentic, private and unfiltered.

Prefer trusted upstreams for sensitive networks. Pin server_names to operators that you trust, or enable Anonymized DNSCrypt or Oblivious DoH so that no single upstream sees both your IP and your queries.

Keep the OS patched. Unattended security upgrades remain enabled on the running VM.

12

Support and Licensing

dnscrypt-proxy is an open-source project distributed under the ISC License. This SecureAnyCloud image bundles the unmodified official dnscrypt-proxy release binary. SecureAnyCloud provides the packaging, the systemd hardening, the secure-by-default encrypted-only upstream policy, the per-instance first-boot automation, the paired deploy guide, and 24/7 support with a guaranteed 24-hour response SLA.

SecureAnyCloud is not affiliated with or endorsed by the dnscrypt-proxy project or its authors. dnscrypt-proxy is a mark of its respective owner and is used here only to identify the software.

Deploy on Azure

Find dnscrypt-proxy on Ubuntu 24.04 LTS on the Azure Marketplace, published by SecureAnyCloud. Deploy from the Portal or the Azure CLI as shown above.

Need Help?

Email sales@secureanycloud.com for deployment help, configuration questions, or licensing enquiries.

Deploy on Azure

Launch dnscrypt-proxy 2.1.18 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure