Add MTProxy, MASQUE, VPN, Link parser. Update AmneziaWG. Remove Tunneling

This commit is contained in:
Sergei Maklagin
2026-04-29 22:11:30 +03:00
parent 09f9f114aa
commit 04908a6a67
158 changed files with 7994 additions and 2277 deletions

View File

@@ -0,0 +1,38 @@
package mtproxy
import (
"context"
"net"
"github.com/sagernet/sing-box/adapter"
M "github.com/sagernet/sing/common/metadata"
)
type Dialer struct {
handler adapter.ConnectionHandlerFuncEx
}
func NewDialer(handler adapter.ConnectionHandlerFuncEx) *Dialer {
return &Dialer{handler}
}
func (d *Dialer) Dial(network, address string) (net.Conn, error) {
return d.DialContext(context.Background(), network, address)
}
func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
inConn, outConn := net.Pipe()
var metadata adapter.InboundContext
if streamContext, ok := ctx.(streamContext); ok {
metadata.Source = M.SocksaddrFromNet(streamContext.ClientAddr())
metadata.User = streamContext.SecretName()
}
metadata.Destination = M.ParseSocksaddr(address)
d.handler(ctx, inConn, metadata, func(error) {})
return outConn, nil
}
type streamContext interface {
ClientAddr() net.Addr
SecretName() string
}

132
protocol/mtproxy/inbound.go Normal file
View File

@@ -0,0 +1,132 @@
package mtproxy
import (
"context"
"net"
"github.com/dolonet/mtg-multi/antireplay"
"github.com/dolonet/mtg-multi/events"
"github.com/dolonet/mtg-multi/ipblocklist"
"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(),
IPBlocklist: ipblocklist.NewNoop(),
IPAllowlist: ipblocklist.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)
}

View File

@@ -0,0 +1,60 @@
package mtproxy
import (
"fmt"
"github.com/dolonet/mtg-multi/mtglib"
"github.com/sagernet/sing/common/logger"
)
type LoggerAdapter struct {
logger logger.Logger
}
func NewLoggerAdapter(logger logger.Logger) *LoggerAdapter {
return &LoggerAdapter{logger}
}
func (l *LoggerAdapter) Named(name string) mtglib.Logger {
return l
}
func (l *LoggerAdapter) BindInt(name string, value int) mtglib.Logger {
return l
}
func (l *LoggerAdapter) BindStr(name, value string) mtglib.Logger {
return l
}
func (l *LoggerAdapter) BindJSON(name, value string) mtglib.Logger {
return l
}
func (l *LoggerAdapter) Printf(format string, args ...any) {
l.logger.Info(fmt.Sprintf(format, args...))
}
func (l *LoggerAdapter) Info(msg string) {
l.logger.Info(msg)
}
func (l *LoggerAdapter) InfoError(msg string, err error) {
l.logger.Error(msg, err)
}
func (l *LoggerAdapter) Warning(msg string) {
l.logger.Warn(msg)
}
func (l *LoggerAdapter) WarningError(msg string, err error) {
l.logger.Warn(msg, err)
}
func (l *LoggerAdapter) Debug(msg string) {
l.logger.Debug(msg)
}
func (l *LoggerAdapter) DebugError(msg string, err error) {
l.logger.Debug(msg, err)
}

View File

@@ -0,0 +1,43 @@
package mtproxy
import (
"context"
"net"
"net/http"
"github.com/dolonet/mtg-multi/essentials"
)
type NetworkAdapter struct {
ctx context.Context
dialer essentials.Dialer
}
func NewNetworkAdapter(ctx context.Context, dialer essentials.Dialer) *NetworkAdapter {
return &NetworkAdapter{ctx, dialer}
}
func (a *NetworkAdapter) Dial(network, address string) (essentials.Conn, error) {
return a.DialContext(a.ctx, network, address)
}
func (a *NetworkAdapter) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
conn, err := a.dialer.DialContext(ctx, network, address)
if err != nil {
return nil, err
}
return essentials.WrapNetConn(conn), nil
}
func (a *NetworkAdapter) MakeHTTPClient(func(ctx context.Context, network, address string) (essentials.Conn, error)) *http.Client {
return &http.Client{
Timeout: 10,
Transport: &http.Transport{DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
return a.DialContext(ctx, network, addr)
}},
}
}
func (a *NetworkAdapter) NativeDialer() essentials.Dialer {
return a.dialer
}