AdguardTeam / AdGuardHome

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

Support PROXY Protocol #2798

Open ZeroClover opened 3 years ago

ZeroClover commented 3 years ago

When using AGH through a load balancer or reverse proxy (probably because I don't want to expose the AGH directly or just want to high availability), DoH can get the user's original IP address through the HTTP header but regular DNS and DoT cannot.

This isn't good for use cases where the AGH is deployed on a server. This is especially important for sites that use GeoDNS for CDN allocation because AGH needs the user's original IP to send the ECS to the recursive DNS server.

This situation is also mentioned in this issue (#1789), where @ameshkov says, "Unfortunately, there are no such options for TLS/TCP."

But in fact, both Nginx and HAProxy can use PROXY Protocol to send the user's real IP over Layer 4. nginx.com has written an article describing how to use Nginx as a DoH / DoT gateway. We just need to add proxy_protocol on; in the stream section to send the user's original IP via PROXY Protocol, but this requires AGH support.

dvonessen commented 3 years ago

I am also interested in this feature. Right now, I am using Kubernetes with Traefik and MetalLB to expose ports on my nodes. All my services are behind Traefik except AGH because of the missing distinction of the clients in AGH. I seeh @ameshkov has remarked it to be in the mileston v1.0.0 would love to see it earlier. ;-) Regards!

Akruidenberg commented 3 years ago

Same Here.

dvonessen commented 3 years ago

@Akruidenberg don't forget to thumbs up first post.

ZeroClover commented 3 years ago

@dvonessen @Akruidenberg

Although AdGuard Home does not support this feature at this time, the same effect can be achieved with go-mmproxy.

https://github.com/path-network/go-mmproxy

The go-mmproxy gives AdGuard Home the ability to obtain the original IP of the client sent by the load balancer via PROXY Protocol.

ameshkov commented 3 years ago

Oh, there's a ready-to-use golang code for that? That's nice, makes it easier to implement inside AGH when we finally are ready to.

Meanwhile, please use go-mmproxy for that.

Akruidenberg commented 3 years ago

Oh, there's a ready-to-use golang code for that? That's nice, makes it easier to implement inside AGH when we finally are ready to.

Meanwhile, please use go-mmproxy for that.

Sadly, there is no docker support for mmproxy.

ZeroClover commented 3 years ago

@Akruidenberg It seems to be possible to use mmproxy on Docker / k8s.

https://andrewmichaelsmith.com/2020/02/preserving-client-ip-in-kubernetes/ https://hub.docker.com/r/unixfox/go-mmproxy

heygo1345678 commented 1 year ago

https://github.com/path-network/go-mmproxy

i try it (https://hub.docker.com/r/unixfox/go-mmproxy) but do not support ipv6 my nginx config:

map $ssl_preread_server_name $dot_map {

alist.example.com dot; }

upstream dot{

    server 192.168.1.2:25577;
}

server { listen 853 ; listen [::]:853 ; proxy_pass $dot_map; ssl_preread on;

proxy_protocol on;

}

my docker go-mmproxy config :

!/bin/sh

sleep 5 ip rule add from 127.0.0.1/8 iif lo table 123 ip route add local 0.0.0.0/0 dev lo table 123

ip -6 rule add from ::1/128 iif lo table 123 ip -6 route add local ::/0 dev lo table 123

echo -en "0.0.0.0/0\n::/0\n" > allowed-networks.txt /usr/bin/go-mmproxy -l 0.0.0.0:25577 -4 127.0.0.1:853 -6 [::1]:853 --allowed-subnets allowed-networks.txt -v 2 /bin/sh

my adguard home listen 853 for dot i checked adguard home it worked for ipv4 only, only have client real ip for ipv4 adguard home version v0.108.0-b.29 go-mmproxy log:

tempsnip

L8X commented 1 year ago

Bump. I need this feature for Nginx in order to be able to securely and correctly proxy DoT and DoUDP / DoTCP.

I'm quite unsure why this has been put on the back burner, it's quite an important feature to add.

eiqnepm commented 1 year ago

It would be really nice if AdGuard Home worked on adding support for The PROXY protocol, by doing so it would allow us to identify DoT clients while using a reverse proxy.

I'm currently running AdGuard Home together with Traefik in Docker using Docker Compose. Traefik is really convenient for routing to multiple Docker containers using labels, and for managing multiple certificates without human input.

docker-compose.yaml ```yaml version: "3" services: traefik: command: - --providers.docker=true - --providers.docker.exposedbydefault=false - --certificatesresolvers.myresolver.acme.dnschallenge=true - --certificatesresolvers.myresolver.acme.dnschallenge.provider=duckdns - --certificatesresolvers.myresolver.acme.email=webmaster@👀.duckdns.org - --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json - --entrypoints.websecure.address=:443 - --entrypoints.web.address=:80 - --entrypoints.web.http.redirections.entrypoint.to=websecure - --entrypoints.dot.address=:853 container_name: traefik depends_on: - adguardhome environment: - DUCKDNS_TOKEN=👀 image: traefik:v3.0 ports: - 80:80 - 443:443 - 853:853 restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt adguardhome: container_name: adguardhome image: adguard/adguardhome labels: - traefik.enable=true - traefik.http.routers.adguardhome-https.rule=Host(`adguardhome.👀.duckdns.org`) - traefik.http.routers.adguardhome-https.entrypoints=websecure - traefik.http.routers.adguardhome-https.tls.certresolver=myresolver - traefik.http.services.adguardhome-https.loadbalancer.server.port=3000 - traefik.http.routers.adguardhome-https.service=adguardhome-https - traefik.tcp.routers.adguardhome_dot.rule=HostSNI(`adguardhome.👀.duckdns.org`) || HostSNIRegexp(`^.+\.adguardhome\.👀\.duckdns\.org$`) - traefik.tcp.routers.adguardhome_dot.entrypoints=dot - traefik.tcp.routers.adguardhome_dot.tls.domains[0].main=adguardhome.👀.duckdns.org - traefik.tcp.routers.adguardhome_dot.tls.domains[0].sans=*.adguardhome.👀.duckdns.org - traefik.tcp.routers.adguardhome_dot.tls.certresolver=myresolver # - traefik.tcp.services.adguardhome_dot.loadbalancer.proxyprotocol.version=2 # - traefik.tcp.routers.adguardhome_dot.service=adguardhome_dot restart: unless-stopped volumes: - ./adguardhome/work:/opt/adguardhome/work - ./adguardhome/conf:/opt/adguardhome/conf ```
AdGuardHome.yaml ```yaml dns: trusted_proxies: - 127.0.0.0/8 - ::1/128 - 10.0.0.0/8 - 172.16.0.0/12 - 192.168.0.0/16 tls: enabled: true server_name: adguardhome.👀.duckdns.org allow_unencrypted_doh: true ```
mash-tec commented 10 months ago

I would also find PROXY protocol support extremly helpful! Would really like to the that feature.

cr0wdelex commented 9 months ago

I just wasted 3 nights to do passing real-IP through DoT and found out that AG does not support it.

I think this is an important feature need to implement since DoT is used in Android device a lot.

maretodoric commented 7 months ago

Bumping this thread since as of 2024, this is still unsupported and i truly believe that we should not resort to unsafe workarounds with go-mmproxy

jaen commented 6 months ago

I would also appreciate support for that. I've moved from static blocklist zones to AdGuard recently, so I could change them dynamically should I need to – but since my AdGuard is behind CoreDNS, I am unable to use per-client filtering.