package mtproxy import ( "context" "net" "github.com/dolonet/mtg-multi/antireplay" "github.com/dolonet/mtg-multi/events" "github.com/dolonet/mtg-multi/mtglib" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter/inbound" "github.com/sagernet/sing-box/common/listener" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/logger" N "github.com/sagernet/sing/common/network" ) func RegisterInbound(registry *inbound.Registry) { inbound.Register[option.MTProxyInboundOptions](registry, C.TypeMTProxy, NewInbound) } type Inbound struct { inbound.Adapter ctx context.Context router adapter.ConnectionRouterEx logger logger.ContextLogger listener *listener.Listener proxy *mtglib.Proxy } func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.MTProxyInboundOptions) (adapter.Inbound, error) { inbound := &Inbound{ Adapter: inbound.NewAdapter(C.TypeMTProxy, tag), ctx: ctx, router: router, logger: logger, listener: listener.New(listener.Options{ Context: ctx, Logger: logger, Listen: options.ListenOptions, }), } mtgLogger := NewLoggerAdapter(logger) secrets := make(map[string]mtglib.Secret, len(options.Users)) for _, user := range options.Users { secret := mtglib.Secret{} err := secret.Set(user.Secret) if err != nil { return nil, err } secrets[user.Name] = secret } opts := mtglib.ProxyOpts{ Logger: mtgLogger, Network: NewNetworkAdapter(ctx, NewDialer(inbound.newConnection)), AntiReplayCache: antireplay.NewNoop(), EventStream: events.NewNoopStream(), Secrets: secrets, Concurrency: options.GetConcurrency(), DomainFrontingPort: options.GetDomainFrontingPort(), DomainFrontingIP: options.DomainFrontingIP, DomainFrontingProxyProtocol: options.DomainFrontingProxyProtocol, PreferIP: options.GetPreferIP(), AutoUpdate: options.AutoUpdate, AllowFallbackOnUnknownDC: options.AllowFallbackOnUnknownDC, TolerateTimeSkewness: options.TolerateTimeSkewness.Build(), IdleTimeout: options.GetIdleTimeout(), HandshakeTimeout: options.GetHandshakeTimeout(), DoppelGangerURLs: options.DoppelGangerURLs, DoppelGangerPerRaid: options.GetDoppelGangerPerRaid(), DoppelGangerEach: options.GetDoppelGangerEach(), DoppelGangerDRS: options.DoppelGangerDRS, ThrottleMaxConnections: options.ThrottleMaxConnections, ThrottleCheckInterval: options.GetThrottleCheckInterval(), } proxy, err := mtglib.NewProxy(opts) if err != nil { return nil, E.New("cannot create a proxy: ", err) } inbound.proxy = proxy return inbound, nil } func (n *Inbound) Start(stage adapter.StartStage) error { if stage != adapter.StartStateStart { return nil } listener, err := n.listener.ListenTCP() if err != nil { return err } go n.proxy.Serve(listener) return nil } func (n *Inbound) Close() error { n.proxy.Shutdown() return common.Close( &n.listener, ) } func (h *Inbound) UpdateUsers(users []option.MTProxyUser) { secrets := make(map[string]mtglib.Secret, len(users)) for _, user := range users { secret := mtglib.Secret{} err := secret.Set(user.Secret) if err != nil { return } secrets[user.Name] = secret } h.proxy.UpdateUsers(secrets) } func (h *Inbound) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { metadata.Inbound = h.Tag() metadata.InboundType = h.Type() h.logger.InfoContext(ctx, "[", metadata.User, "] inbound connection to ", metadata.Destination) h.router.RouteConnectionEx(ctx, conn, metadata, onClose) }