AdguardTeam / AdGuardHome

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

Set SO_REUSEADDR on the server sockets #1861

Closed Mosney closed 4 years ago

Mosney commented 4 years ago

Prerequisites

Please answer the following questions for yourself before submitting an issue. YOU MAY DELETE THE PREREQUISITES SECTION.

Issue Details

Additional Information

I deploy a proxy software clash as gateway transparent proxy at OpenWrt which also run AdGuardHome, and AGH's config is bind_host: 0.0.0.0. Because of AGH deficiencies(see original issue below).
In conclusion, AGH not allow reuse bind-address, so other processes cannot writeback via :53 port, cause proxy software behavioural peculiarities, it will lead proxied standard DNS query respond failed. And it will not affect local network DNS query which not through proxy at all. Of course, is a small probability bug, few users run AGH and proxy software on the same system. Nevertheless, I still hope you can check and fix it, AGH is a gateway level service, it should robustness and compatibility enough.

Original issue: https://github.com/Dreamacro/clash/issues/616#issuecomment-611961492 Comment translation: Some programs bind to0.0.0.0:53 or :::53 and no set SO_REUSEADDR, which makes it impossible to bind the WriteBack By 8.8.8.8:53

Mosney commented 4 years ago

Forgot to mention it: Don't use 0.0.0.0/:: to bind is a quick way to fix this issue, but the drawbacks are obvious, you will no longer be able to listen all IP.

ameshkov commented 4 years ago

This SO_REUSEADDR is an old golang issue, but it seems I've finally found a way to fix it.

@szolin check this out: https://gist.github.com/joliver/4ccd58605e07e8edf71904b172d95513

I am not sure if this approach will work properly on Windows, but other than that, it seems okay.

szolin commented 4 years ago

I don't understand how it's possible.

Some programs bind to 0.0.0.0:53 or :::53 and no set SO_REUSEADDR, which makes it impossible to bind the WriteBack By 8.8.8.8:53

SO_REUSEADDR won't help in case AGH is listening on 0.0.0.0

check this out: https://gist.github.com/joliver/4ccd58605e07e8edf71904b172d95513

SO_REUSEPORT is a feature for distributing network load between several processes of the same application. If we start using it, we will receive half of the incoming requests. The other half will be received by another application.

ihipop commented 1 year ago

I don't understand how it's possible.

Some programs bind to 0.0.0.0:53 or :::53 and no set SO_REUSEADDR, which makes it impossible to bind the WriteBack By 8.8.8.8:53

It's possible. If you dive into the Linux TPROXY stack,when processing a UDP connection, for example ,if the Dest Addr is 8.8.8.8:53, the TPROXY program must bind to 8.8.8.8:53 on TPROXY host os and send the UDP packet back to the Client to make sure the Src Addr and Port is 8.8.8.8:53 , IF,when ADG has binded :53 on this host os without SO_REUSEADDR, the behavior of the TPROXY program will fail with EADDRINUSE (Address already in use)

Here are some example of TPROXY program that has this behavior

https://github.com/Dreamacro/clash/blob/8c7c8f43741923d6a7650dc723b4b51b0f540777/listener/tproxy/packet.go#L20

https://github.com/v2fly/v2ray-core/blob/541fb5c5b173cc60b2009fa0fe3ca4b27133f40c/proxy/dokodemo/dokodemo.go#L161-L168

SO_REUSEADDR won't help in case AGH is listening on 0.0.0.0

check this out: https://gist.github.com/joliver/4ccd58605e07e8edf71904b172d95513

SO_REUSEPORT is a feature for distributing network load between several processes of the same application. If we start using it, we will receive half of the incoming requests. The other half will be received by another application.

it's true when working with distributing network load between several processes, but in the scene above I've mentioned ,it's really safe for ADG to use SO_REUSEADDR,because we wont get inbound connection to 8.8.8.8:53 for our HOST And,DNSMASQ also allow SO_REUSEADDR by default

IMO, we should make this behavior configurable...

@ameshkov @szolin

ihipop commented 1 year ago

after 5 days since this comment,the Team seems to take some actions to support SO_REUSEADDR

https://github.com/AdguardTeam/dnsproxy/commit/5864a879fd36361c644d99f94af14aae9b7ed9b6#diff-8a752bfb9f71b4905540ffeaf78349f38982a8283eac10f845f3eaeb58ba63f6R19

I just can't understand why SO_REUSEPORT is also used and the TCP listen is also applied to these socket options. these aren't necessary, IMO. let's wait and see @ainar-g