Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting to allow serving DNS-over-HTTPS unencrypted #1009

Closed
3 tasks done
yegle opened this issue Sep 17, 2019 · 29 comments
Closed
3 tasks done

Setting to allow serving DNS-over-HTTPS unencrypted #1009

yegle opened this issue Sep 17, 2019 · 29 comments
Labels
external libs Issues that require changes in external libraries. feature request UI

Comments

@yegle
Copy link

yegle commented Sep 17, 2019

  • I am running the latest version
  • I checked the documentation and found no answer
  • I checked to make sure that this issue has not already been filed

Problem Description

I have a public IP and I already have a reverse proxy (with wildcard certificate) in place to serve different websites.

Adguard Home's DoH support seem to only provide encrypted service, and have no option to provide non-encrypted plaintext HTTP, which means I need to reverse proxy HTTPS traffic to HTTPS backend if I want to keep my existing reverse proxy.

Proposed Solution

Adguard Home should be able to provide the same HTTP request handler in plaintext HTTP, so that I can terminate HTTPS connection using my reverse proxy and forward to backend via HTTP.

Alternatives Considered

Reverse proxy HTTPS traffic in HTTPS.

Additional Information

Full disclosure: I know Adguard Home have closed relationship with CoreDNS and this FR has been rejected: coredns/coredns#3257

But I still think this is a valid feature and should be supported:

  1. It's very common to terminate SSL and serve HTTP service on different server (or in the world of containers, on different containers). Requiring HTTPS on the server serving HTTP means the certificate is unnecessarily widely distributed, and additional step each time you renew your certificate.
  2. Go's HTTPS support lacks OCSP stapling support which is crucial for a DoH server (See https://tools.ietf.org/html/rfc8484#section-10). This can easily mitigated by terminating SSL with tools like nginx.

I hope you are convinced this is a good idea :-)

@ameshkov
Copy link
Member

Well, I see no problem with this.

Please submit a pull request.

Here's where you need to make the change:
https://github.com/AdguardTeam/AdGuardHome/blob/master/home/control.go#L521

@yegle
Copy link
Author

yegle commented Sep 18, 2019

Great! I'll see if I can do it this weekend.

@Akruidenberg
Copy link

Great! I'll see if I can do it this weekend.

Any progress?

@yegle
Copy link
Author

yegle commented Oct 5, 2019

Sorry I was distracted. Will send a PR this weekend.

@yegle
Copy link
Author

yegle commented Oct 5, 2019

FWIW, I think the user should also be able to enable DNS-over-HTTP via the settings page. That would take a while to get right as I'm not very familiar with the frontend stuff.

@yegle
Copy link
Author

yegle commented Oct 5, 2019

:-(

It looks like the UI is implemented in React, which I have 0 knowledge of. I guess I'll leave this up to you to implement.

What I want to see in the settings page:

  1. One option to enable DoT
  2. One option to enable HTTPS, with two radio button "Enable HTTPS" and "Disable HTTPS", but provide a checkbox under "Disable HTTPS" saying "enable DNS-over-HTTPS on HTTP port"

@OMICRON3069
Copy link

If AGH serves DNS over HTTP behind a reverse proxy, maybe it's a good idea to recognize client's real IP from http header (i.e. X-Real-IP and X-Forwarded-For) for request coming from localhost?

@yegle
Copy link
Author

yegle commented Oct 6, 2019

That would be my expectation yes.

@ameshkov
Copy link
Member

ameshkov commented Oct 6, 2019

@yegle I suggest starting with something really simple -- not expose this to the UI at all, just add a configuration property that will enable this behavior

@Akruidenberg
Copy link

Is also possible to do this with DOT?

@ameshkov
Copy link
Member

@Akruidenberg it does not make much sense to do it for DOT. DOT without encryption is simply plain DNS over TCP which is already supported.

@szolin
Copy link
Contributor

szolin commented Jan 24, 2020

ec8fe0b
Is there something else we should do on this issue?

@ameshkov ameshkov added this to the v0.104 milestone Jan 26, 2020
@ameshkov
Copy link
Member

@szolin well, I think we should make it possible to change it in the UI.

Let's discuss it later, I've assigned it to v0.104

@Akruidenberg
Copy link

Akruidenberg commented Mar 9, 2020

Is this already implemented in version 0.100.9? The option is available in the config file. Which docker labels are needed for traefik to get this working? The example is only for nginx.
Also, when i set the value from false to true, how can i see if its working?
Nothing changed in the web interface.

@szolin
Copy link
Contributor

szolin commented Mar 12, 2020

Yes, it's implemented. But there's no way to set in via UI, you have to edit yaml file:
https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration

  • allow_unencrypted_doh - Allow DOH queries via unencrypted HTTP (e.g. for reverse proxying)

@Akruidenberg
Copy link

Yes, it's implemented. But there's no way to set in via UI, you have to edit yaml file:
https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration

  • allow_unencrypted_doh - Allow DOH queries via unencrypted HTTP (e.g. for reverse proxying)

Maybe it's an good idea to write a article on the wiki with some examples with nginx and traefik. is a bit difficult to configure to get it working.

@Akruidenberg
Copy link

Akruidenberg commented Mar 18, 2020

Yes, it's implemented. But there's no way to set in via UI, you have to edit yaml file:
https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration

  • allow_unencrypted_doh - Allow DOH queries via unencrypted HTTP (e.g. for reverse proxying)

Maybe it's an good idea to write a article on the wiki with some examples with nginx and traefik. is a bit difficult to configure to get it working.

Got dns over https working now. Not to difficult. set traefik to route over port 80 (http) and set "allow_unencrypted_doh" and the SNI value to true.

However, how to get Traefik 2 working with dns over tls. Traefik version 2 supports tcp.
I dont know how to set my compose file to get it working.

This is my config:

  traefik2:
    container_name: traefik2
    image: traefik:cantal
    restart: always
    command:
      - --global.checkNewVersion=true
      - --global.sendAnonymousUsage=false
      - --entryPoints.http.address=:80
      # https://www.reddit.com/r/docker/comments/c1wrep/traefik_reverse_proxy_question_docker_overlay/
#      - --entrypoints.http.forwardedHeaders.trustedIPs=127.0.0.1/31, 192.168.90.1/24
#      - --entrypoints.http.proxyProtocol=true
#      - --entrypoints.http.proxyProtocol.trustedIPs=127.0.0.1/31, 192.168.90.1/24
      - --entryPoints.https.address=:443
      - --entryPoints.tls.address=:853
      - --api=true
#      - --api.insecure=true
#      - --serversTransport.insecureSkipVerify=false
      - --log=true
      - --log.level=INFO # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
      - --accessLog=true
      - --accessLog.filePath=/var/log/docker/traefik.log
      - --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines
      - --accessLog.filters.statusCodes=400-499
      - --providers.docker=true
      - --providers.docker.defaultrule=Host(`{{ index .Labels "com.docker.compose.service" }}.$DOMAINBASE`)
      - --providers.docker.exposedByDefault=false
      - --providers.docker.network=reverseproxy
      - --providers.docker.endpoint=tcp://dockersock-proxy:2375
      - --providers.docker.swarmMode=false
      - --providers.file.directory=/rules
      - --providers.file.watch=true
      - --certificatesresolvers.ovh.acme.dnschallenge=true
#      - --certificatesResolvers.ovh.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # uncomment when testing
      - --certificatesResolvers.ovh.acme.email=${SMTP_DEST_EMAIL}
      - --certificatesResolvers.ovh.acme.storage=/acme.json
      - --certificatesResolvers.ovh.acme.dnsChallenge.provider=ovh
    networks:
      - reverseproxy
      - dockersock-proxy
    user: ${PUID}
    ports:
      - "80:80"
      - "443:443"
      - "853:853"
    volumes:
      - $USERDIR/traefik2/rules:/rules
      - $USERDIR/traefik2/acme.json:/acme.json
      - $USERDIR/traefik2/traefik.log:/var/log/docker/traefik.log
    environment:
      OVH_ENDPOINT: ovh-eu
      OVH_APPLICATION_KEY: ${OVH_APPLICATION_KEY}
      OVH_APPLICATION_SECRET: ${OVH_APPLICATION_SECRET}
      OVH_CONSUMER_KEY: ${OVH_CONSUMER_KEY}
    sysctls:
      net.ipv4.ip_unprivileged_port_start: "0"
    labels:
      - "traefik.enable=true"
      # HTTP-to-HTTPS Redirect
      - "traefik.http.routers.http_catchall.rule=HostRegexp(`{any:.+}`)"
      - "traefik.http.routers.http_catchall.entrypoints=http"
      - "traefik.http.routers.http_catchall.middlewares=https_redirect@docker"
      - "traefik.http.middlewares.https_redirect.redirectscheme.scheme=https"
      - "traefik.http.middlewares.https_redirect.redirectscheme.permanent=true"
      # HTTP Routers
      - "traefik.http.routers.traefik-rtr.entrypoints=https"
      - "traefik.http.routers.traefik-rtr.rule=Host(`traefik.$DOMAINBASE`)"
      - "traefik.http.routers.traefik-rtr.tls=true"
      - "traefik.http.routers.traefik-rtr.tls.certresolver=ovh"
      - "traefik.http.routers.traefik-rtr.tls.domains[0].main=$DOMAINBASE"
      - "traefik.http.routers.traefik-rtr.tls.domains[0].sans=*.$DOMAINBASE"
      ## Middlewares
      - "traefik.http.routers.traefik-rtr.middlewares=traefik-headers@docker,rate-limit@file,oauth@file"
      - "traefik.http.middlewares.traefik-headers.headers.featurepolicy=camera 'none'; geolocation 'none'; microphone 'none'; payment 'none'; usb 'none'; vr 'none';"
      ## Services - API
      - "traefik.http.routers.traefik-rtr.service=api@internal"
      ## labels      
      - "com.centurylinklabs.watchtower.enable=false"        

adguard:
    container_name: adguardhome
    restart: unless-stopped
    image: adguard/adguardhome
    hostname: adguard
    ports:
      - "53:53"
      - "53:53/udp"
    expose:
      - "80"
      - "3000"
      - "443"
      - "853"
    volumes:
      - ${USERDIR}/adguard/conf:/opt/adguardhome/conf
      - ${USERDIR}/adguard/work:/opt/adguardhome/work
    user: ${PUID}
    networks:
      - reverseproxy
    labels:
      traefik.enable: "true"
      ## HTTP Routers
      traefik.http.routers.adguard-rtr.entrypoints: https
      traefik.http.routers.adguard-rtr.rule: Host(`dns.$DOMAINBASE`)
      traefik.http.routers.adguard-rtr.tls: "true"
      traefik.http.routers.adguard-rtr.tls.certresolver: ovh
      ## Middlewares
      ## HTTP Services
      traefik.http.routers.adguard-rtr.service: adguard-svc
      traefik.http.services.adguard-svc.loadbalancer.server.port: 80  
      ###TCP
      traefik.tcp.routers.adguard-tls.entrypoints: tls
      traefik.tcp.routers.adguard-tls.rule: HostSNI(`dns.$DOMAINBASE`)
      traefik.tcp.routers.adguard-tls.tls: "true"
      traefik.tcp.routers.adguard-tls.tls.certresolver: ovh
      ## Middlewares
      ## tcp Services
      traefik.tcp.routers.adguard-tls.service: adguard-svc-tls
      traefik.tcp.services.adguard-svc-tls.loadbalancer.server.port: 853

How to get this config working?

@Akruidenberg
Copy link

its working! wrong port: 853 is wrong. must be 53.

@Akruidenberg
Copy link

new update: DOT is sometimes slow with complex pages. DOH is working very well with traefik.
I dont get this issue in the past (with self signed certifites and without traefik.
Tried - "traefik.tcp.services.mytcpservice.loadbalancer.terminationdelay=100" but no luck.
Is this a bug in Adguard?

@szolin szolin added UI and removed help wanted labels Oct 2, 2020
@tristanXme
Copy link

I can't get DoT working with a custom signed Cert. Can i deactivate the cert validation from AdGuard Home?

@tristanXme
Copy link

/bump my question

@ainar-g ainar-g added the external libs Issues that require changes in external libraries. label Jun 3, 2021
@ameshkov ameshkov removed this from the v0.107.0 milestone Jun 3, 2021
@ameshkov
Copy link
Member

ameshkov commented Jun 3, 2021

Implemented long time ago. Closing since we don't plan to provide any UI setting for that, unencrypted DOH is an option that's supposed to be used by people who know what they're doing and know how to change the config file.

@ameshkov ameshkov closed this as completed Jun 3, 2021
@enquestor
Copy link

enquestor commented Nov 7, 2021

Sorry for bumping this issue from long ago.
I'm also trying to set up a nginx reverse proxy that manages the certificates and proxy to adguard container unencrypted.

This is my current tls part of the config:

tls:
  enabled: true
  server_name: my.domain.name
  force_https: false
  port_https: 0
  port_dns_over_tls: 853
  port_dns_over_quic: 784
  port_dnscrypt: 0
  dnscrypt_config_file: ""
  allow_unencrypted_doh: true
  strict_sni_check: false
  certificate_chain: ""
  private_key: ""
  certificate_path: ""
  private_key_path: ""

My main question is: How do I set the port DoH server is listening to? Cause I keep getting connection refused on port 80 when doing DoH queries with curl, even within the container.

@ameshkov
Copy link
Member

ameshkov commented Nov 7, 2021

@Allen-hu
port_https: 0 -- this is what you need.

@enquestor
Copy link

@ameshkov
Yes I'm aware of that option, and already have it enabled (shown in my previous comment).

I'd like to know where (which port) I should proxy my DoH requests to, so I could config the reverse proxy correctly.
Ex. http://adguardhome:80

Thanks in advance!

@yegle
Copy link
Author

yegle commented Nov 8, 2021

There is a bind_port option.

@enquestor
Copy link

@yegle I thought that was for the web interface only? Should I be sending my DoH requests there as well?

I set bind_port: 3000 and tried sending requests using curl within the reverse proxy container and get Bad Request from curl:

docker exec -it reverseproxy curl -H 'accept: application/dns-json' 'http://adguardhome:3000/dns-query?name=google.com&type=A'
Bad Request

while sending queries to other ports would result in connection refused:

docker exec -it reverseproxy curl -H 'accept: application/dns-json' 'http://adguardhome/dns-query?name=google.com&type=A'
curl: (7) Failed to connect to adguardhome port 80: Connection refused

@yegle
Copy link
Author

yegle commented Nov 8, 2021

Yes I set that to 80 and have my reverse proxy forward request to that and it seems to work.

https://github.com/yegle/your-dns/blob/master/adguard/conf/AdGuardHome.yaml.example this is the config I'm using.

@yegle
Copy link
Author

yegle commented Nov 8, 2021

Oh I see you are testing using the JSON API. I'm not actually sure Adguard Home supports that. I usually test a doh server using https://github.com/curl/doh.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
external libs Issues that require changes in external libraries. feature request UI
Projects
None yet
Development

No branches or pull requests

8 participants