mirror of
https://github.com/wyx2685/V2bX.git
synced 2026-02-04 04:30:08 +00:00
update singbox
This commit is contained in:
@@ -1,79 +0,0 @@
|
||||
package sing
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/inazumav/sing-box/adapter"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
)
|
||||
|
||||
func (b *Box) startOutbounds() error {
|
||||
outboundTags := make(map[adapter.Outbound]string)
|
||||
outbounds := make(map[string]adapter.Outbound)
|
||||
for i, outboundToStart := range b.outbounds {
|
||||
var outboundTag string
|
||||
if outboundToStart.Tag() == "" {
|
||||
outboundTag = F.ToString(i)
|
||||
} else {
|
||||
outboundTag = outboundToStart.Tag()
|
||||
}
|
||||
if _, exists := outbounds[outboundTag]; exists {
|
||||
return E.New("outbound tag ", outboundTag, " duplicated")
|
||||
}
|
||||
outboundTags[outboundToStart] = outboundTag
|
||||
outbounds[outboundTag] = outboundToStart
|
||||
}
|
||||
started := make(map[string]bool)
|
||||
for {
|
||||
canContinue := false
|
||||
startOne:
|
||||
for _, outboundToStart := range b.outbounds {
|
||||
outboundTag := outboundTags[outboundToStart]
|
||||
if started[outboundTag] {
|
||||
continue
|
||||
}
|
||||
dependencies := outboundToStart.Dependencies()
|
||||
for _, dependency := range dependencies {
|
||||
if !started[dependency] {
|
||||
continue startOne
|
||||
}
|
||||
}
|
||||
started[outboundTag] = true
|
||||
canContinue = true
|
||||
if starter, isStarter := outboundToStart.(common.Starter); isStarter {
|
||||
b.logger.Trace("initializing outbound/", outboundToStart.Type(), "[", outboundTag, "]")
|
||||
err := starter.Start()
|
||||
if err != nil {
|
||||
return E.Cause(err, "initialize outbound/", outboundToStart.Type(), "[", outboundTag, "]")
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(started) == len(b.outbounds) {
|
||||
break
|
||||
}
|
||||
if canContinue {
|
||||
continue
|
||||
}
|
||||
currentOutbound := common.Find(b.outbounds, func(it adapter.Outbound) bool {
|
||||
return !started[outboundTags[it]]
|
||||
})
|
||||
var lintOutbound func(oTree []string, oCurrent adapter.Outbound) error
|
||||
lintOutbound = func(oTree []string, oCurrent adapter.Outbound) error {
|
||||
problemOutboundTag := common.Find(oCurrent.Dependencies(), func(it string) bool {
|
||||
return !started[it]
|
||||
})
|
||||
if common.Contains(oTree, problemOutboundTag) {
|
||||
return E.New("circular outbound dependency: ", strings.Join(oTree, " -> "), " -> ", problemOutboundTag)
|
||||
}
|
||||
problemOutbound := outbounds[problemOutboundTag]
|
||||
if problemOutbound == nil {
|
||||
return E.New("dependency[", problemOutbound, "] not found for outbound[", outboundTags[oCurrent], "]")
|
||||
}
|
||||
return lintOutbound(append(oTree, problemOutboundTag), problemOutbound)
|
||||
}
|
||||
return lintOutbound([]string{outboundTags[currentOutbound]}, currentOutbound)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
//go:build !go1.19
|
||||
|
||||
package sing
|
||||
|
||||
import (
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/inazumav/sing-box/common/dialer/conntrack"
|
||||
"github.com/inazumav/sing-box/option"
|
||||
)
|
||||
|
||||
func applyDebugOptions(options option.DebugOptions) {
|
||||
applyDebugListenOption(options)
|
||||
if options.GCPercent != nil {
|
||||
debug.SetGCPercent(*options.GCPercent)
|
||||
}
|
||||
if options.MaxStack != nil {
|
||||
debug.SetMaxStack(*options.MaxStack)
|
||||
}
|
||||
if options.MaxThreads != nil {
|
||||
debug.SetMaxThreads(*options.MaxThreads)
|
||||
}
|
||||
if options.PanicOnFault != nil {
|
||||
debug.SetPanicOnFault(*options.PanicOnFault)
|
||||
}
|
||||
if options.TraceBack != "" {
|
||||
debug.SetTraceback(options.TraceBack)
|
||||
}
|
||||
if options.MemoryLimit != 0 {
|
||||
// debug.SetMemoryLimit(int64(options.MemoryLimit))
|
||||
conntrack.MemoryLimit = int64(options.MemoryLimit)
|
||||
}
|
||||
if options.OOMKiller != nil {
|
||||
conntrack.KillerEnabled = *options.OOMKiller
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
//go:build go1.19
|
||||
|
||||
package sing
|
||||
|
||||
import (
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/inazumav/sing-box/common/dialer/conntrack"
|
||||
"github.com/inazumav/sing-box/option"
|
||||
)
|
||||
|
||||
func applyDebugOptions(options option.DebugOptions) {
|
||||
applyDebugListenOption(options)
|
||||
if options.GCPercent != nil {
|
||||
debug.SetGCPercent(*options.GCPercent)
|
||||
}
|
||||
if options.MaxStack != nil {
|
||||
debug.SetMaxStack(*options.MaxStack)
|
||||
}
|
||||
if options.MaxThreads != nil {
|
||||
debug.SetMaxThreads(*options.MaxThreads)
|
||||
}
|
||||
if options.PanicOnFault != nil {
|
||||
debug.SetPanicOnFault(*options.PanicOnFault)
|
||||
}
|
||||
if options.TraceBack != "" {
|
||||
debug.SetTraceback(options.TraceBack)
|
||||
}
|
||||
if options.MemoryLimit != 0 {
|
||||
debug.SetMemoryLimit(int64(options.MemoryLimit))
|
||||
conntrack.MemoryLimit = int64(options.MemoryLimit)
|
||||
}
|
||||
if options.OOMKiller != nil {
|
||||
conntrack.KillerEnabled = *options.OOMKiller
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package sing
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/inazumav/sing-box/common/badjson"
|
||||
"github.com/inazumav/sing-box/common/json"
|
||||
"github.com/inazumav/sing-box/log"
|
||||
"github.com/inazumav/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
var debugHTTPServer *http.Server
|
||||
|
||||
func applyDebugListenOption(options option.DebugOptions) {
|
||||
if debugHTTPServer != nil {
|
||||
debugHTTPServer.Close()
|
||||
debugHTTPServer = nil
|
||||
}
|
||||
if options.Listen == "" {
|
||||
return
|
||||
}
|
||||
r := chi.NewMux()
|
||||
r.Route("/debug", func(r chi.Router) {
|
||||
r.Get("/gc", func(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.WriteHeader(http.StatusNoContent)
|
||||
go debug.FreeOSMemory()
|
||||
})
|
||||
r.Get("/memory", func(writer http.ResponseWriter, request *http.Request) {
|
||||
var memStats runtime.MemStats
|
||||
runtime.ReadMemStats(&memStats)
|
||||
|
||||
var memObject badjson.JSONObject
|
||||
memObject.Put("heap", humanize.IBytes(memStats.HeapInuse))
|
||||
memObject.Put("stack", humanize.IBytes(memStats.StackInuse))
|
||||
memObject.Put("idle", humanize.IBytes(memStats.HeapIdle-memStats.HeapReleased))
|
||||
memObject.Put("goroutines", runtime.NumGoroutine())
|
||||
memObject.Put("rss", rusageMaxRSS())
|
||||
|
||||
encoder := json.NewEncoder(writer)
|
||||
encoder.SetIndent("", " ")
|
||||
encoder.Encode(memObject)
|
||||
})
|
||||
r.HandleFunc("/pprof", pprof.Index)
|
||||
r.HandleFunc("/pprof/*", pprof.Index)
|
||||
r.HandleFunc("/pprof/cmdline", pprof.Cmdline)
|
||||
r.HandleFunc("/pprof/profile", pprof.Profile)
|
||||
r.HandleFunc("/pprof/symbol", pprof.Symbol)
|
||||
r.HandleFunc("/pprof/trace", pprof.Trace)
|
||||
})
|
||||
debugHTTPServer = &http.Server{
|
||||
Addr: options.Listen,
|
||||
Handler: r,
|
||||
}
|
||||
go func() {
|
||||
err := debugHTTPServer.ListenAndServe()
|
||||
if err != nil && !E.IsClosed(err) {
|
||||
log.Error(E.Cause(err, "serve debug HTTP server"))
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package sing
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func rusageMaxRSS() float64 {
|
||||
ru := syscall.Rusage{}
|
||||
err := syscall.Getrusage(syscall.RUSAGE_SELF, &ru)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
rss := float64(ru.Maxrss)
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||
rss /= 1 << 20 // ru_maxrss is bytes on darwin
|
||||
} else {
|
||||
// ru_maxrss is kilobytes elsewhere (linux, openbsd, etc)
|
||||
rss /= 1 << 10
|
||||
}
|
||||
return rss
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
//go:build !linux
|
||||
|
||||
package sing
|
||||
|
||||
func rusageMaxRSS() float64 {
|
||||
return -1
|
||||
}
|
||||
@@ -6,21 +6,20 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/inazumav/sing-box/common/urltest"
|
||||
"github.com/sagernet/sing-box/common/urltest"
|
||||
|
||||
"github.com/InazumaV/V2bX/common/rate"
|
||||
|
||||
"github.com/InazumaV/V2bX/limiter"
|
||||
|
||||
"github.com/InazumaV/V2bX/common/counter"
|
||||
"github.com/inazumav/sing-box/adapter"
|
||||
"github.com/inazumav/sing-box/log"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
type HookServer struct {
|
||||
EnableConnClear bool
|
||||
logger log.Logger
|
||||
counter sync.Map
|
||||
connClears sync.Map
|
||||
}
|
||||
@@ -56,10 +55,9 @@ func (h *HookServer) ModeList() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewHookServer(logger log.Logger, enableClear bool) *HookServer {
|
||||
func NewHookServer(enableClear bool) *HookServer {
|
||||
return &HookServer{
|
||||
EnableConnClear: enableClear,
|
||||
logger: logger,
|
||||
counter: sync.Map{},
|
||||
connClears: sync.Map{},
|
||||
}
|
||||
@@ -81,25 +79,25 @@ func (h *HookServer) RoutedConnection(_ context.Context, conn net.Conn, m adapte
|
||||
t := &Tracker{}
|
||||
l, err := limiter.GetLimiter(m.Inbound)
|
||||
if err != nil {
|
||||
h.logger.Warn("get limiter for ", m.Inbound, " error: ", err)
|
||||
log.Warn("get limiter for ", m.Inbound, " error: ", err)
|
||||
return conn, t
|
||||
}
|
||||
if l.CheckDomainRule(m.Domain) {
|
||||
conn.Close()
|
||||
h.logger.Error("[", m.Inbound, "] ",
|
||||
log.Error("[", m.Inbound, "] ",
|
||||
"Limited ", m.User, " access to ", m.Domain, " by domain rule")
|
||||
return conn, t
|
||||
}
|
||||
if l.CheckProtocolRule(m.Protocol) {
|
||||
conn.Close()
|
||||
h.logger.Error("[", m.Inbound, "] ",
|
||||
log.Error("[", m.Inbound, "] ",
|
||||
"Limited ", m.User, " use ", m.Domain, " by protocol rule")
|
||||
return conn, t
|
||||
}
|
||||
ip := m.Source.Addr.String()
|
||||
if b, r := l.CheckLimit(m.User, ip, true); r {
|
||||
conn.Close()
|
||||
h.logger.Error("[", m.Inbound, "] ", "Limited ", m.User, " by ip or conn")
|
||||
log.Error("[", m.Inbound, "] ", "Limited ", m.User, " by ip or conn")
|
||||
return conn, t
|
||||
} else if b != nil {
|
||||
conn = rate.NewConnRateLimiter(conn, b)
|
||||
@@ -135,25 +133,25 @@ func (h *HookServer) RoutedPacketConnection(_ context.Context, conn N.PacketConn
|
||||
t := &Tracker{}
|
||||
l, err := limiter.GetLimiter(m.Inbound)
|
||||
if err != nil {
|
||||
h.logger.Warn("get limiter for ", m.Inbound, " error: ", err)
|
||||
log.Warn("get limiter for ", m.Inbound, " error: ", err)
|
||||
return conn, t
|
||||
}
|
||||
if l.CheckDomainRule(m.Domain) {
|
||||
conn.Close()
|
||||
h.logger.Error("[", m.Inbound, "] ",
|
||||
log.Error("[", m.Inbound, "] ",
|
||||
"Limited ", m.User, " access to ", m.Domain, " by domain rule")
|
||||
return conn, t
|
||||
}
|
||||
if l.CheckProtocolRule(m.Protocol) {
|
||||
conn.Close()
|
||||
h.logger.Error("[", m.Inbound, "] ",
|
||||
log.Error("[", m.Inbound, "] ",
|
||||
"Limited ", m.User, " use ", m.Domain, " by protocol rule")
|
||||
return conn, t
|
||||
}
|
||||
ip := m.Source.Addr.String()
|
||||
if b, r := l.CheckLimit(m.User, ip, true); r {
|
||||
conn.Close()
|
||||
h.logger.Error("[", m.Inbound, "] ", "Limited ", m.User, " by ip or conn")
|
||||
log.Error("[", m.Inbound, "] ", "Limited ", m.User, " by ip or conn")
|
||||
return conn, t
|
||||
} else if b != nil {
|
||||
conn = rate.NewPacketConnCounter(conn, b)
|
||||
|
||||
@@ -10,13 +10,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/inazumav/sing-box/inbound"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
|
||||
"github.com/InazumaV/V2bX/api/panel"
|
||||
"github.com/InazumaV/V2bX/conf"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/inazumav/sing-box/option"
|
||||
"github.com/sagernet/sing-box/inbound"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
)
|
||||
|
||||
type WsNetworkConfig struct {
|
||||
@@ -205,7 +204,7 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
||||
return in, nil
|
||||
}
|
||||
|
||||
func (b *Box) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
||||
func (b *Sing) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
||||
err := updateDNSConfig(info)
|
||||
if err != nil {
|
||||
return fmt.Errorf("build dns error: %s", err)
|
||||
@@ -237,7 +236,7 @@ func (b *Box) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Box) DelNode(tag string) error {
|
||||
func (b *Sing) DelNode(tag string) error {
|
||||
err := b.inbounds[tag].Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("close inbound error: %s", err)
|
||||
|
||||
@@ -3,47 +3,32 @@ package sing
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/inazumav/sing-box/constant"
|
||||
"github.com/inazumav/sing-box/log"
|
||||
vlog "github.com/sirupsen/logrus"
|
||||
"io"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/log"
|
||||
|
||||
"github.com/InazumaV/V2bX/conf"
|
||||
vCore "github.com/InazumaV/V2bX/core"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/inazumav/sing-box/adapter"
|
||||
"github.com/inazumav/sing-box/inbound"
|
||||
"github.com/inazumav/sing-box/log"
|
||||
"github.com/inazumav/sing-box/option"
|
||||
"github.com/inazumav/sing-box/outbound"
|
||||
"github.com/inazumav/sing-box/route"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
"github.com/sagernet/sing/service"
|
||||
"github.com/sagernet/sing/service/pause"
|
||||
box "github.com/sagernet/sing-box"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
)
|
||||
|
||||
var _ adapter.Service = (*Box)(nil)
|
||||
var _ vCore.Core = (*Sing)(nil)
|
||||
|
||||
type DNSConfig struct {
|
||||
Servers []map[string]interface{} `json:"servers"`
|
||||
Rules []map[string]interface{} `json:"rules"`
|
||||
}
|
||||
|
||||
type Box struct {
|
||||
type Sing struct {
|
||||
box *box.BoxEx
|
||||
ctx context.Context
|
||||
createdAt time.Time
|
||||
router adapter.Router
|
||||
inbounds map[string]adapter.Inbound
|
||||
outbounds []adapter.Outbound
|
||||
logFactory log.Factory
|
||||
logger log.ContextLogger
|
||||
hookServer *HookServer
|
||||
done chan struct{}
|
||||
router adapter.RouterEx
|
||||
logFactory log.Factory
|
||||
inbounds map[string]adapter.Inbound
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -82,234 +67,47 @@ func New(c *conf.CoreConfig) (vCore.Core, error) {
|
||||
if c.SingConfig.DnsConfigPath != "" {
|
||||
f, err := os.OpenFile(c.SingConfig.DnsConfigPath, os.O_RDWR|os.O_CREATE, 0755)
|
||||
if err != nil {
|
||||
log.Error("Failed to open or create sing dns config file: %s", err)
|
||||
return nil, fmt.Errorf("failed to open or create sing dns config file: %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
if err := json.NewDecoder(f).Decode(options.DNS); err != nil {
|
||||
log.Error(fmt.Sprintf("Failed to unmarshal sing dns config from file '%v': %v. Using default DNS options.", f.Name(), err))
|
||||
log.Warn(fmt.Sprintf(
|
||||
"Failed to unmarshal sing dns config from file '%v': %v. Using default DNS options",
|
||||
f.Name(), err))
|
||||
options.DNS = &option.DNSOptions{}
|
||||
}
|
||||
os.Setenv("SING_DNS_PATH", c.SingConfig.DnsConfigPath)
|
||||
}
|
||||
ctx := context.Background()
|
||||
ctx = service.ContextWithDefaultRegistry(ctx)
|
||||
ctx = pause.ContextWithDefaultManager(ctx)
|
||||
createdAt := time.Now()
|
||||
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
||||
applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug))
|
||||
var defaultLogWriter io.Writer
|
||||
logFactory, err := log.New(log.Options{
|
||||
Context: ctx,
|
||||
Options: common.PtrValueOrDefault(options.Log),
|
||||
DefaultWriter: defaultLogWriter,
|
||||
BaseTime: createdAt,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create log factory")
|
||||
}
|
||||
router, err := route.NewRouter(
|
||||
ctx,
|
||||
logFactory,
|
||||
common.PtrValueOrDefault(options.Route),
|
||||
common.PtrValueOrDefault(options.DNS),
|
||||
common.PtrValueOrDefault(options.NTP),
|
||||
options.Inbounds,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse route options")
|
||||
}
|
||||
inbounds := make([]adapter.Inbound, len(options.Inbounds))
|
||||
inMap := make(map[string]adapter.Inbound, len(inbounds))
|
||||
outbounds := make([]adapter.Outbound, 0, len(options.Outbounds))
|
||||
for i, inboundOptions := range options.Inbounds {
|
||||
var in adapter.Inbound
|
||||
var tag string
|
||||
if inboundOptions.Tag != "" {
|
||||
tag = inboundOptions.Tag
|
||||
} else {
|
||||
tag = F.ToString(i)
|
||||
}
|
||||
in, err = inbound.New(
|
||||
ctx,
|
||||
router,
|
||||
logFactory.NewLogger(F.ToString("inbound/", inboundOptions.Type, "[", tag, "]")),
|
||||
inboundOptions,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse inbound[", i, "]")
|
||||
}
|
||||
inbounds[i] = in
|
||||
inMap[inboundOptions.Tag] = in
|
||||
}
|
||||
for i, outboundOptions := range options.Outbounds {
|
||||
var out adapter.Outbound
|
||||
var tag string
|
||||
if outboundOptions.Tag != "" {
|
||||
tag = outboundOptions.Tag
|
||||
} else {
|
||||
tag = F.ToString(i)
|
||||
}
|
||||
out, err = outbound.New(
|
||||
ctx,
|
||||
router,
|
||||
logFactory.NewLogger(F.ToString("outbound/", outboundOptions.Type, "[", tag, "]")),
|
||||
tag,
|
||||
outboundOptions)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse outbound[", i, "]")
|
||||
}
|
||||
outbounds = append(outbounds, out)
|
||||
}
|
||||
err = router.Initialize(inbounds, outbounds, func() adapter.Outbound {
|
||||
out, oErr := outbound.New(ctx, router, logFactory.NewLogger("outbound/direct"), "direct", option.Outbound{Type: "direct", Tag: "default"})
|
||||
common.Must(oErr)
|
||||
outbounds = append(outbounds, out)
|
||||
return out
|
||||
b, err := box.NewEx(box.Options{
|
||||
Context: ctx,
|
||||
Options: options,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
server := NewHookServer(logFactory.NewLogger("Hook-Server"), c.SingConfig.EnableConnClear)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create v2ray api server")
|
||||
}
|
||||
router.SetClashServer(server)
|
||||
return &Box{
|
||||
hs := NewHookServer(c.SingConfig.EnableConnClear)
|
||||
b.RouterEx().SetClashServer(hs)
|
||||
b.LogFactory()
|
||||
return &Sing{
|
||||
ctx: ctx,
|
||||
router: router,
|
||||
inbounds: inMap,
|
||||
outbounds: outbounds,
|
||||
createdAt: createdAt,
|
||||
logFactory: logFactory,
|
||||
logger: logFactory.Logger(),
|
||||
hookServer: server,
|
||||
done: make(chan struct{}),
|
||||
box: b,
|
||||
hookServer: hs,
|
||||
router: b.RouterEx(),
|
||||
logFactory: b.LogFactory(),
|
||||
inbounds: make(map[string]adapter.Inbound),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *Box) PreStart() error {
|
||||
err := b.preStart()
|
||||
if err != nil {
|
||||
// TODO: remove catch error
|
||||
defer func() {
|
||||
v := recover()
|
||||
if v != nil {
|
||||
log.Error(E.Cause(err, "origin error"))
|
||||
debug.PrintStack()
|
||||
panic("panic on early close: " + fmt.Sprint(v))
|
||||
}
|
||||
}()
|
||||
b.Close()
|
||||
return err
|
||||
}
|
||||
b.logger.Info("sing-box pre-started (", F.Seconds(time.Since(b.createdAt).Seconds()), "s)")
|
||||
return nil
|
||||
func (b *Sing) Start() error {
|
||||
return b.box.Start()
|
||||
}
|
||||
|
||||
func (b *Box) Start() error {
|
||||
err := b.start()
|
||||
if err != nil {
|
||||
// TODO: remove catch error
|
||||
defer func() {
|
||||
v := recover()
|
||||
if v != nil {
|
||||
log.Error(E.Cause(err, "origin error"))
|
||||
debug.PrintStack()
|
||||
panic("panic on early close: " + fmt.Sprint(v))
|
||||
}
|
||||
}()
|
||||
b.Close()
|
||||
return err
|
||||
}
|
||||
b.logger.Info("sing-box started (", F.Seconds(time.Since(b.createdAt).Seconds()), "s)")
|
||||
return nil
|
||||
func (b *Sing) Close() error {
|
||||
return b.box.Close()
|
||||
}
|
||||
|
||||
func (b *Box) preStart() error {
|
||||
err := b.startOutbounds()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.router.Start()
|
||||
}
|
||||
|
||||
func (b *Box) start() error {
|
||||
vlog.Info("Sing Core Version: ", constant.Version)
|
||||
err := b.preStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i, in := range b.inbounds {
|
||||
var tag string
|
||||
if in.Tag() == "" {
|
||||
tag = F.ToString(i)
|
||||
} else {
|
||||
tag = in.Tag()
|
||||
}
|
||||
b.logger.Trace("initializing inbound/", in.Type(), "[", tag, "]")
|
||||
err = in.Start()
|
||||
if err != nil {
|
||||
return E.Cause(err, "initialize inbound/", in.Type(), "[", tag, "]")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Box) postStart() error {
|
||||
for serviceName, service := range b.outbounds {
|
||||
if lateService, isLateService := service.(adapter.PostStarter); isLateService {
|
||||
b.logger.Trace("post-starting ", service)
|
||||
err := lateService.PostStart()
|
||||
if err != nil {
|
||||
return E.Cause(err, "post-start ", serviceName)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Box) Close() error {
|
||||
select {
|
||||
case <-b.done:
|
||||
return os.ErrClosed
|
||||
default:
|
||||
close(b.done)
|
||||
}
|
||||
var errors error
|
||||
for i, in := range b.inbounds {
|
||||
b.logger.Trace("closing inbound/", in.Type(), "[", i, "]")
|
||||
errors = E.Append(errors, in.Close(), func(err error) error {
|
||||
return E.Cause(err, "close inbound/", in.Type(), "[", i, "]")
|
||||
})
|
||||
}
|
||||
for i, out := range b.outbounds {
|
||||
b.logger.Trace("closing outbound/", out.Type(), "[", i, "]")
|
||||
errors = E.Append(errors, common.Close(out), func(err error) error {
|
||||
return E.Cause(err, "close outbound/", out.Type(), "[", i, "]")
|
||||
})
|
||||
}
|
||||
b.logger.Trace("closing router")
|
||||
if err := common.Close(b.router); err != nil {
|
||||
errors = E.Append(errors, err, func(err error) error {
|
||||
return E.Cause(err, "close router")
|
||||
})
|
||||
}
|
||||
b.logger.Trace("closing log factory")
|
||||
if err := common.Close(b.logFactory); err != nil {
|
||||
errors = E.Append(errors, err, func(err error) error {
|
||||
return E.Cause(err, "close log factory")
|
||||
})
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
func (b *Box) Router() adapter.Router {
|
||||
return b.router
|
||||
}
|
||||
|
||||
func (b *Box) Protocols() []string {
|
||||
func (b *Sing) Protocols() []string {
|
||||
return []string{
|
||||
"vmess",
|
||||
"vless",
|
||||
@@ -319,6 +117,6 @@ func (b *Box) Protocols() []string {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Box) Type() string {
|
||||
func (b *Sing) Type() string {
|
||||
return "sing"
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
"github.com/InazumaV/V2bX/api/panel"
|
||||
"github.com/InazumaV/V2bX/common/counter"
|
||||
"github.com/InazumaV/V2bX/core"
|
||||
"github.com/inazumav/sing-box/inbound"
|
||||
"github.com/inazumav/sing-box/option"
|
||||
"github.com/sagernet/sing-box/inbound"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
)
|
||||
|
||||
func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) {
|
||||
func (b *Sing) AddUsers(p *core.AddUsersParams) (added int, err error) {
|
||||
switch p.NodeInfo.Type {
|
||||
case "vmess", "vless":
|
||||
if p.NodeInfo.Type == "vless" {
|
||||
@@ -67,7 +67,7 @@ func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) {
|
||||
AuthString: p.Users[i].Uuid,
|
||||
}
|
||||
}
|
||||
err = b.inbounds[p.Tag].(*inbound.Hysteria).AddUsers(us)
|
||||
err = b.inbounds[p.Tag].(*inbound.HysteriaM).AddUsers(us)
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -75,7 +75,7 @@ func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) {
|
||||
return len(p.Users), err
|
||||
}
|
||||
|
||||
func (b *Box) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
||||
func (b *Sing) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
||||
if v, ok := b.hookServer.counter.Load(tag); ok {
|
||||
c := v.(*counter.TrafficCounter)
|
||||
up = c.GetUpCount(uuid)
|
||||
@@ -92,7 +92,7 @@ type UserDeleter interface {
|
||||
DelUsers(uuid []string) error
|
||||
}
|
||||
|
||||
func (b *Box) DelUsers(users []panel.UserInfo, tag string) error {
|
||||
func (b *Sing) DelUsers(users []panel.UserInfo, tag string) error {
|
||||
var del UserDeleter
|
||||
if i, ok := b.inbounds[tag]; ok {
|
||||
switch i.Type() {
|
||||
@@ -105,7 +105,7 @@ func (b *Box) DelUsers(users []panel.UserInfo, tag string) error {
|
||||
case "trojan":
|
||||
del = i.(*inbound.Trojan)
|
||||
case "hysteria":
|
||||
del = i.(*inbound.Hysteria)
|
||||
del = i.(*inbound.HysteriaM)
|
||||
}
|
||||
} else {
|
||||
return errors.New("the inbound not found")
|
||||
|
||||
@@ -2,9 +2,10 @@ package sing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/InazumaV/V2bX/conf"
|
||||
"github.com/inazumav/sing-box/option"
|
||||
"strconv"
|
||||
|
||||
"github.com/InazumaV/V2bX/conf"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
)
|
||||
|
||||
func processFallback(c *conf.Options, fallbackForALPN map[string]*option.ServerOptions) error {
|
||||
|
||||
@@ -3,6 +3,7 @@ package xray
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/InazumaV/V2bX/api/panel"
|
||||
"github.com/InazumaV/V2bX/conf"
|
||||
"github.com/xtls/xray-core/core"
|
||||
@@ -15,7 +16,7 @@ type DNSConfig struct {
|
||||
Tag string `json:"tag"`
|
||||
}
|
||||
|
||||
func (c *Core) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
||||
func (c *Xray) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
||||
err := updateDNSConfig(info)
|
||||
if err != nil {
|
||||
return fmt.Errorf("build dns error: %s", err)
|
||||
@@ -39,7 +40,7 @@ func (c *Core) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Core) addInbound(config *core.InboundHandlerConfig) error {
|
||||
func (c *Xray) addInbound(config *core.InboundHandlerConfig) error {
|
||||
rawHandler, err := core.CreateObject(c.Server, config)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -54,7 +55,7 @@ func (c *Core) addInbound(config *core.InboundHandlerConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Core) addOutbound(config *core.OutboundHandlerConfig) error {
|
||||
func (c *Xray) addOutbound(config *core.OutboundHandlerConfig) error {
|
||||
rawHandler, err := core.CreateObject(c.Server, config)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -69,7 +70,7 @@ func (c *Core) addOutbound(config *core.OutboundHandlerConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Core) DelNode(tag string) error {
|
||||
func (c *Xray) DelNode(tag string) error {
|
||||
err := c.removeInbound(tag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("remove in error: %s", err)
|
||||
@@ -81,11 +82,11 @@ func (c *Core) DelNode(tag string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Core) removeInbound(tag string) error {
|
||||
func (c *Xray) removeInbound(tag string) error {
|
||||
return c.ihm.RemoveHandler(context.Background(), tag)
|
||||
}
|
||||
|
||||
func (c *Core) removeOutbound(tag string) error {
|
||||
func (c *Xray) removeOutbound(tag string) error {
|
||||
err := c.ohm.RemoveHandler(context.Background(), tag)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/xtls/xray-core/proxy"
|
||||
)
|
||||
|
||||
func (c *Core) GetUserManager(tag string) (proxy.UserManager, error) {
|
||||
func (c *Xray) GetUserManager(tag string) (proxy.UserManager, error) {
|
||||
handler, err := c.ihm.GetHandler(context.Background(), tag)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("no such inbound tag: %s", err)
|
||||
@@ -27,7 +27,7 @@ func (c *Core) GetUserManager(tag string) (proxy.UserManager, error) {
|
||||
return userManager, nil
|
||||
}
|
||||
|
||||
func (c *Core) DelUsers(users []panel.UserInfo, tag string) error {
|
||||
func (c *Xray) DelUsers(users []panel.UserInfo, tag string) error {
|
||||
userManager, err := c.GetUserManager(tag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get user manager error: %s", err)
|
||||
@@ -47,7 +47,7 @@ func (c *Core) DelUsers(users []panel.UserInfo, tag string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Core) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
||||
func (c *Xray) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
||||
upName := "user>>>" + format.UserTag(tag, uuid) + ">>>traffic>>>uplink"
|
||||
downName := "user>>>" + format.UserTag(tag, uuid) + ">>>traffic>>>downlink"
|
||||
upCounter := c.shm.GetCounter(upName)
|
||||
@@ -70,7 +70,7 @@ func (c *Core) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int6
|
||||
return up, down
|
||||
}
|
||||
|
||||
func (c *Core) AddUsers(p *vCore.AddUsersParams) (added int, err error) {
|
||||
func (c *Xray) AddUsers(p *vCore.AddUsersParams) (added int, err error) {
|
||||
users := make([]*protocol.User, 0, len(p.Users))
|
||||
switch p.NodeInfo.Type {
|
||||
case "vmess":
|
||||
|
||||
@@ -22,12 +22,14 @@ import (
|
||||
coreConf "github.com/xtls/xray-core/infra/conf"
|
||||
)
|
||||
|
||||
var _ vCore.Core = (*Xray)(nil)
|
||||
|
||||
func init() {
|
||||
vCore.RegisterCore("xray", New)
|
||||
}
|
||||
|
||||
// Core Structure
|
||||
type Core struct {
|
||||
// Xray Structure
|
||||
type Xray struct {
|
||||
access sync.Mutex
|
||||
Server *core.Instance
|
||||
ihm inbound.Manager
|
||||
@@ -37,7 +39,7 @@ type Core struct {
|
||||
}
|
||||
|
||||
func New(c *conf.CoreConfig) (vCore.Core, error) {
|
||||
return &Core{Server: getCore(c.XrayConfig)}, nil
|
||||
return &Xray{Server: getCore(c.XrayConfig)}, nil
|
||||
}
|
||||
|
||||
func parseConnectionConfig(c *conf.XrayConnectionConfig) (policy *coreConf.Policy) {
|
||||
@@ -137,7 +139,7 @@ func getCore(c *conf.XrayConfig) *core.Instance {
|
||||
corePolicyConfig := &coreConf.PolicyConfig{}
|
||||
corePolicyConfig.Levels = map[uint32]*coreConf.Policy{0: levelPolicyConfig}
|
||||
policyConfig, _ := corePolicyConfig.Build()
|
||||
// Build Core conf
|
||||
// Build Xray conf
|
||||
config := &core.Config{
|
||||
App: []*serial.TypedMessage{
|
||||
serial.ToTypedMessage(coreLogConfig.Build()),
|
||||
@@ -160,8 +162,8 @@ func getCore(c *conf.XrayConfig) *core.Instance {
|
||||
return server
|
||||
}
|
||||
|
||||
// Start the Core
|
||||
func (c *Core) Start() error {
|
||||
// Start the Xray
|
||||
func (c *Xray) Start() error {
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
if err := c.Server.Start(); err != nil {
|
||||
@@ -175,7 +177,7 @@ func (c *Core) Start() error {
|
||||
}
|
||||
|
||||
// Close the core
|
||||
func (c *Core) Close() error {
|
||||
func (c *Xray) Close() error {
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
c.ihm = nil
|
||||
@@ -189,7 +191,7 @@ func (c *Core) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Core) Protocols() []string {
|
||||
func (c *Xray) Protocols() []string {
|
||||
return []string{
|
||||
"vmess",
|
||||
"vless",
|
||||
@@ -198,6 +200,6 @@ func (c *Core) Protocols() []string {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Core) Type() string {
|
||||
func (c *Xray) Type() string {
|
||||
return "xray"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user