chore: rebuild udp dns resolve

The DNS resolution of the overall UDP part has been delayed to the connection initiation stage. During the rule matching process, it will only be triggered when the IP rule without no-resolve is matched.

For direct and wireguard outbound, the same logic as the TCP part will be followed, that is, when direct-nameserver (or DNS configured by wireguard) exists, the result of the matching process will be discarded and the domain name will be re-resolved. This re-resolution logic is only effective for fakeip.

For reject and DNS outbound, no resolution is required.

For other outbound, resolution will still be performed when the connection is initiated, and the domain name will not be sent directly to the remote server at present.
This commit is contained in:
wwqgtxx
2025-05-27 10:45:26 +08:00
parent 12e3952b74
commit a1c7881229
24 changed files with 246 additions and 190 deletions

View File

@@ -76,9 +76,9 @@ func (sniffer *QuicSniffer) SniffData(b []byte) (string, error) {
func (sniffer *QuicSniffer) WrapperSender(packetSender constant.PacketSender, override bool) constant.PacketSender {
return &quicPacketSender{
sender: packetSender,
chClose: make(chan struct{}),
override: override,
PacketSender: packetSender,
chClose: make(chan struct{}),
override: override,
}
}
@@ -91,7 +91,7 @@ type quicPacketSender struct {
result string
override bool
sender constant.PacketSender
constant.PacketSender
chClose chan struct{}
closed bool
@@ -100,7 +100,7 @@ type quicPacketSender struct {
// Send will send PacketAdapter nonblocking
// the implement must call UDPPacket.Drop() inside Send
func (q *quicPacketSender) Send(current constant.PacketAdapter) {
defer q.sender.Send(current)
defer q.PacketSender.Send(current)
q.lock.RLock()
if q.closed {
@@ -116,29 +116,24 @@ func (q *quicPacketSender) Send(current constant.PacketAdapter) {
}
}
// Process is a blocking loop to send PacketAdapter to PacketConn and update the WriteBackProxy
func (q *quicPacketSender) Process(conn constant.PacketConn, proxy constant.WriteBackProxy) {
q.sender.Process(conn, proxy)
}
// ResolveUDP wait sniffer recv all fragments and update the domain
func (q *quicPacketSender) ResolveUDP(data *constant.Metadata) error {
// DoSniff wait sniffer recv all fragments and update the domain
func (q *quicPacketSender) DoSniff(metadata *constant.Metadata) error {
select {
case <-q.chClose:
q.lock.RLock()
replaceDomain(data, q.result, q.override)
replaceDomain(metadata, q.result, q.override)
q.lock.RUnlock()
break
case <-time.After(quicWaitConn):
q.close()
}
return q.sender.ResolveUDP(data)
return q.PacketSender.DoSniff(metadata)
}
// Close stop the Process loop
func (q *quicPacketSender) Close() {
q.sender.Close()
q.PacketSender.Close()
q.close()
}

View File

@@ -12,7 +12,7 @@ import (
)
type fakeSender struct {
resultCh chan *constant.Metadata
constant.PacketSender
}
var _ constant.PacketSender = (*fakeSender)(nil)
@@ -22,18 +22,7 @@ func (e *fakeSender) Send(packet constant.PacketAdapter) {
packet.Drop()
}
func (e *fakeSender) Process(constant.PacketConn, constant.WriteBackProxy) {
panic("not implemented")
}
func (e *fakeSender) ResolveUDP(metadata *constant.Metadata) error {
e.resultCh <- metadata
return nil
}
func (e *fakeSender) Close() {
panic("not implemented")
}
func (e *fakeSender) DoSniff(metadata *constant.Metadata) error { return nil }
type fakeUDPPacket struct {
data []byte
@@ -85,16 +74,17 @@ func testQuicSniffer(data []string, async bool) (string, error) {
}
resultCh := make(chan *constant.Metadata, 1)
emptySender := &fakeSender{resultCh: resultCh}
emptySender := &fakeSender{}
sender := q.WrapperSender(emptySender, true)
go func() {
meta := constant.Metadata{}
err = sender.ResolveUDP(&meta)
err := sender.DoSniff(&meta)
if err != nil {
panic(err)
}
resultCh <- &meta
}()
for _, d := range data {