diff --git a/common/sniff/dns.go b/common/sniff/dns.go index 13bd7b98..be9e369d 100644 --- a/common/sniff/dns.go +++ b/common/sniff/dns.go @@ -53,7 +53,7 @@ func DomainNameQuery(ctx context.Context, packet []byte) (*adapter.InboundContex } domain := question.Name.String() if question.Class == dnsmessage.ClassINET && (question.Type == dnsmessage.TypeA || question.Type == dnsmessage.TypeAAAA) && IsDomainName(domain) { - return &adapter.InboundContext{Protocol: C.ProtocolDNS, Domain: domain}, nil + return &adapter.InboundContext{Protocol: C.ProtocolDNS /*, Domain: domain*/}, nil } return nil, os.ErrInvalid } diff --git a/constant/proxy.go b/constant/proxy.go index f037e76b..43e39671 100644 --- a/constant/proxy.go +++ b/constant/proxy.go @@ -4,9 +4,9 @@ const ( TypeTun = "tun" TypeRedirect = "redirect" TypeTProxy = "tproxy" - TypeDNS = "dns" TypeDirect = "direct" TypeBlock = "block" + TypeDNS = "dns" TypeSocks = "socks" TypeHTTP = "http" TypeMixed = "mixed" diff --git a/inbound/builder.go b/inbound/builder.go index e6a80ee7..277f9532 100644 --- a/inbound/builder.go +++ b/inbound/builder.go @@ -22,8 +22,6 @@ func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, o return NewRedirect(ctx, router, logger, options.Tag, options.RedirectOptions), nil case C.TypeTProxy: return NewTProxy(ctx, router, logger, options.Tag, options.TProxyOptions), nil - case C.TypeDNS: - return NewDNS(ctx, router, logger, options.Tag, options.DNSOptions), nil case C.TypeDirect: return NewDirect(ctx, router, logger, options.Tag, options.DirectOptions), nil case C.TypeSocks: diff --git a/inbound/tun.go b/inbound/tun.go index acb57281..187e1433 100644 --- a/inbound/tun.go +++ b/inbound/tun.go @@ -21,7 +21,6 @@ import ( F "github.com/sagernet/sing/common/format" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" - "github.com/sagernet/sing/common/task" ) var _ adapter.Inbound = (*Tun)(nil) @@ -38,7 +37,6 @@ type Tun struct { inet4Address netip.Prefix inet6Address netip.Prefix autoRoute bool - hijackDNS bool tunIf tun.Tun tunStack *tun.GVisorTun @@ -64,7 +62,6 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger inet4Address: options.Inet4Address.Build(), inet6Address: options.Inet6Address.Build(), autoRoute: options.AutoRoute, - hijackDNS: options.HijackDNS, }, nil } @@ -109,11 +106,6 @@ func (t *Tun) NewConnection(ctx context.Context, conn net.Conn, upstreamMetadata metadata.SniffEnabled = t.inboundOptions.SniffEnabled metadata.SniffOverrideDestination = t.inboundOptions.SniffOverrideDestination metadata.DomainStrategy = dns.DomainStrategy(t.inboundOptions.DomainStrategy) - if t.hijackDNS && upstreamMetadata.Destination.Port == 53 { - return task.Run(ctx, func() error { - return NewDNSConnection(ctx, t.router, t.logger, conn, metadata) - }) - } t.logger.InfoContext(ctx, "inbound connection from ", metadata.Source) t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) err := t.router.RouteConnection(ctx, conn, metadata) @@ -134,11 +126,6 @@ func (t *Tun) NewPacketConnection(ctx context.Context, conn N.PacketConn, upstre metadata.SniffEnabled = t.inboundOptions.SniffEnabled metadata.SniffOverrideDestination = t.inboundOptions.SniffOverrideDestination metadata.DomainStrategy = dns.DomainStrategy(t.inboundOptions.DomainStrategy) - if t.hijackDNS && upstreamMetadata.Destination.Port == 53 { - return task.Run(ctx, func() error { - return NewDNSPacketConnection(ctx, t.router, t.logger, conn, metadata) - }) - } t.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source) t.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) err := t.router.RoutePacketConnection(ctx, conn, metadata) diff --git a/option/inbound.go b/option/inbound.go index 22b6fd51..bc710166 100644 --- a/option/inbound.go +++ b/option/inbound.go @@ -15,7 +15,6 @@ type _Inbound struct { TunOptions TunInboundOptions `json:"-"` RedirectOptions RedirectInboundOptions `json:"-"` TProxyOptions TProxyInboundOptions `json:"-"` - DNSOptions DNSInboundOptions `json:"-"` DirectOptions DirectInboundOptions `json:"-"` SocksOptions SocksInboundOptions `json:"-"` HTTPOptions HTTPMixedInboundOptions `json:"-"` @@ -32,7 +31,6 @@ func (h Inbound) Equals(other Inbound) bool { h.TunOptions == other.TunOptions && h.RedirectOptions == other.RedirectOptions && h.TProxyOptions == other.TProxyOptions && - h.DNSOptions == other.DNSOptions && h.DirectOptions == other.DirectOptions && h.SocksOptions.Equals(other.SocksOptions) && h.HTTPOptions.Equals(other.HTTPOptions) && @@ -50,8 +48,6 @@ func (h Inbound) MarshalJSON() ([]byte, error) { v = h.RedirectOptions case C.TypeTProxy: v = h.TProxyOptions - case C.TypeDNS: - v = h.DNSOptions case C.TypeDirect: v = h.DirectOptions case C.TypeSocks: @@ -83,8 +79,6 @@ func (h *Inbound) UnmarshalJSON(bytes []byte) error { v = &h.RedirectOptions case C.TypeTProxy: v = &h.TProxyOptions - case C.TypeDNS: - v = &h.DNSOptions case C.TypeDirect: v = &h.DirectOptions case C.TypeSocks: @@ -200,7 +194,6 @@ type TunInboundOptions struct { Inet4Address *ListenPrefix `json:"inet4_address,omitempty"` Inet6Address *ListenPrefix `json:"inet6_address,omitempty"` AutoRoute bool `json:"auto_route,omitempty"` - HijackDNS bool `json:"hijack_dns,omitempty"` InboundOptions } diff --git a/option/outbound.go b/option/outbound.go index f56d5962..74c9e40b 100644 --- a/option/outbound.go +++ b/option/outbound.go @@ -40,7 +40,7 @@ func (h Outbound) MarshalJSON() ([]byte, error) { switch h.Type { case C.TypeDirect: v = h.DirectOptions - case C.TypeBlock: + case C.TypeBlock, C.TypeDNS: v = nil case C.TypeSocks: v = h.SocksOptions @@ -69,7 +69,7 @@ func (h *Outbound) UnmarshalJSON(bytes []byte) error { switch h.Type { case C.TypeDirect: v = &h.DirectOptions - case C.TypeBlock: + case C.TypeBlock, C.TypeDNS: v = nil case C.TypeSocks: v = &h.SocksOptions diff --git a/outbound/block.go b/outbound/block.go index b16e6170..1717f983 100644 --- a/outbound/block.go +++ b/outbound/block.go @@ -22,9 +22,9 @@ func NewBlock(logger log.ContextLogger, tag string) *Block { return &Block{ myOutboundAdapter{ protocol: C.TypeBlock, + network: []string{C.NetworkTCP, C.NetworkUDP}, logger: logger, tag: tag, - network: []string{C.NetworkTCP, C.NetworkUDP}, }, } } diff --git a/outbound/builder.go b/outbound/builder.go index faa00980..5e8d29c7 100644 --- a/outbound/builder.go +++ b/outbound/builder.go @@ -18,6 +18,8 @@ func New(router adapter.Router, logger log.ContextLogger, options option.Outboun return NewDirect(router, logger, options.Tag, options.DirectOptions), nil case C.TypeBlock: return NewBlock(logger, options.Tag), nil + case C.TypeDNS: + return NewDNS(router, logger, options.Tag), nil case C.TypeSocks: return NewSocks(router, logger, options.Tag, options.SocksOptions) case C.TypeHTTP: diff --git a/outbound/default.go b/outbound/default.go index e1ae0b53..b0cfb445 100644 --- a/outbound/default.go +++ b/outbound/default.go @@ -18,9 +18,10 @@ import ( type myOutboundAdapter struct { protocol string + network []string + router adapter.Router logger log.ContextLogger tag string - network []string } func (a *myOutboundAdapter) Type() string { diff --git a/outbound/direct.go b/outbound/direct.go index 317d3d86..b6a411f4 100644 --- a/outbound/direct.go +++ b/outbound/direct.go @@ -27,9 +27,10 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti outbound := &Direct{ myOutboundAdapter: myOutboundAdapter{ protocol: C.TypeDirect, + network: []string{C.NetworkTCP, C.NetworkUDP}, + router: router, logger: logger, tag: tag, - network: []string{C.NetworkTCP, C.NetworkUDP}, }, dialer: dialer.NewOutbound(router, options.OutboundDialerOptions), } diff --git a/inbound/dns.go b/outbound/dns.go similarity index 59% rename from inbound/dns.go rename to outbound/dns.go index dbb11f52..8f93e75f 100644 --- a/inbound/dns.go +++ b/outbound/dns.go @@ -1,67 +1,50 @@ -package inbound +package outbound import ( "context" "encoding/binary" "io" "net" - "net/netip" + "os" "github.com/sagernet/sing-box/adapter" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" - "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" + M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" - "github.com/sagernet/sing/common/udpnat" "golang.org/x/net/dns/dnsmessage" ) +var _ adapter.Outbound = (*DNS)(nil) + type DNS struct { - myInboundAdapter - udpNat *udpnat.Service[netip.AddrPort] + myOutboundAdapter } -func NewDNS(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.DNSInboundOptions) *DNS { - dns := &DNS{ - myInboundAdapter: myInboundAdapter{ - protocol: C.TypeTProxy, - network: options.Network.Build(), - ctx: ctx, - router: router, - logger: logger, - tag: tag, - listenOptions: options.ListenOptions, +func NewDNS(router adapter.Router, logger log.ContextLogger, tag string) *DNS { + return &DNS{ + myOutboundAdapter{ + protocol: C.TypeDNS, + network: []string{C.NetworkTCP, C.NetworkUDP}, + router: router, + logger: logger, + tag: tag, }, } - dns.connHandler = dns - dns.packetHandler = dns - dns.udpNat = udpnat.New[netip.AddrPort](10, adapter.NewUpstreamContextHandler(nil, dns.newPacketConnection, dns)) - dns.packetUpstream = dns.udpNat - return dns +} + +func (d *DNS) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { + return nil, os.ErrInvalid +} + +func (d *DNS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { + return nil, os.ErrInvalid } func (d *DNS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { - return NewDNSConnection(ctx, d.router, d.logger, conn, metadata) -} - -func (d *DNS) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error { - d.udpNat.NewContextPacket(ctx, metadata.Source.AddrPort(), buffer, adapter.UpstreamMetadata(metadata), func(natConn N.PacketConn) (context.Context, N.PacketWriter) { - return adapter.WithContext(log.ContextWithNewID(ctx), &metadata), &udpnat.DirectBackWriter{ - Source: conn, - Nat: natConn, - } - }) - return nil -} - -func (d *DNS) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { - return NewDNSPacketConnection(ctx, d.router, d.logger, conn, metadata) -} - -func NewDNSConnection(ctx context.Context, router adapter.Router, logger log.ContextLogger, conn net.Conn, metadata adapter.InboundContext) error { ctx = adapter.WithContext(ctx, &metadata) _buffer := buf.StackNewSize(1024) defer common.KeepAlive(_buffer) @@ -89,10 +72,10 @@ func NewDNSConnection(ctx context.Context, router adapter.Router, logger log.Con if len(message.Questions) > 0 { question := message.Questions[0] metadata.Domain = string(question.Name.Data[:question.Name.Length-1]) - logger.DebugContext(ctx, "inbound dns query ", formatDNSQuestion(question), " from ", metadata.Source) + d.logger.DebugContext(ctx, "inbound dns query ", formatDNSQuestion(question), " from ", metadata.Source) } go func() error { - response, err := router.Exchange(ctx, &message) + response, err := d.router.Exchange(ctx, &message) if err != nil { return err } @@ -113,7 +96,7 @@ func NewDNSConnection(ctx context.Context, router adapter.Router, logger log.Con } } -func NewDNSPacketConnection(ctx context.Context, router adapter.Router, logger log.ContextLogger, conn N.PacketConn, metadata adapter.InboundContext) error { +func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { ctx = adapter.WithContext(ctx, &metadata) _buffer := buf.StackNewSize(1024) defer common.KeepAlive(_buffer) @@ -133,10 +116,10 @@ func NewDNSPacketConnection(ctx context.Context, router adapter.Router, logger l if len(message.Questions) > 0 { question := message.Questions[0] metadata.Domain = string(question.Name.Data[:question.Name.Length-1]) - logger.DebugContext(ctx, "inbound dns query ", formatDNSQuestion(question), " from ", metadata.Source) + d.logger.DebugContext(ctx, "inbound dns query ", formatDNSQuestion(question), " from ", metadata.Source) } go func() error { - response, err := router.Exchange(ctx, &message) + response, err := d.router.Exchange(ctx, &message) if err != nil { return err } diff --git a/outbound/http.go b/outbound/http.go index 290db2d8..eca3acea 100644 --- a/outbound/http.go +++ b/outbound/http.go @@ -31,9 +31,10 @@ func NewHTTP(router adapter.Router, logger log.ContextLogger, tag string, option return &HTTP{ myOutboundAdapter{ protocol: C.TypeHTTP, + network: []string{C.NetworkTCP}, + router: router, logger: logger, tag: tag, - network: []string{C.NetworkTCP}, }, http.NewClient(detour, options.ServerOptions.Build(), options.Username, options.Password), }, nil diff --git a/outbound/selector.go b/outbound/selector.go index ad7b9ddb..6492a5e1 100644 --- a/outbound/selector.go +++ b/outbound/selector.go @@ -20,7 +20,6 @@ var ( type Selector struct { myOutboundAdapter - router adapter.Router tags []string defaultTag string outbounds map[string]adapter.Outbound @@ -31,10 +30,10 @@ func NewSelector(router adapter.Router, logger log.ContextLogger, tag string, op outbound := &Selector{ myOutboundAdapter: myOutboundAdapter{ protocol: C.TypeSelector, + router: router, logger: logger, tag: tag, }, - router: router, tags: options.Outbounds, defaultTag: options.Default, outbounds: make(map[string]adapter.Outbound), diff --git a/outbound/shadowsocks.go b/outbound/shadowsocks.go index 41eac85c..582b5d84 100644 --- a/outbound/shadowsocks.go +++ b/outbound/shadowsocks.go @@ -33,9 +33,10 @@ func NewShadowsocks(router adapter.Router, logger log.ContextLogger, tag string, return &Shadowsocks{ myOutboundAdapter{ protocol: C.TypeShadowsocks, + network: options.Network.Build(), + router: router, logger: logger, tag: tag, - network: options.Network.Build(), }, dialer.NewOutbound(router, options.OutboundDialerOptions), method, diff --git a/outbound/socks.go b/outbound/socks.go index 981d8fb2..034aa230 100644 --- a/outbound/socks.go +++ b/outbound/socks.go @@ -36,9 +36,10 @@ func NewSocks(router adapter.Router, logger log.ContextLogger, tag string, optio return &Socks{ myOutboundAdapter{ protocol: C.TypeSocks, + network: options.Network.Build(), + router: router, logger: logger, tag: tag, - network: options.Network.Build(), }, socks.NewClient(detour, options.ServerOptions.Build(), version, options.Username, options.Password), }, nil diff --git a/outbound/urltest.go b/outbound/urltest.go index 1a7d69e2..d16748ab 100644 --- a/outbound/urltest.go +++ b/outbound/urltest.go @@ -24,7 +24,6 @@ var ( type URLTest struct { myOutboundAdapter - router adapter.Router tags []string link string interval time.Duration @@ -36,10 +35,10 @@ func NewURLTest(router adapter.Router, logger log.ContextLogger, tag string, opt outbound := &URLTest{ myOutboundAdapter: myOutboundAdapter{ protocol: C.TypeURLTest, + router: router, logger: logger, tag: tag, }, - router: router, tags: options.Outbounds, link: options.URL, interval: time.Duration(options.Interval), diff --git a/outbound/vmess.go b/outbound/vmess.go index 31fd38ae..258ab4b1 100644 --- a/outbound/vmess.go +++ b/outbound/vmess.go @@ -43,9 +43,10 @@ func NewVMess(router adapter.Router, logger log.ContextLogger, tag string, optio return &VMess{ myOutboundAdapter{ protocol: C.TypeVMess, + network: options.Network.Build(), + router: router, logger: logger, tag: tag, - network: options.Network.Build(), }, detour, client, diff --git a/route/router.go b/route/router.go index 1f402ed9..96931ca2 100644 --- a/route/router.go +++ b/route/router.go @@ -439,7 +439,7 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad defer common.KeepAlive(_buffer) buffer := common.Dup(_buffer) defer buffer.Release() - sniffMetadata, err := sniff.PeekStream(ctx, conn, buffer, sniff.TLSClientHello, sniff.HTTPHost) + sniffMetadata, err := sniff.PeekStream(ctx, conn, buffer, sniff.StreamDomainNameQuery, sniff.TLSClientHello, sniff.HTTPHost) if err == nil { metadata.Protocol = sniffMetadata.Protocol metadata.Domain = sniffMetadata.Domain @@ -485,7 +485,7 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m if err != nil { return err } - sniffMetadata, err := sniff.PeekPacket(ctx, buffer.Bytes(), sniff.QUICClientHello, sniff.STUNMessage) + sniffMetadata, err := sniff.PeekPacket(ctx, buffer.Bytes(), sniff.DomainNameQuery, sniff.QUICClientHello, sniff.STUNMessage) originDestination := metadata.Destination if err == nil { metadata.Protocol = sniffMetadata.Protocol