mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-05-14 00:51:12 +03:00
Add MTProxy, MASQUE, VPN, Link parser. Update AmneziaWG. Remove Tunneling
This commit is contained in:
@@ -77,6 +77,7 @@ func UserTableFactory(manager CM.Manager, logger log.Logger) func(ctx *context.C
|
||||
Options: types.FieldOptions{
|
||||
{Text: "Hysteria", Value: "hysteria"},
|
||||
{Text: "Hysteria2", Value: "hysteria2"},
|
||||
{Text: "MTProxy", Value: "mtproxy"},
|
||||
{Text: "Trojan", Value: "trojan"},
|
||||
{Text: "TUIC", Value: "tuic"},
|
||||
{Text: "VLESS", Value: "vless"},
|
||||
@@ -183,16 +184,18 @@ func UserTableFactory(manager CM.Manager, logger log.Logger) func(ctx *context.C
|
||||
FieldOptions(types.FieldOptions{
|
||||
{Text: "Hysteria", Value: "hysteria"},
|
||||
{Text: "Hysteria2", Value: "hysteria2"},
|
||||
{Text: "MTProxy", Value: "mtproxy"},
|
||||
{Text: "Trojan", Value: "trojan"},
|
||||
{Text: "TUIC", Value: "tuic"},
|
||||
{Text: "VLESS", Value: "vless"},
|
||||
{Text: "VMess", Value: "vmess"},
|
||||
}).
|
||||
FieldOnChooseOptionsHide([]string{""}, "inbound").
|
||||
FieldOnChooseOptionsHide([]string{"", "hysteria", "hysteria2", "shadowsocks", "trojan", "tuic"}, "uuid").
|
||||
FieldOnChooseOptionsHide([]string{"", "vless", "vmess"}, "password").
|
||||
FieldOnChooseOptionsHide([]string{"", "hysteria", "hysteria2", "shadowsocks", "trojan", "tuic", "vmess"}, "flow").
|
||||
FieldOnChooseOptionsHide([]string{"", "hysteria", "hysteria2", "shadowsocks", "trojan", "tuic", "vless"}, "alter_id")
|
||||
FieldOnChooseOptionsHide([]string{"", "hysteria", "hysteria2", "mtproxy", "shadowsocks", "trojan", "tuic"}, "uuid").
|
||||
FieldOnChooseOptionsHide([]string{"", "mtproxy", "vless", "vmess"}, "password").
|
||||
FieldOnChooseOptionsHide([]string{"", "hysteria", "hysteria2", "shadowsocks", "trojan", "tuic", "vless", "vmess"}, "secret").
|
||||
FieldOnChooseOptionsHide([]string{"", "hysteria", "hysteria2", "mtproxy", "shadowsocks", "trojan", "tuic", "vmess"}, "flow").
|
||||
FieldOnChooseOptionsHide([]string{"", "hysteria", "hysteria2", "mtproxy", "shadowsocks", "trojan", "tuic", "vless"}, "alter_id")
|
||||
formList.AddField("Inbound", "inbound", db.Varchar, form.Text).
|
||||
FieldMust().
|
||||
FieldDisplayButCanNotEditWhenUpdate().
|
||||
@@ -203,6 +206,7 @@ func UserTableFactory(manager CM.Manager, logger log.Logger) func(ctx *context.C
|
||||
})
|
||||
formList.AddField("UUID", "uuid", db.Varchar, form.Text)
|
||||
formList.AddField("Password", "password", db.Varchar, form.Text)
|
||||
formList.AddField("Secret", "secret", db.Varchar, form.Text)
|
||||
formList.AddField("Flow", "flow", db.Varchar, form.SelectSingle).
|
||||
FieldOptions(types.FieldOptions{
|
||||
{Text: "xtls-rprx-vision", Value: "xtls-rprx-vision"},
|
||||
@@ -233,6 +237,7 @@ func UserTableFactory(manager CM.Manager, logger log.Logger) func(ctx *context.C
|
||||
Inbound: values.Get("inbound"),
|
||||
UUID: values.Get("uuid"),
|
||||
Password: values.Get("password"),
|
||||
Secret: values.Get("secret"),
|
||||
Flow: values.Get("flow"),
|
||||
AlterID: alterId,
|
||||
})
|
||||
@@ -269,6 +274,7 @@ func UserTableFactory(manager CM.Manager, logger log.Logger) func(ctx *context.C
|
||||
_, err = manager.UpdateUser(id, CM.UserUpdate{
|
||||
UUID: values.Get("uuid"),
|
||||
Password: values.Get("password"),
|
||||
Secret: values.Get("secret"),
|
||||
Flow: values.Get("flow"),
|
||||
AlterID: alterId,
|
||||
})
|
||||
|
||||
@@ -48,6 +48,7 @@ type User struct {
|
||||
Inbound string `json:"inbound" validate:"required"`
|
||||
UUID string `json:"uuid" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Secret string `json:"secret" validate:"required"`
|
||||
Flow string `json:"flow" validate:"required"`
|
||||
AlterID int `json:"alter_id" validate:"required"`
|
||||
CreatedAt time.Time `json:"created_at" validate:"required"`
|
||||
@@ -57,10 +58,11 @@ type User struct {
|
||||
type UserCreate struct {
|
||||
SquadIDs []int `json:"squad_ids" validate:"required"`
|
||||
Username string `json:"username" validate:"required"`
|
||||
Type string `json:"type" validate:"required,oneof=hysteria hysteria2 trojan tuic vless vmess"`
|
||||
Type string `json:"type" validate:"required,oneof=hysteria hysteria2 mtproxy trojan tuic vless vmess"`
|
||||
Inbound string `json:"inbound" validate:"required"`
|
||||
UUID string `json:"uuid" validate:"omitempty,uuid4"`
|
||||
Password string `json:"password" validate:"omitempty"`
|
||||
Secret string `json:"secret" validate:"omitempty"`
|
||||
Flow string `json:"flow" validate:"omitempty"`
|
||||
AlterID int `json:"alter_id" validate:"omitempty"`
|
||||
}
|
||||
@@ -68,6 +70,7 @@ type UserCreate struct {
|
||||
type UserUpdate struct {
|
||||
UUID string `json:"uuid" validate:"omitempty,uuid4"`
|
||||
Password string `json:"password" validate:"omitempty"`
|
||||
Secret string `json:"secret" validate:"omitempty"`
|
||||
Flow string `json:"flow" validate:"omitempty"`
|
||||
AlterID int `json:"alter_id" validate:"omitempty"`
|
||||
}
|
||||
@@ -75,6 +78,7 @@ type UserUpdate struct {
|
||||
type BaseUser struct {
|
||||
UUID string `json:"uuid" validate:"omitempty,uuid4"`
|
||||
Password string `json:"password" validate:"omitempty"`
|
||||
Secret string `json:"secret" validate:"omitempty"`
|
||||
Flow string `json:"flow" validate:"omitempty"`
|
||||
AlterID int `json:"alter_id" validate:"omitempty"`
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ var migrations = map[string]string{
|
||||
inbound TEXT NOT NULL,
|
||||
uuid TEXT NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
secret TEXT NOT NULL,
|
||||
flow TEXT NOT NULL,
|
||||
alter_id INTEGER NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL,
|
||||
|
||||
@@ -391,12 +391,13 @@ func (r *PostgreSQLRepository) CreateUser(user constant.UserCreate) (constant.Us
|
||||
inbound,
|
||||
uuid,
|
||||
password,
|
||||
secret,
|
||||
flow,
|
||||
alter_id,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||
RETURNING
|
||||
id,
|
||||
username,
|
||||
@@ -404,6 +405,7 @@ func (r *PostgreSQLRepository) CreateUser(user constant.UserCreate) (constant.Us
|
||||
inbound,
|
||||
uuid,
|
||||
password,
|
||||
secret,
|
||||
flow,
|
||||
alter_id,
|
||||
created_at,
|
||||
@@ -414,6 +416,7 @@ func (r *PostgreSQLRepository) CreateUser(user constant.UserCreate) (constant.Us
|
||||
user.Inbound,
|
||||
user.UUID,
|
||||
user.Password,
|
||||
user.Secret,
|
||||
user.Flow,
|
||||
user.AlterID,
|
||||
now,
|
||||
@@ -425,11 +428,15 @@ func (r *PostgreSQLRepository) CreateUser(user constant.UserCreate) (constant.Us
|
||||
&u.Inbound,
|
||||
&u.UUID,
|
||||
&u.Password,
|
||||
&u.Secret,
|
||||
&u.Flow,
|
||||
&u.AlterID,
|
||||
&u.CreatedAt,
|
||||
&u.UpdatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
rows := make([][]any, len(user.SquadIDs))
|
||||
for i, squadID := range user.SquadIDs {
|
||||
rows[i] = []any{u.ID, squadID}
|
||||
@@ -465,6 +472,7 @@ func (r *PostgreSQLRepository) GetUsers(filters map[string][]string) ([]constant
|
||||
"inbound",
|
||||
"uuid",
|
||||
"password",
|
||||
"secret",
|
||||
"flow",
|
||||
"alter_id",
|
||||
"created_at",
|
||||
@@ -495,6 +503,7 @@ func (r *PostgreSQLRepository) GetUsers(filters map[string][]string) ([]constant
|
||||
&u.Inbound,
|
||||
&u.UUID,
|
||||
&u.Password,
|
||||
&u.Secret,
|
||||
&u.Flow,
|
||||
&u.AlterID,
|
||||
&u.CreatedAt,
|
||||
@@ -539,6 +548,7 @@ func (r *PostgreSQLRepository) GetUser(id int) (constant.User, error) {
|
||||
inbound,
|
||||
uuid,
|
||||
password,
|
||||
secret,
|
||||
flow,
|
||||
alter_id,
|
||||
created_at,
|
||||
@@ -553,6 +563,7 @@ func (r *PostgreSQLRepository) GetUser(id int) (constant.User, error) {
|
||||
&u.Inbound,
|
||||
&u.UUID,
|
||||
&u.Password,
|
||||
&u.Secret,
|
||||
&u.Flow,
|
||||
&u.AlterID,
|
||||
&u.CreatedAt,
|
||||
@@ -568,10 +579,11 @@ func (r *PostgreSQLRepository) UpdateUser(id int, user constant.UserUpdate) (con
|
||||
SET
|
||||
uuid = $1,
|
||||
password = $2,
|
||||
flow = $3,
|
||||
alter_id = $4,
|
||||
updated_at = $5
|
||||
WHERE id = $6
|
||||
secret = $3,
|
||||
flow = $4,
|
||||
alter_id = $5,
|
||||
updated_at = $6
|
||||
WHERE id = $7
|
||||
RETURNING
|
||||
id,
|
||||
ARRAY(
|
||||
@@ -584,6 +596,7 @@ func (r *PostgreSQLRepository) UpdateUser(id int, user constant.UserUpdate) (con
|
||||
inbound,
|
||||
uuid,
|
||||
password,
|
||||
secret,
|
||||
flow,
|
||||
alter_id,
|
||||
created_at,
|
||||
@@ -591,6 +604,7 @@ func (r *PostgreSQLRepository) UpdateUser(id int, user constant.UserUpdate) (con
|
||||
`,
|
||||
user.UUID,
|
||||
user.Password,
|
||||
user.Secret,
|
||||
user.Flow,
|
||||
user.AlterID,
|
||||
time.Now(),
|
||||
@@ -603,6 +617,7 @@ func (r *PostgreSQLRepository) UpdateUser(id int, user constant.UserUpdate) (con
|
||||
&u.Inbound,
|
||||
&u.UUID,
|
||||
&u.Password,
|
||||
&u.Secret,
|
||||
&u.Flow,
|
||||
&u.AlterID,
|
||||
&u.CreatedAt,
|
||||
@@ -628,6 +643,7 @@ func (r *PostgreSQLRepository) DeleteUser(id int) (constant.User, error) {
|
||||
inbound,
|
||||
uuid,
|
||||
password,
|
||||
secret,
|
||||
flow,
|
||||
alter_id,
|
||||
created_at,
|
||||
@@ -640,6 +656,7 @@ func (r *PostgreSQLRepository) DeleteUser(id int) (constant.User, error) {
|
||||
&u.Inbound,
|
||||
&u.UUID,
|
||||
&u.Password,
|
||||
&u.Secret,
|
||||
&u.Flow,
|
||||
&u.AlterID,
|
||||
&u.CreatedAt,
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofrs/uuid/v5"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"github.com/patrickmn/go-cache/v2"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
boxService "github.com/sagernet/sing-box/adapter/service"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
@@ -32,7 +32,7 @@ type Service struct {
|
||||
repository constant.Repository
|
||||
nodes map[string]constant.ConnectedNode
|
||||
|
||||
limiterLocks map[int]map[string]*cache.Cache
|
||||
limiterLocks map[int]map[string]*cache.Cache[string, struct{}]
|
||||
|
||||
userValidator *validator.Validate
|
||||
defaultValidator *validator.Validate
|
||||
@@ -79,6 +79,10 @@ func NewService(ctx context.Context, logger log.ContextLogger, tag string, optio
|
||||
if user.Password == "" {
|
||||
sl.ReportError(user.Password, "password", "Password", "required", "")
|
||||
}
|
||||
case "mtproxy":
|
||||
if user.Secret == "" {
|
||||
sl.ReportError(user.Secret, "secret", "Secret", "required", "")
|
||||
}
|
||||
}
|
||||
}, constant.UserCreate{})
|
||||
return &Service{
|
||||
@@ -87,7 +91,7 @@ func NewService(ctx context.Context, logger log.ContextLogger, tag string, optio
|
||||
logger: logger,
|
||||
repository: repository,
|
||||
nodes: make(map[string]constant.ConnectedNode, 0),
|
||||
limiterLocks: make(map[int]map[string]*cache.Cache),
|
||||
limiterLocks: make(map[int]map[string]*cache.Cache[string, struct{}]),
|
||||
userValidator: userValidator,
|
||||
defaultValidator: validator.New(),
|
||||
}, nil
|
||||
@@ -519,7 +523,7 @@ func (s *Service) AcquireLock(limiterId int, id string) (string, error) {
|
||||
}
|
||||
locks, ok := s.limiterLocks[limiterId]
|
||||
if !ok {
|
||||
locks = make(map[string]*cache.Cache)
|
||||
locks = make(map[string]*cache.Cache[string, struct{}])
|
||||
s.limiterLocks[limiter.ID] = locks
|
||||
}
|
||||
lock, ok := locks[id]
|
||||
@@ -527,8 +531,8 @@ func (s *Service) AcquireLock(limiterId int, id string) (string, error) {
|
||||
if len(locks) == int(limiter.Count) {
|
||||
return "", E.New("not enough free locks")
|
||||
}
|
||||
lock = cache.New(time.Second*30, time.Second)
|
||||
lock.OnEvicted(func(_ string, _ interface{}) {
|
||||
lock = cache.New[string, struct{}](time.Second*30, time.Second)
|
||||
lock.OnEvicted(func(_ string, _ struct{}) {
|
||||
s.connLockMtx.Lock()
|
||||
defer s.connLockMtx.Unlock()
|
||||
if lock.ItemCount() == 0 {
|
||||
@@ -541,7 +545,7 @@ func (s *Service) AcquireLock(limiterId int, id string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
lock.SetDefault(handleID.String(), new(struct{}))
|
||||
lock.SetDefault(handleID.String(), struct{}{})
|
||||
return handleID.String(), nil
|
||||
}
|
||||
|
||||
@@ -556,7 +560,7 @@ func (s *Service) RefreshLock(limiterId int, id string, handleId string) error {
|
||||
if !ok {
|
||||
return E.New("lock not found")
|
||||
}
|
||||
err := lock.Replace(handleId, new(struct{}), time.Second*30)
|
||||
err := lock.Replace(handleId, struct{}{}, time.Second*30)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
88
service/node/inbound/mtproxy.go
Normal file
88
service/node/inbound/mtproxy.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package inbound
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/protocol/mtproxy"
|
||||
CM "github.com/sagernet/sing-box/service/manager/constant"
|
||||
"github.com/sagernet/sing-box/service/node/constant"
|
||||
)
|
||||
|
||||
type MTProxyManager struct {
|
||||
access sync.Mutex
|
||||
inbounds map[string]*MTProxyUserManager
|
||||
}
|
||||
|
||||
func NewMTProxyManager() *MTProxyManager {
|
||||
return &MTProxyManager{
|
||||
inbounds: make(map[string]*MTProxyUserManager),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MTProxyManager) AddUserManager(inbound adapter.Inbound) error {
|
||||
m.access.Lock()
|
||||
defer m.access.Unlock()
|
||||
m.inbounds[inbound.Tag()] = &MTProxyUserManager{
|
||||
inbound: inbound.(*mtproxy.Inbound),
|
||||
usersMap: make(map[string]option.MTProxyUser),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MTProxyManager) GetUserManager(tag string) (constant.UserManager, bool) {
|
||||
m.access.Lock()
|
||||
defer m.access.Unlock()
|
||||
inbound, ok := m.inbounds[tag]
|
||||
return inbound, ok
|
||||
}
|
||||
|
||||
func (m *MTProxyManager) GetUserManagerTags() []string {
|
||||
m.access.Lock()
|
||||
defer m.access.Unlock()
|
||||
tags := make([]string, 0, len(m.inbounds))
|
||||
for tag, _ := range m.inbounds {
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
type MTProxyUserManager struct {
|
||||
inbound *mtproxy.Inbound
|
||||
usersMap map[string]option.MTProxyUser
|
||||
|
||||
mtx sync.Mutex
|
||||
}
|
||||
|
||||
func (i *MTProxyUserManager) postUpdate() {
|
||||
users := make([]option.MTProxyUser, 0, len(i.usersMap))
|
||||
for _, user := range i.usersMap {
|
||||
users = append(users, user)
|
||||
}
|
||||
i.inbound.UpdateUsers(users)
|
||||
}
|
||||
|
||||
func (i *MTProxyUserManager) UpdateUser(user CM.User) {
|
||||
i.mtx.Lock()
|
||||
defer i.mtx.Unlock()
|
||||
i.usersMap[user.Username] = option.MTProxyUser{Name: user.Username, Secret: user.Secret}
|
||||
i.postUpdate()
|
||||
}
|
||||
|
||||
func (i *MTProxyUserManager) UpdateUsers(users []CM.User) {
|
||||
i.mtx.Lock()
|
||||
defer i.mtx.Unlock()
|
||||
clear(i.usersMap)
|
||||
for _, user := range users {
|
||||
i.usersMap[user.Username] = option.MTProxyUser{Name: user.Username, Secret: user.Secret}
|
||||
}
|
||||
i.postUpdate()
|
||||
}
|
||||
|
||||
func (i *MTProxyUserManager) DeleteUser(username string) {
|
||||
i.mtx.Lock()
|
||||
defer i.mtx.Unlock()
|
||||
delete(i.usersMap, username)
|
||||
i.postUpdate()
|
||||
}
|
||||
Reference in New Issue
Block a user