mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-06-09 12:58:15 +03:00
Add new admin panel, failover, dns fallback, providers, limiters. Update XHTTP
This commit is contained in:
72
dns/transport/fallback/fallback.go
Normal file
72
dns/transport/fallback/fallback.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package fallback
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/dns"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
"github.com/sagernet/sing/service"
|
||||
|
||||
mDNS "github.com/miekg/dns"
|
||||
)
|
||||
|
||||
func RegisterTransport(registry *dns.TransportRegistry) {
|
||||
dns.RegisterTransport[option.FallbackDNSServerOptions](registry, C.DNSTypeFallback, NewTransport)
|
||||
}
|
||||
|
||||
var _ adapter.DNSTransport = (*Transport)(nil)
|
||||
|
||||
type Transport struct {
|
||||
dns.TransportAdapter
|
||||
ctx context.Context
|
||||
manager adapter.DNSTransportManager
|
||||
logger logger.ContextLogger
|
||||
tags []string
|
||||
strategy ExchangeStrategy
|
||||
}
|
||||
|
||||
func NewTransport(ctx context.Context, logger log.ContextLogger, tag string, options option.FallbackDNSServerOptions) (adapter.DNSTransport, error) {
|
||||
if len(options.Servers) == 0 {
|
||||
return nil, E.New("missing servers")
|
||||
}
|
||||
manager := service.FromContext[adapter.DNSTransportManager](ctx)
|
||||
servers := make([]adapter.DNSTransport, len(options.Servers))
|
||||
for i, tag := range options.Servers {
|
||||
server, loaded := manager.Transport(tag)
|
||||
if !loaded {
|
||||
return nil, E.New("server ", tag, " not found")
|
||||
}
|
||||
servers[i] = server
|
||||
}
|
||||
strategy, err := CreateStrategy(options.Strategy, servers, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Transport{
|
||||
TransportAdapter: dns.NewTransportAdapter(C.DNSTypeFallback, tag, options.Servers),
|
||||
ctx: ctx,
|
||||
logger: logger,
|
||||
tags: options.Servers,
|
||||
strategy: strategy,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *Transport) Start(stage adapter.StartStage) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Transport) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Transport) Reset() {
|
||||
}
|
||||
|
||||
func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||
return t.strategy(ctx, message)
|
||||
}
|
||||
73
dns/transport/fallback/strategy.go
Normal file
73
dns/transport/fallback/strategy.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package fallback
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
mDNS "github.com/miekg/dns"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
)
|
||||
|
||||
type ExchangeStrategy = func(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error)
|
||||
|
||||
func parallelStrategy(servers []adapter.DNSTransport, logger logger.ContextLogger) ExchangeStrategy {
|
||||
return func(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||
queryCtx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
type result struct {
|
||||
response *mDNS.Msg
|
||||
err error
|
||||
}
|
||||
results := make(chan result)
|
||||
for _, server := range servers {
|
||||
go func() {
|
||||
response, err := server.Exchange(queryCtx, message)
|
||||
select {
|
||||
case results <- result{response, err}:
|
||||
case <-queryCtx.Done():
|
||||
}
|
||||
}()
|
||||
}
|
||||
var lastErr error
|
||||
for range servers {
|
||||
select {
|
||||
case result := <-results:
|
||||
if result.err != nil {
|
||||
lastErr = result.err
|
||||
continue
|
||||
}
|
||||
return result.response, nil
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
return nil, lastErr
|
||||
}
|
||||
}
|
||||
|
||||
func sequentialStrategy(servers []adapter.DNSTransport, logger logger.ContextLogger) ExchangeStrategy {
|
||||
return func(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||
var lastErr error
|
||||
for _, server := range servers {
|
||||
response, err := server.Exchange(ctx, message)
|
||||
if err != nil {
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
return nil, lastErr
|
||||
}
|
||||
}
|
||||
|
||||
func CreateStrategy(strategy string, servers []adapter.DNSTransport, logger logger.ContextLogger) (ExchangeStrategy, error) {
|
||||
switch strategy {
|
||||
case "parallel":
|
||||
return parallelStrategy(servers, logger), nil
|
||||
case "", "sequential":
|
||||
return sequentialStrategy(servers, logger), nil
|
||||
default:
|
||||
return nil, E.New("strategy not found: ", strategy)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user