Deprecate dns_hijack and dns inbound

This commit is contained in:
世界 2022-07-23 09:15:47 +08:00
parent 9f8978bbcf
commit 884c0cf595
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
18 changed files with 50 additions and 83 deletions

View file

@ -53,7 +53,7 @@ func DomainNameQuery(ctx context.Context, packet []byte) (*adapter.InboundContex
} }
domain := question.Name.String() domain := question.Name.String()
if question.Class == dnsmessage.ClassINET && (question.Type == dnsmessage.TypeA || question.Type == dnsmessage.TypeAAAA) && IsDomainName(domain) { 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 return nil, os.ErrInvalid
} }

View file

@ -4,9 +4,9 @@ const (
TypeTun = "tun" TypeTun = "tun"
TypeRedirect = "redirect" TypeRedirect = "redirect"
TypeTProxy = "tproxy" TypeTProxy = "tproxy"
TypeDNS = "dns"
TypeDirect = "direct" TypeDirect = "direct"
TypeBlock = "block" TypeBlock = "block"
TypeDNS = "dns"
TypeSocks = "socks" TypeSocks = "socks"
TypeHTTP = "http" TypeHTTP = "http"
TypeMixed = "mixed" TypeMixed = "mixed"

View file

@ -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 return NewRedirect(ctx, router, logger, options.Tag, options.RedirectOptions), nil
case C.TypeTProxy: case C.TypeTProxy:
return NewTProxy(ctx, router, logger, options.Tag, options.TProxyOptions), nil 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: case C.TypeDirect:
return NewDirect(ctx, router, logger, options.Tag, options.DirectOptions), nil return NewDirect(ctx, router, logger, options.Tag, options.DirectOptions), nil
case C.TypeSocks: case C.TypeSocks:

View file

@ -21,7 +21,6 @@ import (
F "github.com/sagernet/sing/common/format" F "github.com/sagernet/sing/common/format"
M "github.com/sagernet/sing/common/metadata" M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network" N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/task"
) )
var _ adapter.Inbound = (*Tun)(nil) var _ adapter.Inbound = (*Tun)(nil)
@ -38,7 +37,6 @@ type Tun struct {
inet4Address netip.Prefix inet4Address netip.Prefix
inet6Address netip.Prefix inet6Address netip.Prefix
autoRoute bool autoRoute bool
hijackDNS bool
tunIf tun.Tun tunIf tun.Tun
tunStack *tun.GVisorTun tunStack *tun.GVisorTun
@ -64,7 +62,6 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger
inet4Address: options.Inet4Address.Build(), inet4Address: options.Inet4Address.Build(),
inet6Address: options.Inet6Address.Build(), inet6Address: options.Inet6Address.Build(),
autoRoute: options.AutoRoute, autoRoute: options.AutoRoute,
hijackDNS: options.HijackDNS,
}, nil }, nil
} }
@ -109,11 +106,6 @@ func (t *Tun) NewConnection(ctx context.Context, conn net.Conn, upstreamMetadata
metadata.SniffEnabled = t.inboundOptions.SniffEnabled metadata.SniffEnabled = t.inboundOptions.SniffEnabled
metadata.SniffOverrideDestination = t.inboundOptions.SniffOverrideDestination metadata.SniffOverrideDestination = t.inboundOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(t.inboundOptions.DomainStrategy) 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 from ", metadata.Source)
t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
err := t.router.RouteConnection(ctx, conn, metadata) 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.SniffEnabled = t.inboundOptions.SniffEnabled
metadata.SniffOverrideDestination = t.inboundOptions.SniffOverrideDestination metadata.SniffOverrideDestination = t.inboundOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(t.inboundOptions.DomainStrategy) 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 from ", metadata.Source)
t.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) t.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
err := t.router.RoutePacketConnection(ctx, conn, metadata) err := t.router.RoutePacketConnection(ctx, conn, metadata)

View file

@ -15,7 +15,6 @@ type _Inbound struct {
TunOptions TunInboundOptions `json:"-"` TunOptions TunInboundOptions `json:"-"`
RedirectOptions RedirectInboundOptions `json:"-"` RedirectOptions RedirectInboundOptions `json:"-"`
TProxyOptions TProxyInboundOptions `json:"-"` TProxyOptions TProxyInboundOptions `json:"-"`
DNSOptions DNSInboundOptions `json:"-"`
DirectOptions DirectInboundOptions `json:"-"` DirectOptions DirectInboundOptions `json:"-"`
SocksOptions SocksInboundOptions `json:"-"` SocksOptions SocksInboundOptions `json:"-"`
HTTPOptions HTTPMixedInboundOptions `json:"-"` HTTPOptions HTTPMixedInboundOptions `json:"-"`
@ -32,7 +31,6 @@ func (h Inbound) Equals(other Inbound) bool {
h.TunOptions == other.TunOptions && h.TunOptions == other.TunOptions &&
h.RedirectOptions == other.RedirectOptions && h.RedirectOptions == other.RedirectOptions &&
h.TProxyOptions == other.TProxyOptions && h.TProxyOptions == other.TProxyOptions &&
h.DNSOptions == other.DNSOptions &&
h.DirectOptions == other.DirectOptions && h.DirectOptions == other.DirectOptions &&
h.SocksOptions.Equals(other.SocksOptions) && h.SocksOptions.Equals(other.SocksOptions) &&
h.HTTPOptions.Equals(other.HTTPOptions) && h.HTTPOptions.Equals(other.HTTPOptions) &&
@ -50,8 +48,6 @@ func (h Inbound) MarshalJSON() ([]byte, error) {
v = h.RedirectOptions v = h.RedirectOptions
case C.TypeTProxy: case C.TypeTProxy:
v = h.TProxyOptions v = h.TProxyOptions
case C.TypeDNS:
v = h.DNSOptions
case C.TypeDirect: case C.TypeDirect:
v = h.DirectOptions v = h.DirectOptions
case C.TypeSocks: case C.TypeSocks:
@ -83,8 +79,6 @@ func (h *Inbound) UnmarshalJSON(bytes []byte) error {
v = &h.RedirectOptions v = &h.RedirectOptions
case C.TypeTProxy: case C.TypeTProxy:
v = &h.TProxyOptions v = &h.TProxyOptions
case C.TypeDNS:
v = &h.DNSOptions
case C.TypeDirect: case C.TypeDirect:
v = &h.DirectOptions v = &h.DirectOptions
case C.TypeSocks: case C.TypeSocks:
@ -200,7 +194,6 @@ type TunInboundOptions struct {
Inet4Address *ListenPrefix `json:"inet4_address,omitempty"` Inet4Address *ListenPrefix `json:"inet4_address,omitempty"`
Inet6Address *ListenPrefix `json:"inet6_address,omitempty"` Inet6Address *ListenPrefix `json:"inet6_address,omitempty"`
AutoRoute bool `json:"auto_route,omitempty"` AutoRoute bool `json:"auto_route,omitempty"`
HijackDNS bool `json:"hijack_dns,omitempty"`
InboundOptions InboundOptions
} }

View file

@ -40,7 +40,7 @@ func (h Outbound) MarshalJSON() ([]byte, error) {
switch h.Type { switch h.Type {
case C.TypeDirect: case C.TypeDirect:
v = h.DirectOptions v = h.DirectOptions
case C.TypeBlock: case C.TypeBlock, C.TypeDNS:
v = nil v = nil
case C.TypeSocks: case C.TypeSocks:
v = h.SocksOptions v = h.SocksOptions
@ -69,7 +69,7 @@ func (h *Outbound) UnmarshalJSON(bytes []byte) error {
switch h.Type { switch h.Type {
case C.TypeDirect: case C.TypeDirect:
v = &h.DirectOptions v = &h.DirectOptions
case C.TypeBlock: case C.TypeBlock, C.TypeDNS:
v = nil v = nil
case C.TypeSocks: case C.TypeSocks:
v = &h.SocksOptions v = &h.SocksOptions

View file

@ -22,9 +22,9 @@ func NewBlock(logger log.ContextLogger, tag string) *Block {
return &Block{ return &Block{
myOutboundAdapter{ myOutboundAdapter{
protocol: C.TypeBlock, protocol: C.TypeBlock,
network: []string{C.NetworkTCP, C.NetworkUDP},
logger: logger, logger: logger,
tag: tag, tag: tag,
network: []string{C.NetworkTCP, C.NetworkUDP},
}, },
} }
} }

View file

@ -18,6 +18,8 @@ func New(router adapter.Router, logger log.ContextLogger, options option.Outboun
return NewDirect(router, logger, options.Tag, options.DirectOptions), nil return NewDirect(router, logger, options.Tag, options.DirectOptions), nil
case C.TypeBlock: case C.TypeBlock:
return NewBlock(logger, options.Tag), nil return NewBlock(logger, options.Tag), nil
case C.TypeDNS:
return NewDNS(router, logger, options.Tag), nil
case C.TypeSocks: case C.TypeSocks:
return NewSocks(router, logger, options.Tag, options.SocksOptions) return NewSocks(router, logger, options.Tag, options.SocksOptions)
case C.TypeHTTP: case C.TypeHTTP:

View file

@ -18,9 +18,10 @@ import (
type myOutboundAdapter struct { type myOutboundAdapter struct {
protocol string protocol string
network []string
router adapter.Router
logger log.ContextLogger logger log.ContextLogger
tag string tag string
network []string
} }
func (a *myOutboundAdapter) Type() string { func (a *myOutboundAdapter) Type() string {

View file

@ -27,9 +27,10 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
outbound := &Direct{ outbound := &Direct{
myOutboundAdapter: myOutboundAdapter{ myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeDirect, protocol: C.TypeDirect,
network: []string{C.NetworkTCP, C.NetworkUDP},
router: router,
logger: logger, logger: logger,
tag: tag, tag: tag,
network: []string{C.NetworkTCP, C.NetworkUDP},
}, },
dialer: dialer.NewOutbound(router, options.OutboundDialerOptions), dialer: dialer.NewOutbound(router, options.OutboundDialerOptions),
} }

View file

@ -1,67 +1,50 @@
package inbound package outbound
import ( import (
"context" "context"
"encoding/binary" "encoding/binary"
"io" "io"
"net" "net"
"net/netip" "os"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant" C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/buf"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network" N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/udpnat"
"golang.org/x/net/dns/dnsmessage" "golang.org/x/net/dns/dnsmessage"
) )
var _ adapter.Outbound = (*DNS)(nil)
type DNS struct { type DNS struct {
myInboundAdapter myOutboundAdapter
udpNat *udpnat.Service[netip.AddrPort]
} }
func NewDNS(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.DNSInboundOptions) *DNS { func NewDNS(router adapter.Router, logger log.ContextLogger, tag string) *DNS {
dns := &DNS{ return &DNS{
myInboundAdapter: myInboundAdapter{ myOutboundAdapter{
protocol: C.TypeTProxy, protocol: C.TypeDNS,
network: options.Network.Build(), network: []string{C.NetworkTCP, C.NetworkUDP},
ctx: ctx, router: router,
router: router, logger: logger,
logger: logger, tag: tag,
tag: tag,
listenOptions: options.ListenOptions,
}, },
} }
dns.connHandler = dns }
dns.packetHandler = dns
dns.udpNat = udpnat.New[netip.AddrPort](10, adapter.NewUpstreamContextHandler(nil, dns.newPacketConnection, dns)) func (d *DNS) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
dns.packetUpstream = dns.udpNat return nil, os.ErrInvalid
return dns }
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 { 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) ctx = adapter.WithContext(ctx, &metadata)
_buffer := buf.StackNewSize(1024) _buffer := buf.StackNewSize(1024)
defer common.KeepAlive(_buffer) defer common.KeepAlive(_buffer)
@ -89,10 +72,10 @@ func NewDNSConnection(ctx context.Context, router adapter.Router, logger log.Con
if len(message.Questions) > 0 { if len(message.Questions) > 0 {
question := message.Questions[0] question := message.Questions[0]
metadata.Domain = string(question.Name.Data[:question.Name.Length-1]) 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 { go func() error {
response, err := router.Exchange(ctx, &message) response, err := d.router.Exchange(ctx, &message)
if err != nil { if err != nil {
return err 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) ctx = adapter.WithContext(ctx, &metadata)
_buffer := buf.StackNewSize(1024) _buffer := buf.StackNewSize(1024)
defer common.KeepAlive(_buffer) defer common.KeepAlive(_buffer)
@ -133,10 +116,10 @@ func NewDNSPacketConnection(ctx context.Context, router adapter.Router, logger l
if len(message.Questions) > 0 { if len(message.Questions) > 0 {
question := message.Questions[0] question := message.Questions[0]
metadata.Domain = string(question.Name.Data[:question.Name.Length-1]) 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 { go func() error {
response, err := router.Exchange(ctx, &message) response, err := d.router.Exchange(ctx, &message)
if err != nil { if err != nil {
return err return err
} }

View file

@ -31,9 +31,10 @@ func NewHTTP(router adapter.Router, logger log.ContextLogger, tag string, option
return &HTTP{ return &HTTP{
myOutboundAdapter{ myOutboundAdapter{
protocol: C.TypeHTTP, protocol: C.TypeHTTP,
network: []string{C.NetworkTCP},
router: router,
logger: logger, logger: logger,
tag: tag, tag: tag,
network: []string{C.NetworkTCP},
}, },
http.NewClient(detour, options.ServerOptions.Build(), options.Username, options.Password), http.NewClient(detour, options.ServerOptions.Build(), options.Username, options.Password),
}, nil }, nil

View file

@ -20,7 +20,6 @@ var (
type Selector struct { type Selector struct {
myOutboundAdapter myOutboundAdapter
router adapter.Router
tags []string tags []string
defaultTag string defaultTag string
outbounds map[string]adapter.Outbound outbounds map[string]adapter.Outbound
@ -31,10 +30,10 @@ func NewSelector(router adapter.Router, logger log.ContextLogger, tag string, op
outbound := &Selector{ outbound := &Selector{
myOutboundAdapter: myOutboundAdapter{ myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeSelector, protocol: C.TypeSelector,
router: router,
logger: logger, logger: logger,
tag: tag, tag: tag,
}, },
router: router,
tags: options.Outbounds, tags: options.Outbounds,
defaultTag: options.Default, defaultTag: options.Default,
outbounds: make(map[string]adapter.Outbound), outbounds: make(map[string]adapter.Outbound),

View file

@ -33,9 +33,10 @@ func NewShadowsocks(router adapter.Router, logger log.ContextLogger, tag string,
return &Shadowsocks{ return &Shadowsocks{
myOutboundAdapter{ myOutboundAdapter{
protocol: C.TypeShadowsocks, protocol: C.TypeShadowsocks,
network: options.Network.Build(),
router: router,
logger: logger, logger: logger,
tag: tag, tag: tag,
network: options.Network.Build(),
}, },
dialer.NewOutbound(router, options.OutboundDialerOptions), dialer.NewOutbound(router, options.OutboundDialerOptions),
method, method,

View file

@ -36,9 +36,10 @@ func NewSocks(router adapter.Router, logger log.ContextLogger, tag string, optio
return &Socks{ return &Socks{
myOutboundAdapter{ myOutboundAdapter{
protocol: C.TypeSocks, protocol: C.TypeSocks,
network: options.Network.Build(),
router: router,
logger: logger, logger: logger,
tag: tag, tag: tag,
network: options.Network.Build(),
}, },
socks.NewClient(detour, options.ServerOptions.Build(), version, options.Username, options.Password), socks.NewClient(detour, options.ServerOptions.Build(), version, options.Username, options.Password),
}, nil }, nil

View file

@ -24,7 +24,6 @@ var (
type URLTest struct { type URLTest struct {
myOutboundAdapter myOutboundAdapter
router adapter.Router
tags []string tags []string
link string link string
interval time.Duration interval time.Duration
@ -36,10 +35,10 @@ func NewURLTest(router adapter.Router, logger log.ContextLogger, tag string, opt
outbound := &URLTest{ outbound := &URLTest{
myOutboundAdapter: myOutboundAdapter{ myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeURLTest, protocol: C.TypeURLTest,
router: router,
logger: logger, logger: logger,
tag: tag, tag: tag,
}, },
router: router,
tags: options.Outbounds, tags: options.Outbounds,
link: options.URL, link: options.URL,
interval: time.Duration(options.Interval), interval: time.Duration(options.Interval),

View file

@ -43,9 +43,10 @@ func NewVMess(router adapter.Router, logger log.ContextLogger, tag string, optio
return &VMess{ return &VMess{
myOutboundAdapter{ myOutboundAdapter{
protocol: C.TypeVMess, protocol: C.TypeVMess,
network: options.Network.Build(),
router: router,
logger: logger, logger: logger,
tag: tag, tag: tag,
network: options.Network.Build(),
}, },
detour, detour,
client, client,

View file

@ -439,7 +439,7 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
defer common.KeepAlive(_buffer) defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer) buffer := common.Dup(_buffer)
defer buffer.Release() 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 { if err == nil {
metadata.Protocol = sniffMetadata.Protocol metadata.Protocol = sniffMetadata.Protocol
metadata.Domain = sniffMetadata.Domain metadata.Domain = sniffMetadata.Domain
@ -485,7 +485,7 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
if err != nil { if err != nil {
return err 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 originDestination := metadata.Destination
if err == nil { if err == nil {
metadata.Protocol = sniffMetadata.Protocol metadata.Protocol = sniffMetadata.Protocol