mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-24 17:41:29 +00:00
Add loopback check
This commit is contained in:
parent
62425ad3e4
commit
6843970536
3
box.go
3
box.go
|
@ -117,6 +117,7 @@ func New(options Options) (*Box, error) {
|
||||||
ctx,
|
ctx,
|
||||||
router,
|
router,
|
||||||
logFactory.NewLogger(F.ToString("outbound/", outboundOptions.Type, "[", tag, "]")),
|
logFactory.NewLogger(F.ToString("outbound/", outboundOptions.Type, "[", tag, "]")),
|
||||||
|
tag,
|
||||||
outboundOptions)
|
outboundOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "parse outbound[", i, "]")
|
return nil, E.Cause(err, "parse outbound[", i, "]")
|
||||||
|
@ -124,7 +125,7 @@ func New(options Options) (*Box, error) {
|
||||||
outbounds = append(outbounds, out)
|
outbounds = append(outbounds, out)
|
||||||
}
|
}
|
||||||
err = router.Initialize(inbounds, outbounds, func() adapter.Outbound {
|
err = router.Initialize(inbounds, outbounds, func() adapter.Outbound {
|
||||||
out, oErr := outbound.New(ctx, router, logFactory.NewLogger("outbound/direct"), option.Outbound{Type: "direct", Tag: "default"})
|
out, oErr := outbound.New(ctx, router, logFactory.NewLogger("outbound/direct"), "direct", option.Outbound{Type: "direct", Tag: "default"})
|
||||||
common.Must(oErr)
|
common.Must(oErr)
|
||||||
outbounds = append(outbounds, out)
|
outbounds = append(outbounds, out)
|
||||||
return out
|
return out
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -26,7 +26,7 @@ require (
|
||||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||||
github.com/sagernet/sing v0.2.2-0.20230407053809-308e421e33c2
|
github.com/sagernet/sing v0.2.2-0.20230407053809-308e421e33c2
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230407055526-2a27418e7855
|
github.com/sagernet/sing-dns v0.1.5-0.20230408004833-5adaf486d440
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.0
|
github.com/sagernet/sing-shadowsocks v0.2.0
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0
|
github.com/sagernet/sing-shadowtls v0.1.0
|
||||||
github.com/sagernet/sing-tun v0.1.4-0.20230326080954-8848c0e4cbab
|
github.com/sagernet/sing-tun v0.1.4-0.20230326080954-8848c0e4cbab
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -113,8 +113,8 @@ github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
||||||
github.com/sagernet/sing v0.2.2-0.20230407053809-308e421e33c2 h1:VjeHDxEgpB2fqK5G16yBvtLacibvg3h2MsIjal0UXH0=
|
github.com/sagernet/sing v0.2.2-0.20230407053809-308e421e33c2 h1:VjeHDxEgpB2fqK5G16yBvtLacibvg3h2MsIjal0UXH0=
|
||||||
github.com/sagernet/sing v0.2.2-0.20230407053809-308e421e33c2/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
|
github.com/sagernet/sing v0.2.2-0.20230407053809-308e421e33c2/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230407055526-2a27418e7855 h1:a3W2X1n5C/oYGp/Dd26eoymME3iXN8TJq7LZtO2MSUY=
|
github.com/sagernet/sing-dns v0.1.5-0.20230408004833-5adaf486d440 h1:VH8/BcOVuApHtS+vKP+khxlGRcXH7KKhgkTDtNynqSQ=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230407055526-2a27418e7855/go.mod h1:69PNSHyEmXdjf6C+bXBOdr2GQnPeEyWjIzo/MV8gmz8=
|
github.com/sagernet/sing-dns v0.1.5-0.20230408004833-5adaf486d440/go.mod h1:69PNSHyEmXdjf6C+bXBOdr2GQnPeEyWjIzo/MV8gmz8=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.0 h1:ILDWL7pwWfkPLEbviE/MyCgfjaBmJY/JVVY+5jhSb58=
|
github.com/sagernet/sing-shadowsocks v0.2.0 h1:ILDWL7pwWfkPLEbviE/MyCgfjaBmJY/JVVY+5jhSb58=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.0/go.mod h1:ysYzszRLpNzJSorvlWRMuzU6Vchsp7sd52q+JNY4axw=
|
github.com/sagernet/sing-shadowsocks v0.2.0/go.mod h1:ysYzszRLpNzJSorvlWRMuzU6Vchsp7sd52q+JNY4axw=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=
|
github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
dns.RegisterTransport([]string{"dhcp"}, func(ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
|
dns.RegisterTransport([]string{"dhcp"}, func(name string, ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
|
||||||
return nil, E.New(`DHCP is not included in this build, rebuild with -tags with_dhcp`)
|
return nil, E.New(`DHCP is not included in this build, rebuild with -tags with_dhcp`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
const WithQUIC = false
|
const WithQUIC = false
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
dns.RegisterTransport([]string{"quic", "h3"}, func(ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
|
dns.RegisterTransport([]string{"quic", "h3"}, func(name string, ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
|
||||||
return nil, C.ErrQUICNotIncluded
|
return nil, C.ErrQUICNotIncluded
|
||||||
})
|
})
|
||||||
v2ray.RegisterQUICConstructor(
|
v2ray.RegisterQUICConstructor(
|
||||||
|
|
|
@ -10,50 +10,51 @@ import (
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.Outbound) (adapter.Outbound, error) {
|
func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Outbound) (adapter.Outbound, error) {
|
||||||
var metadata *adapter.InboundContext
|
var metadata *adapter.InboundContext
|
||||||
if options.Tag != "" {
|
if tag != "" {
|
||||||
ctx, metadata = adapter.AppendContext(ctx)
|
ctx, metadata = adapter.AppendContext(ctx)
|
||||||
metadata.Outbound = options.Tag
|
metadata.Outbound = tag
|
||||||
}
|
}
|
||||||
if options.Type == "" {
|
if options.Type == "" {
|
||||||
return nil, E.New("missing outbound type")
|
return nil, E.New("missing outbound type")
|
||||||
}
|
}
|
||||||
|
ctx = ContextWithTag(ctx, tag)
|
||||||
switch options.Type {
|
switch options.Type {
|
||||||
case C.TypeDirect:
|
case C.TypeDirect:
|
||||||
return NewDirect(router, logger, options.Tag, options.DirectOptions)
|
return NewDirect(router, logger, tag, options.DirectOptions)
|
||||||
case C.TypeBlock:
|
case C.TypeBlock:
|
||||||
return NewBlock(logger, options.Tag), nil
|
return NewBlock(logger, tag), nil
|
||||||
case C.TypeDNS:
|
case C.TypeDNS:
|
||||||
return NewDNS(router, options.Tag), nil
|
return NewDNS(router, tag), nil
|
||||||
case C.TypeSocks:
|
case C.TypeSocks:
|
||||||
return NewSocks(router, logger, options.Tag, options.SocksOptions)
|
return NewSocks(router, logger, tag, options.SocksOptions)
|
||||||
case C.TypeHTTP:
|
case C.TypeHTTP:
|
||||||
return NewHTTP(router, logger, options.Tag, options.HTTPOptions)
|
return NewHTTP(router, logger, tag, options.HTTPOptions)
|
||||||
case C.TypeShadowsocks:
|
case C.TypeShadowsocks:
|
||||||
return NewShadowsocks(ctx, router, logger, options.Tag, options.ShadowsocksOptions)
|
return NewShadowsocks(ctx, router, logger, tag, options.ShadowsocksOptions)
|
||||||
case C.TypeVMess:
|
case C.TypeVMess:
|
||||||
return NewVMess(ctx, router, logger, options.Tag, options.VMessOptions)
|
return NewVMess(ctx, router, logger, tag, options.VMessOptions)
|
||||||
case C.TypeTrojan:
|
case C.TypeTrojan:
|
||||||
return NewTrojan(ctx, router, logger, options.Tag, options.TrojanOptions)
|
return NewTrojan(ctx, router, logger, tag, options.TrojanOptions)
|
||||||
case C.TypeWireGuard:
|
case C.TypeWireGuard:
|
||||||
return NewWireGuard(ctx, router, logger, options.Tag, options.WireGuardOptions)
|
return NewWireGuard(ctx, router, logger, tag, options.WireGuardOptions)
|
||||||
case C.TypeHysteria:
|
case C.TypeHysteria:
|
||||||
return NewHysteria(ctx, router, logger, options.Tag, options.HysteriaOptions)
|
return NewHysteria(ctx, router, logger, tag, options.HysteriaOptions)
|
||||||
case C.TypeTor:
|
case C.TypeTor:
|
||||||
return NewTor(ctx, router, logger, options.Tag, options.TorOptions)
|
return NewTor(ctx, router, logger, tag, options.TorOptions)
|
||||||
case C.TypeSSH:
|
case C.TypeSSH:
|
||||||
return NewSSH(ctx, router, logger, options.Tag, options.SSHOptions)
|
return NewSSH(ctx, router, logger, tag, options.SSHOptions)
|
||||||
case C.TypeShadowTLS:
|
case C.TypeShadowTLS:
|
||||||
return NewShadowTLS(ctx, router, logger, options.Tag, options.ShadowTLSOptions)
|
return NewShadowTLS(ctx, router, logger, tag, options.ShadowTLSOptions)
|
||||||
case C.TypeShadowsocksR:
|
case C.TypeShadowsocksR:
|
||||||
return NewShadowsocksR(ctx, router, logger, options.Tag, options.ShadowsocksROptions)
|
return NewShadowsocksR(ctx, router, logger, tag, options.ShadowsocksROptions)
|
||||||
case C.TypeVLESS:
|
case C.TypeVLESS:
|
||||||
return NewVLESS(ctx, router, logger, options.Tag, options.VLESSOptions)
|
return NewVLESS(ctx, router, logger, tag, options.VLESSOptions)
|
||||||
case C.TypeSelector:
|
case C.TypeSelector:
|
||||||
return NewSelector(router, logger, options.Tag, options.SelectorOptions)
|
return NewSelector(router, logger, tag, options.SelectorOptions)
|
||||||
case C.TypeURLTest:
|
case C.TypeURLTest:
|
||||||
return NewURLTest(router, logger, options.Tag, options.URLTestOptions)
|
return NewURLTest(router, logger, tag, options.URLTestOptions)
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown outbound type: ", options.Type)
|
return nil, E.New("unknown outbound type: ", options.Type)
|
||||||
}
|
}
|
||||||
|
|
14
outbound/lookback.go
Normal file
14
outbound/lookback.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package outbound
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
type outboundTagKey struct{}
|
||||||
|
|
||||||
|
func ContextWithTag(ctx context.Context, outboundTag string) context.Context {
|
||||||
|
return context.WithValue(ctx, outboundTagKey{}, outboundTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TagFromContext(ctx context.Context) (string, bool) {
|
||||||
|
value, loaded := ctx.Value(outboundTagKey{}).(string)
|
||||||
|
return value, loaded
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/ntp"
|
"github.com/sagernet/sing-box/ntp"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing-box/outbound"
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
"github.com/sagernet/sing-tun"
|
"github.com/sagernet/sing-tun"
|
||||||
"github.com/sagernet/sing-vmess"
|
"github.com/sagernet/sing-vmess"
|
||||||
|
@ -218,7 +219,7 @@ func NewRouter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
transport, err := dns.CreateTransport(ctx, logFactory.NewLogger(F.ToString("dns/transport[", tag, "]")), detour, server.Address)
|
transport, err := dns.CreateTransport(tag, ctx, logFactory.NewLogger(F.ToString("dns/transport[", tag, "]")), detour, server.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "parse dns server[", tag, "]")
|
return nil, E.Cause(err, "parse dns server[", tag, "]")
|
||||||
}
|
}
|
||||||
|
@ -258,7 +259,7 @@ func NewRouter(
|
||||||
}
|
}
|
||||||
if defaultTransport == nil {
|
if defaultTransport == nil {
|
||||||
if len(transports) == 0 {
|
if len(transports) == 0 {
|
||||||
transports = append(transports, dns.NewLocalTransport(N.SystemDialer))
|
transports = append(transports, dns.NewLocalTransport("local", N.SystemDialer))
|
||||||
}
|
}
|
||||||
defaultTransport = transports[0]
|
defaultTransport = transports[0]
|
||||||
}
|
}
|
||||||
|
@ -660,9 +661,11 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||||
metadata.DestinationAddresses = addresses
|
metadata.DestinationAddresses = addresses
|
||||||
r.dnsLogger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]")
|
r.dnsLogger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]")
|
||||||
}
|
}
|
||||||
matchedRule, detour := r.match(ctx, &metadata, r.defaultOutboundForConnection)
|
ctx, matchedRule, detour, err := r.match(ctx, &metadata, r.defaultOutboundForConnection)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if !common.Contains(detour.Network(), N.NetworkTCP) {
|
if !common.Contains(detour.Network(), N.NetworkTCP) {
|
||||||
conn.Close()
|
|
||||||
return E.New("missing supported outbound, closing connection")
|
return E.New("missing supported outbound, closing connection")
|
||||||
}
|
}
|
||||||
if r.clashServer != nil {
|
if r.clashServer != nil {
|
||||||
|
@ -738,9 +741,11 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||||
metadata.DestinationAddresses = addresses
|
metadata.DestinationAddresses = addresses
|
||||||
r.dnsLogger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]")
|
r.dnsLogger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]")
|
||||||
}
|
}
|
||||||
matchedRule, detour := r.match(ctx, &metadata, r.defaultOutboundForPacketConnection)
|
ctx, matchedRule, detour, err := r.match(ctx, &metadata, r.defaultOutboundForPacketConnection)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if !common.Contains(detour.Network(), N.NetworkUDP) {
|
if !common.Contains(detour.Network(), N.NetworkUDP) {
|
||||||
conn.Close()
|
|
||||||
return E.New("missing supported outbound, closing packet connection")
|
return E.New("missing supported outbound, closing packet connection")
|
||||||
}
|
}
|
||||||
if r.clashServer != nil {
|
if r.clashServer != nil {
|
||||||
|
@ -756,7 +761,18 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||||
return detour.NewPacketConnection(ctx, conn, metadata)
|
return detour.NewPacketConnection(ctx, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) match(ctx context.Context, metadata *adapter.InboundContext, defaultOutbound adapter.Outbound) (adapter.Rule, adapter.Outbound) {
|
func (r *Router) match(ctx context.Context, metadata *adapter.InboundContext, defaultOutbound adapter.Outbound) (context.Context, adapter.Rule, adapter.Outbound, error) {
|
||||||
|
matchRule, matchOutbound := r.match0(ctx, metadata, defaultOutbound)
|
||||||
|
if contextOutbound, loaded := outbound.TagFromContext(ctx); loaded {
|
||||||
|
if contextOutbound == matchOutbound.Tag() {
|
||||||
|
return nil, nil, nil, E.New("connection loopback in outbound/", matchOutbound.Type(), "[", matchOutbound.Tag(), "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx = outbound.ContextWithTag(ctx, matchOutbound.Tag())
|
||||||
|
return ctx, matchRule, matchOutbound, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Router) match0(ctx context.Context, metadata *adapter.InboundContext, defaultOutbound adapter.Outbound) (adapter.Rule, adapter.Outbound) {
|
||||||
if r.processSearcher != nil {
|
if r.processSearcher != nil {
|
||||||
var originDestination netip.AddrPort
|
var originDestination netip.AddrPort
|
||||||
if metadata.OriginDestination.IsValid() {
|
if metadata.OriginDestination.IsValid() {
|
||||||
|
|
|
@ -35,6 +35,7 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Transport struct {
|
type Transport struct {
|
||||||
|
name string
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
router adapter.Router
|
router adapter.Router
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
|
@ -46,7 +47,7 @@ type Transport struct {
|
||||||
updatedAt time.Time
|
updatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTransport(ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
|
func NewTransport(name string, ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
|
||||||
linkURL, err := url.Parse(link)
|
linkURL, err := url.Parse(link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -59,6 +60,7 @@ func NewTransport(ctx context.Context, logger logger.ContextLogger, dialer N.Dia
|
||||||
return nil, E.New("missing router in context")
|
return nil, E.New("missing router in context")
|
||||||
}
|
}
|
||||||
transport := &Transport{
|
transport := &Transport{
|
||||||
|
name: name,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: router,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
@ -68,6 +70,10 @@ func NewTransport(ctx context.Context, logger logger.ContextLogger, dialer N.Dia
|
||||||
return transport, nil
|
return transport, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Transport) Name() string {
|
||||||
|
return t.name
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Transport) Start() error {
|
func (t *Transport) Start() error {
|
||||||
err := t.fetchServers()
|
err := t.fetchServers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -247,7 +253,7 @@ func (t *Transport) recreateServers(iface *net.Interface, serverAddrs []netip.Ad
|
||||||
})
|
})
|
||||||
var transports []dns.Transport
|
var transports []dns.Transport
|
||||||
for _, serverAddr := range serverAddrs {
|
for _, serverAddr := range serverAddrs {
|
||||||
serverTransport, err := dns.NewUDPTransport(t.ctx, serverDialer, M.Socksaddr{Addr: serverAddr, Port: 53})
|
serverTransport, err := dns.NewUDPTransport(t.name, t.ctx, serverDialer, M.Socksaddr{Addr: serverAddr, Port: 53})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue