AdguardTeam / AdguardTeam/dnsproxy
[Feature Request] Add support for Unix Domain Sockets
- 主要语言
- Go
- 星标
- 3.3k
- 派生
- 343
- PR 合并指标
- 30 天内没有已合并 PR
描述
Dear developers,
Currently, `dnsproxy` can only use IP sockets for upstream and downstream communication. For many use cases where `dnsproxy` runs on same machine as client or an upstream resolver (like a local Unbound), this is not optimal. Using TCP loopback (`127.0.0.1`) for local communication creates unnecessary network overhead from the TCP/IP stack that we could avoid.
I would like to propose adding a possibility for `dnsproxy` to use Unix Domain Sockets (UDS). This would be for both upstream connections and for listening sockets.
The desired behavior would be to allow configurations like this:
* `unix:/path/to/dns.sock` for plain DNS over a datagram socket.
* `tls+unix:/path/to/dns.sock` for DNS-over-TLS over a stream socket.
To achieve this, `dnsproxy` would need to use Go's `net.Dial("unixgram", ...)` for UDP-like protocols and `net.Dial("unix", ...)` for TCP-like protocols.
The only alternative is to continue using TCP loopback. As I will explain below, this is less performant and has a less robust security model for local IPC.
**Additional context**
I have done a small research on this topic, and I believe this feature would be very valuable.
#### 1. Performance Benefit
The performance benefit is the main reason for this request. For small packets like DNS queries, UDS is much faster than TCP loopback.
* **Throughput:** Benchmarks show UDS can handle over 2x more messages per second (one test showed ~22,000 msgs/sec for UDS vs ~10,000 for TCP).
* **Latency:** Latency can be 3 times lower (e.g., 2µs for UDS vs 6µs for TCP).
This is because UDS is a direct communication channel through the kernel and it completely bypasses the network stack. There is no TCP three-way handshake, no packet encapsulation, and no checksum calculation.
#### 2. Security Improvement
Also, security is better with UDS. A socket is a file in the filesystem, so we can use standard Unix file permissions (`chmod`, `chown`) to control exactly which user or process can access it. This is much more granular and simple than managing access to a TCP port, where any local process can try to connect by default.
#### 3. Practical Use Case: Reverse Proxy Integration
A very good use case is integration with a reverse proxy like Nginx. Nginx can be configured to handle the TLS termination for DoT or DoQ and then forward the plain DNS requests to `dnsproxy` over a very fast UDS connection.
#### 4. Known Limitations & Challenges
Of course, I understand there are some complications.
* **Windows Limitation:** The biggest problem is Windows. As I understand, Go's `net` package on Windows supports `unix` (stream sockets) but **does not** support `unixgram` (datagram sockets). This is a big limitation because it means proxying plain DNS-over-UDP would not work on Windows. For this platform, maybe the feature can be disabled or it must fallback to TCP. This should be clearly documented.
* **Socket File Management:** The `dnsproxy` process would be responsible for the socket file. If the program crashes, the stale socket file can remain and cause an error on restart. The program must have logic to check for and remove the old socket file when it starts.
Even with these limitations, the performance and security benefits on Unix-like systems (Linux, BSD, macOS) where most servers run are very significant. Thank you for considering this feature.
**P.S.**
It's a followup of [my previous FR in Adguard Home repo](https://github.com/AdguardTeam/AdGuardHome/issues/3840)
贡献指南
这个仓库没有索引到贡献指南
评估
这个 Issue 还没有评估数据。