I actually use Mullvad's servers with DoH + NetworkManager as a daily driver! Here are my notes on how to set this up:
1. Install the dnscrypt-proxy package along with dnscrypt-proxy-openrc or the equivalent for your init.
2. Run the following command and see if any programs are using port 53. Disable them if there are (or apply the appropriate configs in order to free up the port, the dnsmasq step below is an example). For more info see https://wiki.archlinux.org/title/DNS-over-HTTPS#Disable_any_services_bound_to_port_53
ss -lp 'sport = :domain'
3. Edit /etc/dnscrypt-proxy/dnscrypt-proxy.toml to include Mullvad's servers, here's my config as an example:
listen_addresses = ['127.0.0.1:53']
server_names = ['mullvad-family-doh']
cache=true
block_ipv6 = true
ipv6_servers = false
require_dnssec = false
require_nolog = true
log_level = 0
log_file = '/var/log/dnscrypt-proxy/dnscrypt-proxy.log'
[query_log]
file = '/var/log/dnscrypt-proxy/query.log'
[nx_log]
file = '/var/log/dnscrypt-proxy/nx.log'
[sources]
[sources.'public-resolvers']
url = 'https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md'
cache_file = '/var/cache/dnscrypt-proxy/public-resolvers.md'
minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
refresh_delay = 72
prefix = ''
4. If you have dnsmasq installed and running, add these lines to the end of /etc/dnsmasq.conf (though this may depend on your configuration):
no-resolv
bind-interfaces
listen-address=127.0.0.1
5. If you have dhcp installed and running, add this to /etc/dhcpcd.conf so that it doesn't interfere with resolv.conf:
nohook resolv.conf
(note: only do steps 4 and 5 if you already have those programs running. They aren't necessarily needed for DoH)
6. In /etc/NetworkManager/NetworkManager.conf add this under [main] so that it doesn't interfere with resolv.conf (there should be a similar setting for connman):
dns=none
rc-manager=unmanaged
7. Edit /etc/resolv.conf like so:
nameserver 127.0.0.1
8. Very important step for dnscrypt-proxy, follow the instructions from https://wiki.artixlinux.org/Main/Dnscrypt-proxy#Troubleshooting (under the preferred section)
9. Enable and start the dnscrypt-proxy service + restart NetworkManager (edit the commands according to your init):
sudo rc-update add dnscrypt-proxy default
sudo rc-service dnscrypt-proxy start
sudo rc-service NetworkManager restart
Aaand DoH should work now! (you can test at https://mullvad.net/en/check)
Even though this is just a collection of fragments from wiki pages, forum posts and trial and error, I hope this will be useful for someone since I couldn't find any complete and coherent guides when trying to set this up myself.
Stubby is a good alternative to dnscrypt-proxy if you want DoT, you can follow pretty much the same steps but enable Stubby instead. Also note that neither NetworkManager nor connman are able to handle dns encryption themselves, hence the need for other programs.