70 lines
2.3 KiB
Go
70 lines
2.3 KiB
Go
package route
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/sagernet/sing-box/adapter"
|
|
C "github.com/sagernet/sing-box/constant"
|
|
"github.com/sagernet/sing-box/dns"
|
|
dnsOutbound "github.com/sagernet/sing-box/protocol/dns"
|
|
R "github.com/sagernet/sing-box/route/rule"
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
M "github.com/sagernet/sing/common/metadata"
|
|
N "github.com/sagernet/sing/common/network"
|
|
|
|
mDNS "github.com/miekg/dns"
|
|
)
|
|
|
|
func (r *Router) hijackDNSStream(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
|
metadata.Destination = M.Socksaddr{}
|
|
for {
|
|
conn.SetReadDeadline(time.Now().Add(C.DNSTimeout))
|
|
err := dnsOutbound.HandleStreamDNSRequest(ctx, r.dns, conn, metadata)
|
|
if err != nil {
|
|
if !E.IsClosedOrCanceled(err) {
|
|
return err
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (r *Router) hijackDNSPacket(ctx context.Context, conn N.PacketConn, packetBuffers []*N.PacketBuffer, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
|
|
err := dnsOutbound.NewDNSPacketConnection(ctx, r.dns, conn, packetBuffers, metadata)
|
|
N.CloseOnHandshakeFailure(conn, onClose, err)
|
|
if err != nil && !E.IsClosedOrCanceled(err) {
|
|
return E.Cause(err, "process DNS packet")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *Router) HijackDNSPacket(ctx context.Context, payload []byte, writer N.PacketWriter, metadata adapter.InboundContext) {
|
|
var message mDNS.Msg
|
|
err := message.Unpack(payload)
|
|
if err != nil {
|
|
r.logger.ErrorContext(ctx, E.Cause(err, "process DNS packet: unpack request"))
|
|
return
|
|
}
|
|
destination := metadata.Destination
|
|
metadata.Destination = M.Socksaddr{}
|
|
r.dns.ExchangeAsync(adapter.WithContext(ctx, &metadata), &message, adapter.DNSQueryOptions{}, func(response *mDNS.Msg, exchangeErr error) {
|
|
if exchangeErr == nil {
|
|
exchangeErr = r.writeDNSPacketResponse(&message, response, writer, destination)
|
|
}
|
|
if exchangeErr != nil && !R.IsRejected(exchangeErr) && !E.IsClosedOrCanceled(exchangeErr) {
|
|
r.logger.ErrorContext(ctx, E.Cause(exchangeErr, "process DNS packet"))
|
|
}
|
|
})
|
|
}
|
|
|
|
func (r *Router) writeDNSPacketResponse(message *mDNS.Msg, response *mDNS.Msg, writer N.PacketWriter, destination M.Socksaddr) error {
|
|
responseBuffer, err := dns.TruncateDNSMessage(message, response, 1024)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return writer.WritePacket(responseBuffer, destination)
|
|
}
|