mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 00:21:30 +00:00
Add resolver for inbound
This commit is contained in:
parent
538a1f5909
commit
9c256afc1a
|
@ -2,8 +2,11 @@ package adapter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Inbound interface {
|
type Inbound interface {
|
||||||
|
@ -23,8 +26,10 @@ type InboundContext struct {
|
||||||
|
|
||||||
// cache
|
// cache
|
||||||
|
|
||||||
|
DomainStrategy C.DomainStrategy
|
||||||
SniffEnabled bool
|
SniffEnabled bool
|
||||||
SniffOverrideDestination bool
|
SniffOverrideDestination bool
|
||||||
|
DestinationAddresses []netip.Addr
|
||||||
|
|
||||||
SourceGeoIPCode string
|
SourceGeoIPCode string
|
||||||
GeoIPCode string
|
GeoIPCode string
|
||||||
|
@ -50,5 +55,5 @@ func AppendContext(ctx context.Context) (context.Context, *InboundContext) {
|
||||||
return ctx, metadata
|
return ctx, metadata
|
||||||
}
|
}
|
||||||
metadata = new(InboundContext)
|
metadata = new(InboundContext)
|
||||||
return WithContext(ctx, metadata), nil
|
return WithContext(ctx, metadata), metadata
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,6 +12,6 @@ type Outbound interface {
|
||||||
Tag() string
|
Tag() string
|
||||||
Network() []string
|
Network() []string
|
||||||
N.Dialer
|
N.Dialer
|
||||||
NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error
|
NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
|
||||||
NewPacketConnection(ctx context.Context, conn N.PacketConn, destination M.Socksaddr) error
|
NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(router adapter.Router, options option.DialerOptions) N.Dialer {
|
func New(router adapter.Router, options option.DialerOptions) N.Dialer {
|
||||||
domainStrategy := C.DomainStrategy(options.DomainStrategy)
|
|
||||||
var dialer N.Dialer
|
|
||||||
if options.Detour == "" {
|
if options.Detour == "" {
|
||||||
dialer = NewDefault(options)
|
return NewDefault(options)
|
||||||
dialer = NewResolveDialer(router, dialer, domainStrategy)
|
|
||||||
} else {
|
} else {
|
||||||
dialer = NewDetour(router, options.Detour)
|
return NewDetour(router, options.Detour)
|
||||||
if domainStrategy != C.DomainStrategyAsIS {
|
|
||||||
dialer = NewResolveDialer(router, dialer, domainStrategy)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOutbound(router adapter.Router, options option.OutboundDialerOptions) N.Dialer {
|
||||||
|
dialer := New(router, options.DialerOptions)
|
||||||
|
domainStrategy := C.DomainStrategy(options.DomainStrategy)
|
||||||
|
if domainStrategy != C.DomainStrategyAsIS || options.Detour == "" && !C.CGO_ENABLED {
|
||||||
|
dialer = NewResolveDialer(router, dialer, domainStrategy)
|
||||||
}
|
}
|
||||||
if options.OverrideOptions.IsValid() {
|
if options.OverrideOptions.IsValid() {
|
||||||
dialer = NewOverride(dialer, common.PtrValueOrDefault(options.OverrideOptions))
|
dialer = NewOverride(dialer, common.PtrValueOrDefault(options.OverrideOptions))
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
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"
|
||||||
|
|
||||||
|
@ -41,16 +40,7 @@ func (d *ResolveDialer) DialContext(ctx context.Context, network string, destina
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var conn net.Conn
|
return DialSerial(ctx, d.dialer, network, destination, addresses)
|
||||||
var connErrors []error
|
|
||||||
for _, address := range addresses {
|
|
||||||
conn, err = d.dialer.DialContext(ctx, network, M.SocksaddrFromAddrPort(address, destination.Port))
|
|
||||||
if err != nil {
|
|
||||||
connErrors = append(connErrors, err)
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
return nil, E.Errors(connErrors...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ResolveDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (d *ResolveDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
@ -67,16 +57,7 @@ func (d *ResolveDialer) ListenPacket(ctx context.Context, destination M.Socksadd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var conn net.PacketConn
|
return ListenSerial(ctx, d.dialer, destination, addresses)
|
||||||
var connErrors []error
|
|
||||||
for _, address := range addresses {
|
|
||||||
conn, err = d.dialer.ListenPacket(ctx, M.SocksaddrFromAddrPort(address, destination.Port))
|
|
||||||
if err != nil {
|
|
||||||
connErrors = append(connErrors, err)
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
return nil, E.Errors(connErrors...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ResolveDialer) Upstream() any {
|
func (d *ResolveDialer) Upstream() any {
|
||||||
|
|
39
common/dialer/serial.go
Normal file
39
common/dialer/serial.go
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package dialer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DialSerial(ctx context.Context, dialer N.Dialer, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) {
|
||||||
|
var conn net.Conn
|
||||||
|
var err error
|
||||||
|
var connErrors []error
|
||||||
|
for _, address := range destinationAddresses {
|
||||||
|
conn, err = dialer.DialContext(ctx, network, M.SocksaddrFromAddrPort(address, destination.Port))
|
||||||
|
if err != nil {
|
||||||
|
connErrors = append(connErrors, err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
return nil, E.Errors(connErrors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListenSerial(ctx context.Context, dialer N.Dialer, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.PacketConn, error) {
|
||||||
|
var conn net.PacketConn
|
||||||
|
var err error
|
||||||
|
var connErrors []error
|
||||||
|
for _, address := range destinationAddresses {
|
||||||
|
conn, err = dialer.ListenPacket(ctx, M.SocksaddrFromAddrPort(address, destination.Port))
|
||||||
|
if err != nil {
|
||||||
|
connErrors = append(connErrors, err)
|
||||||
|
}
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
return nil, E.Errors(connErrors...)
|
||||||
|
}
|
|
@ -77,9 +77,14 @@ func (r *Reader) readMetadata() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) Read(code string) ([]Item, error) {
|
func (r *Reader) Read(code string) ([]Item, error) {
|
||||||
if _, exists := r.domainIndex[code]; !exists {
|
index, exists := r.domainIndex[code]
|
||||||
|
if !exists {
|
||||||
return nil, E.New("code ", code, " not exists!")
|
return nil, E.New("code ", code, " not exists!")
|
||||||
}
|
}
|
||||||
|
_, err := r.reader.Seek(int64(index), io.SeekCurrent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
counter := &rw.ReadCounter{Reader: r.reader}
|
counter := &rw.ReadCounter{Reader: r.reader}
|
||||||
domain := make([]Item, r.domainLength[code])
|
domain := make([]Item, r.domainLength[code])
|
||||||
for i := range domain {
|
for i := range domain {
|
||||||
|
@ -97,7 +102,7 @@ func (r *Reader) Read(code string) ([]Item, error) {
|
||||||
}
|
}
|
||||||
domain[i] = item
|
domain[i] = item
|
||||||
}
|
}
|
||||||
_, err := r.reader.Seek(int64(r.domainIndex[code])-counter.Count(), io.SeekCurrent)
|
_, err = r.reader.Seek(int64(-index)-counter.Count(), io.SeekCurrent)
|
||||||
return domain, err
|
return domain, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
constant/cgo.go
Normal file
3
constant/cgo.go
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
package constant
|
||||||
|
|
||||||
|
const CGO_ENABLED = true
|
5
constant/cgo_disabled.go
Normal file
5
constant/cgo_disabled.go
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
//go:build !cgo
|
||||||
|
|
||||||
|
package constant
|
||||||
|
|
||||||
|
const CGO_ENABLED = false
|
|
@ -4,11 +4,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
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-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/dialer"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,16 +31,7 @@ func (d *DialerWrapper) DialContext(ctx context.Context, network string, destina
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var conn net.Conn
|
return dialer.DialSerial(ctx, d.dialer, network, destination, addresses)
|
||||||
var connErrors []error
|
|
||||||
for _, address := range addresses {
|
|
||||||
conn, err = d.dialer.DialContext(ctx, network, M.SocksaddrFromAddrPort(address, destination.Port))
|
|
||||||
if err != nil {
|
|
||||||
connErrors = append(connErrors, err)
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
return nil, E.Errors(connErrors...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DialerWrapper) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (d *DialerWrapper) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
@ -51,16 +42,7 @@ func (d *DialerWrapper) ListenPacket(ctx context.Context, destination M.Socksadd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var conn net.PacketConn
|
return dialer.ListenSerial(ctx, d.dialer, destination, addresses)
|
||||||
var connErrors []error
|
|
||||||
for _, address := range addresses {
|
|
||||||
conn, err = d.dialer.ListenPacket(ctx, M.SocksaddrFromAddrPort(address, destination.Port))
|
|
||||||
if err != nil {
|
|
||||||
connErrors = append(connErrors, err)
|
|
||||||
}
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
return nil, E.Errors(connErrors...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DialerWrapper) Upstream() any {
|
func (d *DialerWrapper) Upstream() any {
|
||||||
|
|
|
@ -136,6 +136,7 @@ func (a *myInboundAdapter) loopTCPIn() {
|
||||||
metadata.Inbound = a.tag
|
metadata.Inbound = a.tag
|
||||||
metadata.SniffEnabled = a.listenOptions.SniffEnabled
|
metadata.SniffEnabled = a.listenOptions.SniffEnabled
|
||||||
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
|
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
|
||||||
|
metadata.DomainStrategy = C.DomainStrategy(a.listenOptions.DomainStrategy)
|
||||||
metadata.Network = C.NetworkTCP
|
metadata.Network = C.NetworkTCP
|
||||||
metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr())
|
metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr())
|
||||||
a.logger.WithContext(ctx).Info("inbound connection from ", metadata.Source)
|
a.logger.WithContext(ctx).Info("inbound connection from ", metadata.Source)
|
||||||
|
@ -167,6 +168,7 @@ func (a *myInboundAdapter) loopUDPIn() {
|
||||||
metadata.Inbound = a.tag
|
metadata.Inbound = a.tag
|
||||||
metadata.SniffEnabled = a.listenOptions.SniffEnabled
|
metadata.SniffEnabled = a.listenOptions.SniffEnabled
|
||||||
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
|
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
|
||||||
|
metadata.DomainStrategy = C.DomainStrategy(a.listenOptions.DomainStrategy)
|
||||||
metadata.Network = C.NetworkUDP
|
metadata.Network = C.NetworkUDP
|
||||||
metadata.Source = M.SocksaddrFromNetIP(addr)
|
metadata.Source = M.SocksaddrFromNetIP(addr)
|
||||||
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
|
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
|
||||||
|
@ -191,6 +193,7 @@ func (a *myInboundAdapter) loopUDPInThreadSafe() {
|
||||||
metadata.Inbound = a.tag
|
metadata.Inbound = a.tag
|
||||||
metadata.SniffEnabled = a.listenOptions.SniffEnabled
|
metadata.SniffEnabled = a.listenOptions.SniffEnabled
|
||||||
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
|
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
|
||||||
|
metadata.DomainStrategy = C.DomainStrategy(a.listenOptions.DomainStrategy)
|
||||||
metadata.Network = C.NetworkUDP
|
metadata.Network = C.NetworkUDP
|
||||||
metadata.Source = M.SocksaddrFromNetIP(addr)
|
metadata.Source = M.SocksaddrFromNetIP(addr)
|
||||||
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
|
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
|
||||||
|
|
|
@ -85,6 +85,7 @@ type ListenOptions struct {
|
||||||
UDPTimeout int64 `json:"udp_timeout,omitempty"`
|
UDPTimeout int64 `json:"udp_timeout,omitempty"`
|
||||||
SniffEnabled bool `json:"sniff,omitempty"`
|
SniffEnabled bool `json:"sniff,omitempty"`
|
||||||
SniffOverrideDestination bool `json:"sniff_override_destination,omitempty"`
|
SniffOverrideDestination bool `json:"sniff_override_destination,omitempty"`
|
||||||
|
DomainStrategy DomainStrategy `json:"domain_strategy,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SimpleInboundOptions struct {
|
type SimpleInboundOptions struct {
|
||||||
|
|
|
@ -74,6 +74,10 @@ type DialerOptions struct {
|
||||||
ReuseAddr bool `json:"reuse_addr,omitempty"`
|
ReuseAddr bool `json:"reuse_addr,omitempty"`
|
||||||
ConnectTimeout int `json:"connect_timeout,omitempty"`
|
ConnectTimeout int `json:"connect_timeout,omitempty"`
|
||||||
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OutboundDialerOptions struct {
|
||||||
|
DialerOptions
|
||||||
OverrideOptions *OverrideStreamOptions `json:"override,omitempty"`
|
OverrideOptions *OverrideStreamOptions `json:"override,omitempty"`
|
||||||
DomainStrategy DomainStrategy `json:"domain_strategy,omitempty"`
|
DomainStrategy DomainStrategy `json:"domain_strategy,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -99,13 +103,13 @@ func (o ServerOptions) Build() M.Socksaddr {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DirectOutboundOptions struct {
|
type DirectOutboundOptions struct {
|
||||||
DialerOptions
|
OutboundDialerOptions
|
||||||
OverrideAddress string `json:"override_address,omitempty"`
|
OverrideAddress string `json:"override_address,omitempty"`
|
||||||
OverridePort uint16 `json:"override_port,omitempty"`
|
OverridePort uint16 `json:"override_port,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SocksOutboundOptions struct {
|
type SocksOutboundOptions struct {
|
||||||
DialerOptions
|
OutboundDialerOptions
|
||||||
ServerOptions
|
ServerOptions
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
|
@ -114,14 +118,14 @@ type SocksOutboundOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPOutboundOptions struct {
|
type HTTPOutboundOptions struct {
|
||||||
DialerOptions
|
OutboundDialerOptions
|
||||||
ServerOptions
|
ServerOptions
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShadowsocksOutboundOptions struct {
|
type ShadowsocksOutboundOptions struct {
|
||||||
DialerOptions
|
OutboundDialerOptions
|
||||||
ServerOptions
|
ServerOptions
|
||||||
Method string `json:"method"`
|
Method string `json:"method"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
|
|
|
@ -100,13 +100,13 @@ func (s DomainStrategy) MarshalJSON() ([]byte, error) {
|
||||||
value = ""
|
value = ""
|
||||||
// value = "AsIS"
|
// value = "AsIS"
|
||||||
case C.DomainStrategyPreferIPv4:
|
case C.DomainStrategyPreferIPv4:
|
||||||
value = "PreferIPv4"
|
value = "prefer_ipv4"
|
||||||
case C.DomainStrategyPreferIPv6:
|
case C.DomainStrategyPreferIPv6:
|
||||||
value = "PreferIPv6"
|
value = "prefer_ipv6"
|
||||||
case C.DomainStrategyUseIPv4:
|
case C.DomainStrategyUseIPv4:
|
||||||
value = "UseIPv4"
|
value = "ipv4_only"
|
||||||
case C.DomainStrategyUseIPv6:
|
case C.DomainStrategyUseIPv6:
|
||||||
value = "UseIPv6"
|
value = "ipv6_only"
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown domain strategy: ", s)
|
return nil, E.New("unknown domain strategy: ", s)
|
||||||
}
|
}
|
||||||
|
@ -122,13 +122,13 @@ func (s *DomainStrategy) UnmarshalJSON(bytes []byte) error {
|
||||||
switch value {
|
switch value {
|
||||||
case "", "AsIS":
|
case "", "AsIS":
|
||||||
*s = DomainStrategy(C.DomainStrategyAsIS)
|
*s = DomainStrategy(C.DomainStrategyAsIS)
|
||||||
case "PreferIPv4":
|
case "prefer_ipv4":
|
||||||
*s = DomainStrategy(C.DomainStrategyPreferIPv4)
|
*s = DomainStrategy(C.DomainStrategyPreferIPv4)
|
||||||
case "PreferIPv6":
|
case "prefer_ipv6":
|
||||||
*s = DomainStrategy(C.DomainStrategyPreferIPv6)
|
*s = DomainStrategy(C.DomainStrategyPreferIPv6)
|
||||||
case "UseIPv4":
|
case "ipv4_only":
|
||||||
*s = DomainStrategy(C.DomainStrategyUseIPv4)
|
*s = DomainStrategy(C.DomainStrategyUseIPv4)
|
||||||
case "UseIPv6":
|
case "ipv6_only":
|
||||||
*s = DomainStrategy(C.DomainStrategyUseIPv6)
|
*s = DomainStrategy(C.DomainStrategyUseIPv6)
|
||||||
default:
|
default:
|
||||||
return E.New("unknown domain strategy: ", value)
|
return E.New("unknown domain strategy: ", value)
|
||||||
|
|
|
@ -40,14 +40,14 @@ func (h *Block) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.
|
||||||
return nil, io.EOF
|
return nil, io.EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Block) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
func (h *Block) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
h.logger.WithContext(ctx).Info("blocked connection to ", destination)
|
h.logger.WithContext(ctx).Info("blocked connection to ", metadata.Destination)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Block) NewPacketConnection(ctx context.Context, conn N.PacketConn, destination M.Socksaddr) error {
|
func (h *Block) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
h.logger.WithContext(ctx).Info("blocked packet connection to ", destination)
|
h.logger.WithContext(ctx).Info("blocked packet connection to ", metadata.Destination)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,11 @@ import (
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/dialer"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,6 +37,51 @@ func (a *myOutboundAdapter) Network() []string {
|
||||||
return a.network
|
return a.network
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewConnection(ctx context.Context, this N.Dialer, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
|
ctx = adapter.WithContext(ctx, &metadata)
|
||||||
|
var outConn net.Conn
|
||||||
|
var err error
|
||||||
|
if len(metadata.DestinationAddresses) > 0 {
|
||||||
|
outConn, err = dialer.DialSerial(ctx, this, C.NetworkTCP, metadata.Destination, metadata.DestinationAddresses)
|
||||||
|
} else {
|
||||||
|
outConn, err = this.DialContext(ctx, C.NetworkTCP, metadata.Destination)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return bufio.CopyConn(ctx, conn, outConn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEarlyConnection(ctx context.Context, this N.Dialer, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
|
ctx = adapter.WithContext(ctx, &metadata)
|
||||||
|
var outConn net.Conn
|
||||||
|
var err error
|
||||||
|
if len(metadata.DestinationAddresses) > 0 {
|
||||||
|
outConn, err = dialer.DialSerial(ctx, this, C.NetworkTCP, metadata.Destination, metadata.DestinationAddresses)
|
||||||
|
} else {
|
||||||
|
outConn, err = this.DialContext(ctx, C.NetworkTCP, metadata.Destination)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return CopyEarlyConn(ctx, conn, outConn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
|
ctx = adapter.WithContext(ctx, &metadata)
|
||||||
|
var outConn net.PacketConn
|
||||||
|
var err error
|
||||||
|
if len(metadata.DestinationAddresses) > 0 {
|
||||||
|
outConn, err = dialer.ListenSerial(ctx, this, metadata.Destination, metadata.DestinationAddresses)
|
||||||
|
} else {
|
||||||
|
outConn, err = this.ListenPacket(ctx, metadata.Destination)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(outConn))
|
||||||
|
}
|
||||||
|
|
||||||
func CopyEarlyConn(ctx context.Context, conn net.Conn, serverConn net.Conn) error {
|
func CopyEarlyConn(ctx context.Context, conn net.Conn, serverConn net.Conn) error {
|
||||||
_payload := buf.StackNew()
|
_payload := buf.StackNew()
|
||||||
payload := common.Dup(_payload)
|
payload := common.Dup(_payload)
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common/bufio"
|
|
||||||
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"
|
||||||
|
|
||||||
|
@ -32,7 +31,7 @@ func NewDirect(router adapter.Router, logger log.Logger, tag string, options opt
|
||||||
tag: tag,
|
tag: tag,
|
||||||
network: []string{C.NetworkTCP, C.NetworkUDP},
|
network: []string{C.NetworkTCP, C.NetworkUDP},
|
||||||
},
|
},
|
||||||
dialer: dialer.New(router, options.DialerOptions),
|
dialer: dialer.NewOutbound(router, options.OutboundDialerOptions),
|
||||||
}
|
}
|
||||||
if options.OverrideAddress != "" && options.OverridePort != 0 {
|
if options.OverrideAddress != "" && options.OverridePort != 0 {
|
||||||
outbound.overrideOption = 1
|
outbound.overrideOption = 1
|
||||||
|
@ -50,6 +49,7 @@ func NewDirect(router adapter.Router, logger log.Logger, tag string, options opt
|
||||||
func (h *Direct) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (h *Direct) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
ctx, metadata := adapter.AppendContext(ctx)
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
metadata.Outbound = h.tag
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
switch h.overrideOption {
|
switch h.overrideOption {
|
||||||
case 1:
|
case 1:
|
||||||
destination = h.overrideDestination
|
destination = h.overrideDestination
|
||||||
|
@ -72,22 +72,15 @@ func (h *Direct) DialContext(ctx context.Context, network string, destination M.
|
||||||
func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
ctx, metadata := adapter.AppendContext(ctx)
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
metadata.Outbound = h.tag
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
h.logger.WithContext(ctx).Info("outbound packet connection")
|
h.logger.WithContext(ctx).Info("outbound packet connection")
|
||||||
return h.dialer.ListenPacket(ctx, destination)
|
return h.dialer.ListenPacket(ctx, destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
func (h *Direct) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
outConn, err := h.DialContext(ctx, C.NetworkTCP, destination)
|
return NewConnection(ctx, h, conn, metadata)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return bufio.CopyConn(ctx, conn, outConn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, destination M.Socksaddr) error {
|
func (h *Direct) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
outConn, err := h.ListenPacket(ctx, destination)
|
return NewPacketConnection(ctx, h, conn, metadata)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(outConn))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common/bufio"
|
|
||||||
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/protocol/http"
|
"github.com/sagernet/sing/protocol/http"
|
||||||
|
@ -32,13 +31,14 @@ func NewHTTP(router adapter.Router, logger log.Logger, tag string, options optio
|
||||||
tag: tag,
|
tag: tag,
|
||||||
network: []string{C.NetworkTCP},
|
network: []string{C.NetworkTCP},
|
||||||
},
|
},
|
||||||
http.NewClient(dialer.New(router, options.DialerOptions), options.ServerOptions.Build(), options.Username, options.Password),
|
http.NewClient(dialer.NewOutbound(router, options.OutboundDialerOptions), options.ServerOptions.Build(), options.Username, options.Password),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTP) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (h *HTTP) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
ctx, metadata := adapter.AppendContext(ctx)
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
metadata.Outbound = h.tag
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
h.logger.WithContext(ctx).Info("outbound connection to ", destination)
|
h.logger.WithContext(ctx).Info("outbound connection to ", destination)
|
||||||
return h.client.DialContext(ctx, network, destination)
|
return h.client.DialContext(ctx, network, destination)
|
||||||
}
|
}
|
||||||
|
@ -46,17 +46,14 @@ func (h *HTTP) DialContext(ctx context.Context, network string, destination M.So
|
||||||
func (h *HTTP) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (h *HTTP) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
ctx, metadata := adapter.AppendContext(ctx)
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
metadata.Outbound = h.tag
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
return nil, os.ErrInvalid
|
return nil, os.ErrInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTP) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
func (h *HTTP) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
outConn, err := h.DialContext(ctx, C.NetworkTCP, destination)
|
return NewConnection(ctx, h, conn, metadata)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return bufio.CopyConn(ctx, conn, outConn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTP) NewPacketConnection(ctx context.Context, conn N.PacketConn, destination M.Socksaddr) error {
|
func (h *HTTP) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
return os.ErrInvalid
|
return os.ErrInvalid
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ func NewShadowsocks(router adapter.Router, logger log.Logger, tag string, option
|
||||||
tag: tag,
|
tag: tag,
|
||||||
network: options.Network.Build(),
|
network: options.Network.Build(),
|
||||||
},
|
},
|
||||||
dialer.New(router, options.DialerOptions),
|
dialer.NewOutbound(router, options.OutboundDialerOptions),
|
||||||
method,
|
method,
|
||||||
options.ServerOptions.Build(),
|
options.ServerOptions.Build(),
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -48,6 +48,7 @@ func NewShadowsocks(router adapter.Router, logger log.Logger, tag string, option
|
||||||
func (h *Shadowsocks) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (h *Shadowsocks) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
ctx, metadata := adapter.AppendContext(ctx)
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
metadata.Outbound = h.tag
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
switch network {
|
switch network {
|
||||||
case C.NetworkTCP:
|
case C.NetworkTCP:
|
||||||
h.logger.WithContext(ctx).Info("outbound connection to ", destination)
|
h.logger.WithContext(ctx).Info("outbound connection to ", destination)
|
||||||
|
@ -71,6 +72,7 @@ func (h *Shadowsocks) DialContext(ctx context.Context, network string, destinati
|
||||||
func (h *Shadowsocks) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (h *Shadowsocks) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
ctx, metadata := adapter.AppendContext(ctx)
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
metadata.Outbound = h.tag
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
h.logger.WithContext(ctx).Info("outbound packet connection to ", h.serverAddr)
|
h.logger.WithContext(ctx).Info("outbound packet connection to ", h.serverAddr)
|
||||||
outConn, err := h.dialer.ListenPacket(ctx, destination)
|
outConn, err := h.dialer.ListenPacket(ctx, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -79,18 +81,10 @@ func (h *Shadowsocks) ListenPacket(ctx context.Context, destination M.Socksaddr)
|
||||||
return h.method.DialPacketConn(&bufio.BindPacketConn{PacketConn: outConn, Addr: h.serverAddr.UDPAddr()}), nil
|
return h.method.DialPacketConn(&bufio.BindPacketConn{PacketConn: outConn, Addr: h.serverAddr.UDPAddr()}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Shadowsocks) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
func (h *Shadowsocks) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
serverConn, err := h.DialContext(ctx, C.NetworkTCP, destination)
|
return NewEarlyConnection(ctx, h, conn, metadata)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return CopyEarlyConn(ctx, conn, serverConn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Shadowsocks) NewPacketConnection(ctx context.Context, conn N.PacketConn, destination M.Socksaddr) error {
|
func (h *Shadowsocks) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
serverConn, err := h.ListenPacket(ctx, destination)
|
return NewPacketConnection(ctx, h, conn, metadata)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(serverConn))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common/bufio"
|
|
||||||
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/protocol/socks"
|
"github.com/sagernet/sing/protocol/socks"
|
||||||
|
@ -24,7 +23,7 @@ type Socks struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSocks(router adapter.Router, logger log.Logger, tag string, options option.SocksOutboundOptions) (*Socks, error) {
|
func NewSocks(router adapter.Router, logger log.Logger, tag string, options option.SocksOutboundOptions) (*Socks, error) {
|
||||||
detour := dialer.New(router, options.DialerOptions)
|
detour := dialer.NewOutbound(router, options.OutboundDialerOptions)
|
||||||
var version socks.Version
|
var version socks.Version
|
||||||
var err error
|
var err error
|
||||||
if options.Version != "" {
|
if options.Version != "" {
|
||||||
|
@ -49,6 +48,7 @@ func NewSocks(router adapter.Router, logger log.Logger, tag string, options opti
|
||||||
func (h *Socks) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (h *Socks) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
ctx, metadata := adapter.AppendContext(ctx)
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
metadata.Outbound = h.tag
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
switch network {
|
switch network {
|
||||||
case C.NetworkTCP:
|
case C.NetworkTCP:
|
||||||
h.logger.WithContext(ctx).Info("outbound connection to ", destination)
|
h.logger.WithContext(ctx).Info("outbound connection to ", destination)
|
||||||
|
@ -63,22 +63,15 @@ func (h *Socks) DialContext(ctx context.Context, network string, destination M.S
|
||||||
func (h *Socks) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (h *Socks) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
ctx, metadata := adapter.AppendContext(ctx)
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
metadata.Outbound = h.tag
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
h.logger.WithContext(ctx).Info("outbound packet connection to ", destination)
|
h.logger.WithContext(ctx).Info("outbound packet connection to ", destination)
|
||||||
return h.client.ListenPacket(ctx, destination)
|
return h.client.ListenPacket(ctx, destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Socks) NewConnection(ctx context.Context, conn net.Conn, destination M.Socksaddr) error {
|
func (h *Socks) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
outConn, err := h.DialContext(ctx, C.NetworkTCP, destination)
|
return NewConnection(ctx, h, conn, metadata)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return bufio.CopyConn(ctx, conn, outConn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Socks) NewPacketConnection(ctx context.Context, conn N.PacketConn, destination M.Socksaddr) error {
|
func (h *Socks) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
outConn, err := h.ListenPacket(ctx, destination)
|
return NewPacketConnection(ctx, h, conn, metadata)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(outConn))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ type Router struct {
|
||||||
|
|
||||||
dnsClient adapter.DNSClient
|
dnsClient adapter.DNSClient
|
||||||
defaultDomainStrategy C.DomainStrategy
|
defaultDomainStrategy C.DomainStrategy
|
||||||
|
dnsRules []adapter.Rule
|
||||||
|
|
||||||
defaultTransport adapter.DNSTransport
|
defaultTransport adapter.DNSTransport
|
||||||
transports []adapter.DNSTransport
|
transports []adapter.DNSTransport
|
||||||
|
@ -69,9 +70,11 @@ func NewRouter(ctx context.Context, logger log.Logger, options option.RouteOptio
|
||||||
dnsLogger: logger.WithPrefix("dns: "),
|
dnsLogger: logger.WithPrefix("dns: "),
|
||||||
outboundByTag: make(map[string]adapter.Outbound),
|
outboundByTag: make(map[string]adapter.Outbound),
|
||||||
rules: make([]adapter.Rule, 0, len(options.Rules)),
|
rules: make([]adapter.Rule, 0, len(options.Rules)),
|
||||||
|
dnsRules: make([]adapter.Rule, 0, len(dnsOptions.Rules)),
|
||||||
needGeoIPDatabase: hasGeoRule(options.Rules, isGeoIPRule) || hasGeoDNSRule(dnsOptions.Rules, isGeoIPDNSRule),
|
needGeoIPDatabase: hasGeoRule(options.Rules, isGeoIPRule) || hasGeoDNSRule(dnsOptions.Rules, isGeoIPDNSRule),
|
||||||
needGeositeDatabase: hasGeoRule(options.Rules, isGeositeRule) || hasGeoDNSRule(dnsOptions.Rules, isGeositeDNSRule),
|
needGeositeDatabase: hasGeoRule(options.Rules, isGeositeRule) || hasGeoDNSRule(dnsOptions.Rules, isGeositeDNSRule),
|
||||||
geoIPOptions: common.PtrValueOrDefault(options.GeoIP),
|
geoIPOptions: common.PtrValueOrDefault(options.GeoIP),
|
||||||
|
geositeOptions: common.PtrValueOrDefault(options.Geosite),
|
||||||
defaultDetour: options.Final,
|
defaultDetour: options.Final,
|
||||||
dnsClient: dns.NewClient(dnsOptions.DNSClientOptions),
|
dnsClient: dns.NewClient(dnsOptions.DNSClientOptions),
|
||||||
defaultDomainStrategy: C.DomainStrategy(dnsOptions.Strategy),
|
defaultDomainStrategy: C.DomainStrategy(dnsOptions.Strategy),
|
||||||
|
@ -88,7 +91,7 @@ func NewRouter(ctx context.Context, logger log.Logger, options option.RouteOptio
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "parse dns rule[", i, "]")
|
return nil, E.Cause(err, "parse dns rule[", i, "]")
|
||||||
}
|
}
|
||||||
router.rules = append(router.rules, dnsRule)
|
router.dnsRules = append(router.dnsRules, dnsRule)
|
||||||
}
|
}
|
||||||
transports := make([]adapter.DNSTransport, len(dnsOptions.Servers))
|
transports := make([]adapter.DNSTransport, len(dnsOptions.Servers))
|
||||||
dummyTransportMap := make(map[string]adapter.DNSTransport)
|
dummyTransportMap := make(map[string]adapter.DNSTransport)
|
||||||
|
@ -259,6 +262,12 @@ func (r *Router) Start() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, rule := range r.dnsRules {
|
||||||
|
err := rule.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
if r.needGeositeDatabase {
|
if r.needGeositeDatabase {
|
||||||
for _, rule := range r.rules {
|
for _, rule := range r.rules {
|
||||||
err := rule.UpdateGeosite()
|
err := rule.UpdateGeosite()
|
||||||
|
@ -266,6 +275,12 @@ func (r *Router) Start() error {
|
||||||
r.logger.Error("failed to initialize geosite: ", err)
|
r.logger.Error("failed to initialize geosite: ", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, rule := range r.dnsRules {
|
||||||
|
err := rule.UpdateGeosite()
|
||||||
|
if err != nil {
|
||||||
|
r.logger.Error("failed to initialize geosite: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
err := common.Close(r.geositeReader)
|
err := common.Close(r.geositeReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -275,6 +290,18 @@ func (r *Router) Start() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) Close() error {
|
func (r *Router) Close() error {
|
||||||
|
for _, rule := range r.rules {
|
||||||
|
err := rule.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, rule := range r.dnsRules {
|
||||||
|
err := rule.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return common.Close(
|
return common.Close(
|
||||||
common.PtrOrNil(r.geoIPReader),
|
common.PtrOrNil(r.geoIPReader),
|
||||||
)
|
)
|
||||||
|
@ -325,12 +352,20 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||||
conn = bufio.NewCachedConn(conn, buffer)
|
conn = bufio.NewCachedConn(conn, buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if metadata.Destination.IsFqdn() && metadata.DomainStrategy != C.DomainStrategyAsIS {
|
||||||
|
addresses, err := r.Lookup(adapter.WithContext(ctx, &metadata), metadata.Destination.Fqdn, metadata.DomainStrategy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
metadata.DestinationAddresses = addresses
|
||||||
|
r.dnsLogger.WithContext(ctx).Info("resolved [", strings.Join(common.Map(metadata.DestinationAddresses, F.ToString0[netip.Addr]), " "), "]")
|
||||||
|
}
|
||||||
detour := r.match(ctx, metadata, r.defaultOutboundForConnection)
|
detour := r.match(ctx, metadata, r.defaultOutboundForConnection)
|
||||||
if !common.Contains(detour.Network(), C.NetworkTCP) {
|
if !common.Contains(detour.Network(), C.NetworkTCP) {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return E.New("missing supported outbound, closing connection")
|
return E.New("missing supported outbound, closing connection")
|
||||||
}
|
}
|
||||||
return detour.NewConnection(adapter.WithContext(ctx, &metadata), conn, metadata.Destination)
|
return detour.NewConnection(ctx, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
|
@ -359,12 +394,20 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||||
}
|
}
|
||||||
conn = bufio.NewCachedPacketConn(conn, buffer, originDestination)
|
conn = bufio.NewCachedPacketConn(conn, buffer, originDestination)
|
||||||
}
|
}
|
||||||
|
if metadata.Destination.IsFqdn() && metadata.DomainStrategy != C.DomainStrategyAsIS {
|
||||||
|
addresses, err := r.Lookup(adapter.WithContext(ctx, &metadata), metadata.Destination.Fqdn, metadata.DomainStrategy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
metadata.DestinationAddresses = addresses
|
||||||
|
r.dnsLogger.WithContext(ctx).Info("resolved [", strings.Join(common.Map(metadata.DestinationAddresses, F.ToString0[netip.Addr]), " "), "]")
|
||||||
|
}
|
||||||
detour := r.match(ctx, metadata, r.defaultOutboundForPacketConnection)
|
detour := r.match(ctx, metadata, r.defaultOutboundForPacketConnection)
|
||||||
if !common.Contains(detour.Network(), C.NetworkUDP) {
|
if !common.Contains(detour.Network(), C.NetworkUDP) {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
return E.New("missing supported outbound, closing packet connection")
|
return E.New("missing supported outbound, closing packet connection")
|
||||||
}
|
}
|
||||||
return detour.NewPacketConnection(adapter.WithContext(ctx, &metadata), conn, metadata.Destination)
|
return detour.NewPacketConnection(ctx, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) Exchange(ctx context.Context, message *dnsmessage.Message) (*dnsmessage.Message, error) {
|
func (r *Router) Exchange(ctx context.Context, message *dnsmessage.Message) (*dnsmessage.Message, error) {
|
||||||
|
@ -397,10 +440,10 @@ func (r *Router) match(ctx context.Context, metadata adapter.InboundContext, def
|
||||||
func (r *Router) matchDNS(ctx context.Context) adapter.DNSTransport {
|
func (r *Router) matchDNS(ctx context.Context) adapter.DNSTransport {
|
||||||
metadata := adapter.ContextFrom(ctx)
|
metadata := adapter.ContextFrom(ctx)
|
||||||
if metadata == nil {
|
if metadata == nil {
|
||||||
r.dnsLogger.WithContext(ctx).Info("no context")
|
r.dnsLogger.WithContext(ctx).Warn("no context")
|
||||||
return r.defaultTransport
|
return r.defaultTransport
|
||||||
}
|
}
|
||||||
for i, rule := range r.rules {
|
for i, rule := range r.dnsRules {
|
||||||
if rule.Match(metadata) {
|
if rule.Match(metadata) {
|
||||||
detour := rule.Outbound()
|
detour := rule.Outbound()
|
||||||
r.dnsLogger.WithContext(ctx).Info("match[", i, "] ", rule.String(), " => ", detour)
|
r.dnsLogger.WithContext(ctx).Info("match[", i, "] ", rule.String(), " => ", detour)
|
||||||
|
|
|
@ -41,14 +41,21 @@ func (r *IPCIDRItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if metadata.Destination.IsFqdn() {
|
if metadata.Destination.IsIP() {
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, prefix := range r.prefixes {
|
for _, prefix := range r.prefixes {
|
||||||
if prefix.Contains(metadata.Destination.Addr) {
|
if prefix.Contains(metadata.Destination.Addr) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for _, address := range metadata.DestinationAddresses {
|
||||||
|
for _, prefix := range r.prefixes {
|
||||||
|
if prefix.Contains(address) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@ package route
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
N "github.com/sagernet/sing/common/network"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
)
|
)
|
||||||
|
@ -36,42 +34,27 @@ func NewGeoIPItem(router adapter.Router, logger log.Logger, isSource bool, codes
|
||||||
func (r *GeoIPItem) Match(metadata *adapter.InboundContext) bool {
|
func (r *GeoIPItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
geoReader := r.router.GeoIPReader()
|
geoReader := r.router.GeoIPReader()
|
||||||
if geoReader == nil {
|
if geoReader == nil {
|
||||||
return r.match(metadata)
|
return false
|
||||||
}
|
}
|
||||||
if r.isSource {
|
if r.isSource {
|
||||||
if metadata.SourceGeoIPCode == "" {
|
if metadata.SourceGeoIPCode == "" {
|
||||||
metadata.SourceGeoIPCode = geoReader.Lookup(metadata.Source.Addr)
|
metadata.SourceGeoIPCode = geoReader.Lookup(metadata.Source.Addr)
|
||||||
}
|
}
|
||||||
|
return r.codeMap[metadata.SourceGeoIPCode]
|
||||||
} else {
|
} else {
|
||||||
if metadata.Destination.IsFqdn() {
|
if metadata.Destination.IsIP() {
|
||||||
return false
|
|
||||||
}
|
|
||||||
if metadata.GeoIPCode == "" {
|
if metadata.GeoIPCode == "" {
|
||||||
metadata.GeoIPCode = geoReader.Lookup(metadata.Destination.Addr)
|
metadata.GeoIPCode = geoReader.Lookup(metadata.Destination.Addr)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return r.match(metadata)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *GeoIPItem) match(metadata *adapter.InboundContext) bool {
|
|
||||||
if r.isSource {
|
|
||||||
if metadata.SourceGeoIPCode == "" {
|
|
||||||
if !N.IsPublicAddr(metadata.Source.Addr) {
|
|
||||||
metadata.SourceGeoIPCode = "private"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r.codeMap[metadata.SourceGeoIPCode]
|
|
||||||
} else {
|
|
||||||
if metadata.Destination.IsFqdn() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if metadata.GeoIPCode == "" {
|
|
||||||
if !N.IsPublicAddr(metadata.Destination.Addr) {
|
|
||||||
metadata.GeoIPCode = "private"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r.codeMap[metadata.GeoIPCode]
|
return r.codeMap[metadata.GeoIPCode]
|
||||||
}
|
}
|
||||||
|
for _, address := range metadata.DestinationAddresses {
|
||||||
|
if r.codeMap[geoReader.Lookup(address)] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *GeoIPItem) String() string {
|
func (r *GeoIPItem) String() string {
|
||||||
|
|
Loading…
Reference in a new issue