XDNS finalmask: Support resolvers (client) and domains (server) instead of domain (#5872)

https://github.com/XTLS/Xray-core/pull/5872#issuecomment-4192730898

Example: https://github.com/XTLS/Xray-core/pull/5872#issuecomment-4196172391

---------

Co-authored-by: LjhAUMEM <llnu14702@gmail.com>
This commit is contained in:
Nikita Nemirovsky
2026-04-12 03:37:32 +08:00
committed by GitHub
parent a91a88c7b2
commit 1642fdfbdd
10 changed files with 266 additions and 112 deletions
+26 -12
View File
@@ -52,7 +52,7 @@ type queue struct {
type xdnsConnServer struct {
net.PacketConn
domain Name
domains []Name
ch chan *record
readQueue chan *packet
@@ -63,15 +63,22 @@ type xdnsConnServer struct {
}
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
domain, err := ParseName(c.Domain)
if err != nil {
return nil, err
if len(c.Domains) == 0 {
return nil, errors.New("empty domains")
}
domains := make([]Name, 0, len(c.Domains))
for _, domain := range c.Domains {
domain, err := ParseName(domain)
if err != nil {
return nil, err
}
domains = append(domains, domain)
}
conn := &xdnsConnServer{
PacketConn: raw,
domain: domain,
domains: domains,
ch: make(chan *record, 500),
readQueue: make(chan *packet, 512),
@@ -156,8 +163,8 @@ func (c *xdnsConnServer) recvLoop() {
}
n, addr, err := c.PacketConn.ReadFrom(buf[:])
if err != nil || n == 0 {
if go_errors.Is(err, net.ErrClosed) || go_errors.Is(err, io.EOF) {
if err != nil {
if go_errors.Is(err, net.ErrClosed) {
break
}
continue
@@ -169,7 +176,7 @@ func (c *xdnsConnServer) recvLoop() {
continue
}
resp, payload := responseFor(&query, c.domain)
resp, payload := responseFor(&query, c.domains)
var clientID [8]byte
n = copy(clientID[:], payload)
@@ -321,7 +328,7 @@ func (c *xdnsConnServer) sendLoop() {
}
_, err = c.PacketConn.WriteTo(buf, rec.Addr)
if go_errors.Is(err, net.ErrClosed) || go_errors.Is(err, io.ErrClosedPipe) {
if go_errors.Is(err, net.ErrClosed) {
c.closed = true
break
}
@@ -399,7 +406,7 @@ func nextPacketServer(r *bytes.Reader) ([]byte, error) {
}
}
func responseFor(query *Message, domain Name) (*Message, []byte) {
func responseFor(query *Message, domains []Name) (*Message, []byte) {
resp := &Message{
ID: query.ID,
Flags: 0x8000,
@@ -447,7 +454,14 @@ func responseFor(query *Message, domain Name) (*Message, []byte) {
}
question := query.Question[0]
prefix, ok := question.Name.TrimSuffix(domain)
var prefix Name
var ok bool
for _, domain := range domains {
prefix, ok = question.Name.TrimSuffix(domain)
if ok {
break
}
}
if !ok {
resp.Flags |= RcodeNameError
return resp, nil
@@ -525,7 +539,7 @@ func computeMaxEncodedPayload(limit int) int {
},
},
}
resp, _ := responseFor(query, [][]byte{})
resp, _ := responseFor(query, []Name{[][]byte{}})
resp.Answer = []RR{
{