AdguardTeam / AdGuardHome

Network-wide ads & trackers blocking DNS server
https://adguard.com/adguard-home/overview.html
GNU General Public License v3.0
25.63k stars 1.84k forks source link

Why use same https port for DNS and Web Portal #7424

Open vdias opened 1 week ago

vdias commented 1 week ago

Prerequisites

The problem

Whys use same port for DNS service and Administration portal.

How can we filter public VPS access to the administration portal? There is no sense of having this like this.

Proposed solution

Different port for different services

Alternatives considered and additional information

No response

ChronSyn commented 1 week ago

The premise of DoH (DNS-over-HTTPS) is that it wraps the DNS lookup as regular HTTPS requests, making it more difficult for interception and forgery by attackers. Whereas DoT and regular unencrypted DNS can be identified by the target (e.g. port), DoH is impossible to differentiate from the outside.

Separation of DoH from non-DoH HTTPS defeats one of the key benefits of it. If you wanted that, you may as well just use DoT (DNS-over-TLS).

You can configure the HTTPS port for your admin interface and DoH, as well as the DNS-over-TLS port, in 'Settings -> Encryption Settings':

image

As you can see, the /dns-query endpoint is where a DNS lookup will be sent to. You may be able to use that to determine if a DoT request is being routed to the DNS resolver, or if it's being routed to the admin interface.

Marcus1Pierce commented 1 week ago

You can use a reverse proxy like Nginx, Caddy, or Traefik to separate the domain for DoH and the Dashboard.

For example, you can use the domain dns.example.com only to handle /dns-query (DNS over HTTPS) and block access to the dashboard on dns.example.com or redirect to error 404. Use the domain dns-dashboard.example.com for dashboard access.

saint-lascivious commented 1 week ago

If you expand this outside of HTTPS, and also look towards TLS and QUIC (and H3?), the same problems are realised without the (IMO flawed) argument of "well ahhckshully …you're directing queries to a URL rather than a domain with a port suffix".

vdias commented 1 week ago

You can use a reverse proxy like Nginx, Caddy, or Traefik to separate the domain for DoH and the Dashboard.

For example, you can use the domain dns.example.com only to handle /dns-query (DNS over HTTPS) and block access to the dashboard on dns.example.com or redirect to error 404. Use the domain dns-dashboard.example.com for dashboard access.

Any nginx conf example?

Marcus1Pierce commented 1 week ago

@vdias Maybe you can try this:

Configuration for dns.example.com

server {
    listen 443 ssl http2;                # Enable HTTP/2
    listen [::]:443 ssl http2;           # Enable HTTP/2 for IPv6
    server_name dns.example.com;

    ssl_certificate /etc/letsencrypt/live/dns.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dns.example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;  # Simplified for strong ciphers

    # Proxy for /dns-query
    location = /dns-query {
        proxy_pass https://adguardhome-ip:port;
        proxy_set_header Host $host;
        proxy_ssl_server_name on;
        proxy_ssl_name dns.example.com;
    }

    # Proxy for /dns-query/*
    location ~ ^/dns-query/.*$ {
        proxy_pass https://adguardhome-ip:port;
        proxy_set_header Host $host;
        proxy_ssl_server_name on;
        proxy_ssl_name dns.example.com;
    }

    # Respond with 404 for all other routes
    location / {
        return 404;
    }
}

Configuration for dns-dashboard.example.com

server {
    listen 443 ssl http2;                # Enable HTTP/2
    listen [::]:443 ssl http2;           # Enable HTTP/2 for IPv6
    server_name dns-dashboard.example.com;

    ssl_certificate /etc/letsencrypt/live/dns.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dns.example.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;  # Simplified for strong ciphers

    # Proxy all other requests to adguardhome
    location / {
        proxy_pass https://adguardhome-ip:port;
    }

    # Respond with 404 for /dns-query and /dns-query/*
    location = /dns-query {
        return 404;
    }

    location ~ ^/dns-query/.*$ {
        return 404;
    }
}

I’m not sure whether this is the correct configuration or not. I got this config from ChatGPT. It might need to be checked again to ensure it meets the requirements.

vdias commented 1 week ago

One last question... if adgurad already have the certificate part... do i need to offload it again to nginx...

Marcus1Pierce commented 1 week ago

It seems so. Just try to match the certificate with the one in AdGuardHome.

vdias commented 1 week ago

This is completely no sense... nginx do not work...

Even something as simple as this do not work...

nginx.conf

server {
    listen 443 ssl;
    server_name XXXXXXX.com;

    ssl_certificate /etc/letsencrypt/live/XXXXXXX/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/XXXXXXX/privkey.pem;

    location / {
        proxy_pass https://localhost:4443/;
        proxy_set_header Host $host;
        allow PUBLIC-IP-HOME/32;
        deny all;
    }

    location /dns-query {
        proxy_pass https://localhost:4443/dns-query;
    }
}

AdGuardHome.yaml

tls:
  enabled: true
  server_name: XXXXXXX.com
  force_https: false
  port_https: 4443
  port_dns_over_tls: 853
  port_dns_over_quic: 853
  port_dnscrypt: 0
  dnscrypt_config_file: ""
  allow_unencrypted_doh: true
  certificate_chain: ""
  private_key: ""
  certificate_path: ""
  private_key_path: ""
  strict_sni_check: false
saint-lascivious commented 1 week ago

And as I attempted to point out, the web interface would still be accessible via QUIC, so it's mostly a moot point I think.

vdias commented 1 week ago

it a product design limitation... completely no sense...

admin should use one port DOH another one and so on...

saint-lascivious commented 1 week ago

Sharing ports isn't ultimately the issue I don't think. The issue is resolution capabilities and web administration interface listening address/interface not being able to be decoupled, and/or the lack of IP/CIDR based access control for the web interface.

Being able to disable/enable the web interface entirely would also be quite nice.

Marcus1Pierce commented 1 week ago

@vdias Try searching for issues related with filter here https://github.com/AdguardTeam/AdGuardHome/issues. I previously used Nginx for something similar, but I have forgotten the details. Now I use Caddy for this, and it works well for me.

This is my config with caddy.

AdGuardHome.yaml

tls:
  enabled: true
  server_name: dns.example.com
  force_https: false
  port_https: 443
  port_dns_over_tls: 853
  port_dns_over_quic: 853
  port_dnscrypt: 0
  dnscrypt_config_file: ""
  allow_unencrypted_doh: false
  certificate_chain: ""
  private_key: ""
  certificate_path: /etc/letsencrypt/live/dns.example.com/fullchain.pem
  private_key_path: /etc/letsencrypt/live/dns.example.com/privkey.pem
  strict_sni_check: false

Caddyfile

dns.example.com {
        tls /etc/letsencrypt/live/dns.example.com/fullchain.pem /etc/letsencrypt/live/dns.example.com/privkey.pem

        log {
                output file /log/dns-ads.log {
                        roll_size 2MiB
                }
                level INFO
        }

        handle /dns-query {
                reverse_proxy https://adguardhome {
                        trusted_proxies 10.1.1.0/24
                        header_up Host {upstream_hostport}
                        transport http {
                                tls
                                tls_server_name dns.example.com
                        }
                }
        }

        handle /dns-query/* {
                reverse_proxy https://adguardhome {
                trusted_proxies 10.1.1.0/24
                header_up Host {upstream_hostport}
                        transport http {
                                tls
                                tls_server_name dns.example.com
                        }
                }
        }

        handle / {
                respond 404
        }
}

dns-dashboard.example.com {
        tls /etc/letsencrypt/live/example.com/fullchain.pem /etc/letsencrypt/live/example.com/privkey.pem

        reverse_proxy https://adguardhome {
                transport http {
                        tls_insecure_skip_verify
                }
        }

        handle /dns-query {
                respond 404
        }

        handle /dns-query/* {
                respond 404
        }

        header {
                Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
                X-Content-Type-Options "nosniff"
                X-Frame-Options "SAMEORIGIN"
                X-XSS-Protection "1; mode=block"
                Referrer-Policy "no-referrer"
        }
}
Marcus1Pierce commented 1 week ago

And as I attempted to point out, the web interface would still be accessible via QUIC, so it's mostly a moot point I think.

In my case, the web interface still blocked even when using the H3/QUIC protocol.

This is the image when I try to access dashboard from the DoH subdomain. DNS Block