Restore protected desktop DNS resolver - #148
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a Linux/Windows “session Core” executable alongside the existing native library artifacts, with a process-wide DNS resolver that binds DNS sockets to a selected active non-loopback interface and is restored on shutdown. This aligns with libXray’s desktop packaging story by shipping a constrained CLI wrapper (xray run ...) and validating it in CI.
Changes:
- Introduces
desktop_bin(bin/xray/bin/xray.exe) with strictrun -dns <IP:port> -interface <name> -config <xray.json>parsing and basic tests. - Adds desktop DNS binding/restore logic (
dnspackage) and platform-specific socket binding for Windows/Linux. - Updates build scripts, CI workflows, and documentation to build/package/verify the desktop Core.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| readme/README.zh_CN.md | Documents the Linux/Windows session Core CLI contract. |
| README.md | Documents the Linux/Windows session Core CLI contract (English). |
| go.mod | Promotes golang.org/x/sys to a direct dependency for desktop DNS binding. |
| dns/resolver.go | Refactors resolver creation to support a generalized socket-control hook. |
| dns/dns_windows.go | Adds Windows socket binding for DNS traffic to a specific interface. |
| dns/dns_linux.go | Adds Linux socket binding for DNS traffic to a specific interface. |
| dns/dns_desktop.go | Adds desktop SetDNS/ResetDNS that binds DNS sockets to an interface and restores the prior resolver. |
| desktop_bin/main.go | Implements the desktop session Core CLI and lifecycle (SetDNS → RunXray → wait → StopXray). |
| desktop_bin/main_test.go | Tests CLI flag parsing/validation for the session Core. |
| build/app/windows.py | Builds and packages bin/xray.exe for Windows artifacts. |
| build/app/linux.py | Builds and packages bin/xray for Linux artifacts. |
| build/app/build.py | Adds shared build_desktop_bin helper for desktop Core compilation. |
| AGENTS.md | Updates repository layout/docs to include the new desktop Core artifact and behavior. |
| .github/workflows/validate.yml | Validates Linux artifacts now include a runnable ./bin/xray -h. |
| .github/workflows/build.yml | Tests/validates desktop Core and packages it into Linux/Windows build artifacts. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
dns/dns_linux.go:13
- bindDNSInterface returns the raw unix.BindToDevice error, which makes it hard to tell which interface the resolver tried to bind to when failures occur (e.g., EPERM without required OS privileges/capabilities). Wrapping the error with the interface name improves diagnostics for the session Core and SetDNS callers.
func bindDNSInterface(_ string, fd uintptr, iface *net.Interface) error {
return unix.BindToDevice(int(fd), iface.Name)
}
dns/dns_windows.go:38
- When interface binding fails on Windows, the returned error lacks context about which interface/network was being enforced, which makes it difficult to diagnose DNS failures from the session Core. Wrapping SetsockoptInt errors with the interface name (and network) will make failures actionable without changing behavior.
func bindDNSInterface(network string, fd uintptr, iface *net.Interface) error {
switch network {
case "tcp4", "udp4", "ip4":
index := int(int32(bits.ReverseBytes32(uint32(iface.Index))))
return windows.SetsockoptInt(
Summary
run -dns <IP:port> -interface <name> -config <xray.json>Testing
go test ./... -count=1git diff --check