AdGuard Home - DoH & DoT - External nginx reverse proxy

I’m running AdGuard Home on my RPi that is hosting Home Assistant. It works fine for local things, but I’m trying to figure out how to make it work with DoH and DoT when my Unraid box is hosting my nginx reverse proxy for everything else on my network.

Has anyone set this up before?

What’s the link between DNS over TLS/HTTPS and your nginx reverse proxy?
DoH/DoT might be used by “clients” trying to reach your nginx reverse-proxy, but that’s out of your control…

I can’t enable the Encryption settings because for some reason it has to know what the certs are:

In order to use encryption, you need to provide a valid SSL certificates chain for your domain. You can get a free certificate on letsencrypt.org or you can buy it from one of the trusted Certificate Authorities.

Is that from the AdGuard doc?
That would be when adguard acts as a DoT/DoH server

I’m at loss at what you’re trying to achieve, really.
When external clients will try to reach your HA through an external domain + nginx, they won’t use your adguard to resolve the domain name.

For your local clients, what would be the point of encrypting DNS traffic to your local DNS server?

You need to export the cert and private key you are using for your nginx reverse proxy (on Unraid) to import it into AdGuard.
While those certs are not very important for DoH, as the TLS termination will be your reverse HTTPS proxy, it is crucial for DoT, as the TLS termination is AdGuard itself.

If you don’t certs, you can use the “let’s encrypt HA plugin” to create and update those.
Personally I use “Nginx Proxy Manager” plugin on my HA that takes care of both the certificate generation and renewal, and the management of the integrated reverse proxy.

However you must know that there is a limitation with AdGuard Home on HA.
While the DoT port will be accessible from you local network, the HTTPS port that you configure in Adguard interface, will only listen on 127.0.0.1 .
This is a problem, because Nginx Proxy Manager is not able to redirect traffic to 127.0.0.1 as it runs in hass.io network, while AdGuard runs on the host network.
There is two solution for that:

  1. Run AdGuard Home outside of HA.
  2. Keep AdGuard Home on HA, and use simpleproxy in a new container on your HAos.

One day I might make a plugin for HA that does that just, but for now you’ll have to get your hand dirty:

  1. Get access to the HAos: Debugging the Home Assistant Operating System | Home Assistant Developer Docs
  2. install Nginx Proxy Manager HA plugin, as we need to proxy traffic from within the HA host.
  3. what you want is a TCP proxy that listen at 172.30.32.1:444 and forwards traffic to he HTTPS port of AdGuard, which is running at 127.0.0.1:441 (441 being the HTTPS port you have configured in AdGuard UI)
    To that end, I slapped simpleproxy on a raspbian container. So you can directly do :
    docker run -d --name doh-tcp-proxy --restart unless-stopped --network=host fclem/raspbian-bullseye simpleproxy -L 172.30.32.1:444 -R 127.0.0.1:441
    (replace 441 by the port you used for HTTPS in AdGuard Home)
  4. finally create an host in Nginx Proxy Manager, but put something boggus in forward IP / Port (see figure 1)
    as otherwise you would give public open access to your AdGuard Home web interface to the internet, which would be absolutely terrible for you;
    and then in custom locations put:
location: /dns-query
scheme: https
forward hostname: 172.30.32.1/dns-query
forward port : 444

like seen in figure 2:

With this setup I get access to my DoH and DoT on my public ip with my own domain. Super sweet !
For example in android you can setup your private DNS as : domain.tld (you need to NAT TCP port 853)
and for DoH, in chrome for example : https://domain.tld/dns-query

2 Likes

I believe the point is to access his DoH and DoT from his public ip.
For example you can setup Android (>9) to use any DoT,
And same goes with DoH and any modern browser or the latest OSes.

It’s a great way to make sure that none of you devices mobiles/laptops, ever use plain text DNS over any random network ever again, and also always have network level ad blocking on the go, anywhere, everywhere, all the time.

I’ve done just that for myself for the past 2-3 years, and I’m never going back.

It’s supposed to bind to the LAN IP address of the host as well, does it not do that for you? Why couldn’t NPM just redirect to https://<host LAN IP>:441?

Also another alternative is just to use a reverse proxy addon that runs on the host. I use Caddy 2 personally since I like the control it gives me and that its config is text, here’s its addon. I usually use the json syntax so I’m a bit rusty with Caddyfile syntax but translating my json config I’m pretty sure all you need is this:

@adguard_doh {
  host <Your DOH Host>
  method GET
  path /dns-query*
}
reverse_proxy @adguard_doh localhost:441 {
  trusted_proxies <Your proxy IP>
  transport http {
    tls_server_name <Your DOH Host>
  }
}
reverse_proxy <Your DOH URL> https://http.cat/404 {
  header_up Host http.cat
}

The last bit is just for fun. Should redirect everything without /dns-query to https://http.cat/404. Can also just serve up a 404 or whatever you want.

EDIT: Small tweak, path should be /dns-query* not /dns-query. That’s not strictly necessary though, you can just use /dns-query. However if you have multiple clients connecting to adguard over DoH and want to keep track of which is which then adguard does this with an extra path part. You send the query to /dns-query/<client ID>. See here for more info on this.

You can identify clients over DoT as well, you do it with a subdomain there <client ID>.<DOT Host>. If you want to use that then remember to get a wildcard certificate for your DOT URL otherwise it won’t work.

Well, then, or you are opening your AdGuard to the world, which seems to me a greater security risk than your DNS traffic being intercepted, or you’re using a VPN, in which case encryption is unnecessary…

Well you can limit it to only the dot port and only udp traffic. But yea I agree, it’s not ideal. I tried it for a bit then switched to a VPN approach for a few reasons:

  1. security, didn’t like opening a port to Adguard
  2. can’t be easily toggled on and off. You’re not exactly getting 5 9s of reliability out of a self hosted DNS server on one machine in one physical location. Plus performance becomes unbearable in spotty networks, everything just starts silently failing and you have to dig into settings menus to fix it.
  3. you can’t switch from dot to DHCP provided DNS when on your wifi. So it slows down DNS in your house since you’re still using the external dot url unless you manually dig into settings and toggle it.

VPN that toggles on and off with my wifi seemed a lot easier

You have approximately one million more “chances” to be nmap’ed by a script kiddie than anyone sniffing your DNS traffic :slight_smile:

And when they found it, your DNS will be used for whatever they want, including attacks to 3rd parties…
Wide-open self-hosted DNS is likely to be frowned upon by your provider as well.

Bottom-line: Very bad idea :wink:

1 Like

You also must expose port 853. Android will not allow you to provide an alternate port. So it’ll be pretty obvious what it is when they do find it

No, just its DoT resolver endpoint.

Well actually it is not. (c.f. AdGuard Home secure to open to public? · Issue #769 · AdguardTeam/AdGuardHome · GitHub)
So risky that they are using it for their public dns at dns.adguard.com :laughing:

Haha, no, that would be less efficient, and honestly quite silly.

First off, no, that’s ridicule. One billion while you’re at it :laughing:
Second we are not talking about sniffing (while that’s a possible threat on any network), but logging and matching with client ID. This is a quite common practice, for example on an office network. AdGuard/pihole/etc offer this feature out of the box, so someone with almost zero knowledge can deploy such a thing on their network, and that’s precisely what DoT and DoH defend against.
Finally : “oh no a script kiddie nmap’ed me !!” yeah so what ?

Like resolving hostnames ? OH NO !!!
“Whatever they want” :fearful: ?? Let’s hope they don’t want to make coffee with it !

Yeah ! most likely using the well known DoT remote code execution CVE-666.

Bottom-line: If I had no initial understanding of the OP yet clear intentions, had someone else explain them to me, I would refrain from making baseless/ridicule claims, and expressing half-backed/uninformed opinion purporting those as serious advice. But hey, that’s just me.

That’s exactly what I meant.

Sniffing and spoofing are the only reasons to enable DoT. Obviously, the DNS server itself knows what you’re asking it (duh) and can log or match it if it has been configured to do so.
Enabling DoT vs. Google servers would exactly brings you nothing in that regard.

No, I’m talking about DNS DDOS for which you will be held responsible as owner of that wide-open dns server (https://www.imperva.com/learn/ddos/dns-amplification/).
I know what I’m talking about, I made that mistake.

Lol. This forum starts to feel like twitter :joy:

Maybe, but it’s not what you wrote though. Am I suppose to guess what you meant then ?

No it’s not. Privacy is another one, it’s in fact the most common reason to enable DoT.

Except it would. It would bring you the privacy, and control over who can see/log your DNS queries. I.e. your company management, whom could fire you for it, VS a public DNS.

DNS DDOS. So source IP of DNS packets are spoofed to the one target IP.
Let’s assume a 4000 bytes UDP response per request x 20 rpc/s = 80kb/s.
Biggest contribution to a DDOS attack ever. LOL.

You being ignorant / incapable (for example), doesn’t imply other are too, but thanks for your unsolicited concern over my abilities / safety (definitely on point with the purpose of that forum, btw).

What do you mean ? (I guess it’s again one of those instance where I’m supposed to guess what you mean, right ?) So, maybe you mean a negative feeling ??
Then you are probably referring to your own “contributions” not bringing anything constructive or of value to this thread (as opposed to a complete, detailed and documented solution to the OP’s request), polluting it with baseless/wrong claims or useless comments such has :
“I don’t understand what you are saying/trying to do”
“Made myself vulnerable to a DNS amplification attack, and was then victim of an DNS amplification attack, LOL”
Right ?

No, it’s not :

Since v0.107.0 AdGuard Home is able to restrict DNS-over-HTTPS requests which came from the proxy server not included into “trusted” list. By default, it’s configured to accept requests from IPv4 and IPv6 loopback addresses.

So the only way would be adding your reverse proxy as a trusted_proxies in AdGuardHome.yaml which would involve excessive tinkering with AdGuard HA plugin.

Caddy 2 seems nice, but how is that any different from what is achievable with NPM ? I mean unless it runs on the host network, rather than hassio (like NPM does) then it does not bring anything more than NPM in this context.

This is precisely the intention behind what I’m doing, as seen in Figure 2.

DoT works on TCP.

How so ?

What’s the security concern here ? (your uninformed dislike, is not a valid argument)

Not only it can, in fact, be easily switched on/off ( see Tasker Share), you could even make it automatic, however it is also not necessary.
I’ve been using this setup for more than 3 years, first on top of PiHole, and now on top of AdGuard HA plugin, and I’ve never had any issue neither with performance, nor availability. (running at home on a raspi 3B, on a ethernet 1G/500M+ internet link, so of course that wouldn’t be the case for anyone)
The only limitation of course, is when being abroad and not using roaming, where this solution incurs a significant latency penalty VS local DHCP assigned DNS. (for roaming it does not matter, as your internet GW is in your home-provider network anyways.) In this context VPN would also be inpacted, even worst, since you would be routing all your traffic by default to the VPN rather than just DNS.

Also using reliability and performance as an argument, while proposing (self-hosted) VPN as a solution, is silly at best. Your VPN will not have any better availability nor performance (which would be arguably lower), making your argument fallacious.

Why would you want to do that ? the “external” DoT url hits my router, and thus will be routed to my local AdGuard through NAT reflection, while the TLS overhead in this scenario is negligible, and DHCP provided DNS would be local AdGuard anyways.
For the sake of argument I’m running benchmarks for that right now, and will be updating with the results later.

Lot easier ? So you’re telling me you set up your VPN client to only route DNS traffic to the VPN ? Because otherwise the performance penalty will be massive.

Seems to me that VPN is overkill and cumbersome, as it is factually not any more reliable or better in term of performance, even arguably worst (at least in the context you are describing). Sure, to the unsuspecting, it might seems like a more “secure” option, but that’s just a misconception, biased/uninformed/subjective opinion, rather than a fact. ( I mean unless you find any security concern/issue with their implementation :
AdGuardHome/tls.go at master · AdguardTeam/AdGuardHome · GitHub :
github. com /AdguardTeam/AdGuardHome/blob/master/internal/home/tls.go or have actually some factual claims backing that up)

Interesting, I stand corrected then. That does complicate things.

Yes it runs on the host network. Sorry you’re right, I realized I forgot to mention that, that was the reason for my suggestion:

:man_facepalming: Huh yea I guess I forgot this. It’s been a minute.

My security concern here is forwarding a port through your firewall directly to hosted software is universally considered a bad idea. Some software is more hardened and prepared for this kind of access then others. I would hope AdGuard is for at least its DoT and DoH features as surely they must’ve been designed expecting to be public facing. There are definitely far worse things one could forward a port to. That still doesn’t give a free pass for increasing ones vulnerability space.

I don’t have a specific security issue to point to here it’s true. But I just see it as every piece of software I forward a port too increases the likelihood that a vulnerability will be discovered in one of those pieces of software and I’ll have it open to the world.

Nice! I went looking for a way to do this via tasker when I was using this option and couldn’t find one. Definitely keeping this, that’s handy :+1:

I mean I’m not using it just for DNS. It allows me to act as if my phone/computer is always in my house for purposes of access. I needed that anyway. I also found that wireguard is so fast that there’s really very little overhead created by it. Yes my traffic is slowed by going to my house but generally not enough that I am bothered by it. And if I am I simply turn it off until my service is better.

I wasn’t proposing VPN as a more performant option, sorry if that wasn’t clear. Yes it obviously has the same issues around spotty service, probably exacerbated. And now that you have shown a way to easily toggle DoT one of my concerns is alleviated (easily toggling it off when service is spotty) so that’s great.

I still think people should always limit the number of ports they forward to self-hosted software as good security practice. So if someone is going to forward one for VPN perhaps consider just doing that instead of also forwarding one for DoT. If not then that changes the discussion. Adguard’s DoT service is probably fine to be exposed publicly either way its just always good to limit your exposure service.

Yea that’s fair. I mean not every router supports that but most can.

Hi, can you write tutorial when i’m running Adguard Home outside HA? I have proxmox, HA in VM nad Adguard in lxc. Also in other lxc i have nginx proxy manager.

So the proxy is just to take port 441 from 127.x and go to regular ip 192.168.x with port 444.
In your nginx container are you accepting host port 444 and internal port going to 443?
I was thinking of using my router to do something similar. Most allow port forwarding. Was also trying to think of a stand alone solution.

I’m trying to achieve access to doh and dot along with https website over my public ip with a domain.

So far this seems like a good option so I don’t have to fiddle with my router since I can’t think of another way around hosting adguard, nginx reverse proxy, and everything else in docker. Haven’t seen chaining

This may be useful: https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration#configuring-upstreams