fix: register user_manager in context, immediate credential sync for all protocols, fix vless flow, add Authorization header
Some checks failed
Build / Calculate version (push) Has been cancelled
Build / Build binary (push) Has been cancelled
Build / Build Darwin binaries (push) Has been cancelled
Build / Build Windows binaries (push) Has been cancelled
Build / Build Android (push) Has been cancelled
Build / Publish Android (push) Has been cancelled
Build / Build Apple clients (push) Has been cancelled
Build / Upload builds (push) Has been cancelled
Some checks failed
Build / Calculate version (push) Has been cancelled
Build / Build binary (push) Has been cancelled
Build / Build Darwin binaries (push) Has been cancelled
Build / Build Windows binaries (push) Has been cancelled
Build / Build Android (push) Has been cancelled
Build / Publish Android (push) Has been cancelled
Build / Build Apple clients (push) Has been cancelled
Build / Upload builds (push) Has been cancelled
This commit is contained in:
parent
3123c2f29a
commit
691cce1361
6 changed files with 124 additions and 71 deletions
16
box.go
16
box.go
|
|
@ -30,6 +30,7 @@ import (
|
|||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/protocol/direct"
|
||||
"github.com/sagernet/sing-box/route"
|
||||
"github.com/sagernet/sing-box/service/usermanager"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
|
|
@ -290,6 +291,19 @@ func New(options Options) (*Box, error) {
|
|||
return nil, E.Cause(err, "initialize endpoint[", i, "]")
|
||||
}
|
||||
}
|
||||
if experimentalOptions.UserManager != nil {
|
||||
userManager, err := usermanager.New(
|
||||
ctx,
|
||||
logFactory.NewLogger("service/user_manager"),
|
||||
"user_manager",
|
||||
*experimentalOptions.UserManager,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create user_manager")
|
||||
}
|
||||
service.MustRegister[adapter.UserManager](ctx, userManager)
|
||||
internalServices = append(internalServices, userManager)
|
||||
}
|
||||
for i, inboundOptions := range options.Inbounds {
|
||||
var tag string
|
||||
if inboundOptions.Tag != "" {
|
||||
|
|
@ -561,7 +575,7 @@ func (s *Box) start() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = adapter.Start(s.logger, adapter.StartStateStart, s.inbound, s.service)
|
||||
err = adapter.Start(s.logger, adapter.StartStateStart, s.service, s.inbound)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,24 +284,29 @@ func (h *Inbound) Start(stage adapter.StartStage) error {
|
|||
return h.service.Start(packetConn)
|
||||
}
|
||||
|
||||
func (h *Inbound) syncCredentials() {
|
||||
creds, err := h.userManager.GetCredentials(C.TypeHysteria2)
|
||||
if err != nil || len(creds) == 0 {
|
||||
return
|
||||
}
|
||||
userList := make([]int, len(creds))
|
||||
userNameList := make([]string, len(creds))
|
||||
userPasswordList := make([]string, len(creds))
|
||||
for i, c := range creds {
|
||||
userList[i] = i
|
||||
userNameList[i] = c.Username
|
||||
userPasswordList[i] = c.Credential
|
||||
}
|
||||
h.service.UpdateUsers(userList, userPasswordList)
|
||||
h.userNameList = userNameList
|
||||
}
|
||||
|
||||
func (h *Inbound) credentialLoop() {
|
||||
h.syncCredentials()
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
creds, err := h.userManager.GetCredentials(C.TypeHysteria2)
|
||||
if err != nil || len(creds) == 0 {
|
||||
continue
|
||||
}
|
||||
userList := make([]int, len(creds))
|
||||
userNameList := make([]string, len(creds))
|
||||
userPasswordList := make([]string, len(creds))
|
||||
for i, c := range creds {
|
||||
userList[i] = i
|
||||
userNameList[i] = c.Username
|
||||
userPasswordList[i] = c.Credential
|
||||
}
|
||||
h.service.UpdateUsers(userList, userPasswordList)
|
||||
h.userNameList = userNameList
|
||||
h.syncCredentials()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -157,19 +157,24 @@ func (n *Inbound) Start(stage adapter.StartStage) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (n *Inbound) syncCredentials() {
|
||||
creds, err := n.userManager.GetCredentials(C.TypeNaive)
|
||||
if err != nil || len(creds) == 0 {
|
||||
return
|
||||
}
|
||||
users := make([]auth.User, len(creds))
|
||||
for i, c := range creds {
|
||||
users[i] = auth.User{Username: c.Username, Password: c.Credential}
|
||||
}
|
||||
n.authenticator = auth.NewAuthenticator(users)
|
||||
}
|
||||
|
||||
func (n *Inbound) credentialLoop() {
|
||||
n.syncCredentials()
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
creds, err := n.userManager.GetCredentials(C.TypeNaive)
|
||||
if err != nil || len(creds) == 0 {
|
||||
continue
|
||||
}
|
||||
users := make([]auth.User, len(creds))
|
||||
for i, c := range creds {
|
||||
users[i] = auth.User{Username: c.Username, Password: c.Credential}
|
||||
}
|
||||
n.authenticator = auth.NewAuthenticator(users)
|
||||
n.syncCredentials()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -212,40 +212,45 @@ func (h *Inbound) Start(stage adapter.StartStage) error {
|
|||
return h.server.Start(packetConn)
|
||||
}
|
||||
|
||||
func (h *Inbound) syncCredentials() {
|
||||
creds, err := h.userManager.GetCredentials(C.TypeTUIC)
|
||||
if err != nil || len(creds) == 0 {
|
||||
return
|
||||
}
|
||||
userList := make([]int, 0, len(creds))
|
||||
userNameList := make([]string, 0, len(creds))
|
||||
userUUIDList := make([][16]byte, 0, len(creds))
|
||||
userPasswordList := make([]string, 0, len(creds))
|
||||
for i, c := range creds {
|
||||
parts := strings.SplitN(c.Credential, ":", 2)
|
||||
if len(parts) < 1 || parts[0] == "" {
|
||||
continue
|
||||
}
|
||||
userUUID, pErr := uuid.FromString(parts[0])
|
||||
if pErr != nil {
|
||||
continue
|
||||
}
|
||||
password := ""
|
||||
if len(parts) == 2 {
|
||||
password = parts[1]
|
||||
}
|
||||
userList = append(userList, i)
|
||||
userNameList = append(userNameList, c.Username)
|
||||
userUUIDList = append(userUUIDList, userUUID)
|
||||
userPasswordList = append(userPasswordList, password)
|
||||
}
|
||||
if len(userList) > 0 {
|
||||
h.server.UpdateUsers(userList, userUUIDList, userPasswordList)
|
||||
h.userNameList = userNameList
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Inbound) credentialLoop() {
|
||||
h.syncCredentials()
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
creds, err := h.userManager.GetCredentials(C.TypeTUIC)
|
||||
if err != nil || len(creds) == 0 {
|
||||
continue
|
||||
}
|
||||
userList := make([]int, 0, len(creds))
|
||||
userNameList := make([]string, 0, len(creds))
|
||||
userUUIDList := make([][16]byte, 0, len(creds))
|
||||
userPasswordList := make([]string, 0, len(creds))
|
||||
for i, c := range creds {
|
||||
parts := strings.SplitN(c.Credential, ":", 2)
|
||||
if len(parts) < 1 || parts[0] == "" {
|
||||
continue
|
||||
}
|
||||
userUUID, pErr := uuid.FromString(parts[0])
|
||||
if pErr != nil {
|
||||
continue
|
||||
}
|
||||
password := ""
|
||||
if len(parts) == 2 {
|
||||
password = parts[1]
|
||||
}
|
||||
userList = append(userList, i)
|
||||
userNameList = append(userNameList, c.Username)
|
||||
userUUIDList = append(userUUIDList, userUUID)
|
||||
userPasswordList = append(userPasswordList, password)
|
||||
}
|
||||
if len(userList) > 0 {
|
||||
h.server.UpdateUsers(userList, userUUIDList, userPasswordList)
|
||||
h.userNameList = userNameList
|
||||
}
|
||||
h.syncCredentials()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
|||
for i, c := range creds {
|
||||
userIndices[i] = i
|
||||
userUUIDs[i] = c.Credential
|
||||
userFlows[i] = ""
|
||||
userFlows[i] = "xtls-rprx-vision"
|
||||
userNameList[i] = c.Username
|
||||
}
|
||||
service.UpdateUsers(userIndices, userUUIDs, userFlows)
|
||||
|
|
@ -171,26 +171,37 @@ func (h *Inbound) Start(stage adapter.StartStage) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (h *Inbound) syncCredentials() {
|
||||
creds, err := h.userManager.GetCredentials(C.TypeVLESS)
|
||||
if err != nil {
|
||||
h.logger.Warn("syncCredentials: GetCredentials error: ", err)
|
||||
return
|
||||
}
|
||||
if len(creds) == 0 {
|
||||
h.logger.Warn("syncCredentials: no vless credentials yet")
|
||||
return
|
||||
}
|
||||
h.logger.Info("syncCredentials: loaded ", len(creds), " vless users")
|
||||
userIndices := make([]int, len(creds))
|
||||
userUUIDs := make([]string, len(creds))
|
||||
userFlows := make([]string, len(creds))
|
||||
userNameList := make([]string, len(creds))
|
||||
for i, c := range creds {
|
||||
userIndices[i] = i
|
||||
userUUIDs[i] = c.Credential
|
||||
userFlows[i] = "xtls-rprx-vision"
|
||||
userNameList[i] = c.Username
|
||||
}
|
||||
h.service.UpdateUsers(userIndices, userUUIDs, userFlows)
|
||||
h.userNameList = userNameList
|
||||
}
|
||||
|
||||
func (h *Inbound) credentialLoop() {
|
||||
h.syncCredentials()
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
creds, err := h.userManager.GetCredentials(C.TypeVLESS)
|
||||
if err != nil || len(creds) == 0 {
|
||||
continue
|
||||
}
|
||||
userIndices := make([]int, len(creds))
|
||||
userUUIDs := make([]string, len(creds))
|
||||
userFlows := make([]string, len(creds))
|
||||
userNameList := make([]string, len(creds))
|
||||
for i, c := range creds {
|
||||
userIndices[i] = i
|
||||
userUUIDs[i] = c.Credential
|
||||
userFlows[i] = ""
|
||||
userNameList[i] = c.Username
|
||||
}
|
||||
h.service.UpdateUsers(userIndices, userUUIDs, userFlows)
|
||||
h.userNameList = userNameList
|
||||
h.syncCredentials()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -127,8 +127,11 @@ func (m *Manager) Start(stage adapter.StartStage) error {
|
|||
}
|
||||
m.logger.Info("starting user manager")
|
||||
|
||||
m.logger.Debug("running initial credential fetch")
|
||||
if err := m.refreshCredentials(); err != nil {
|
||||
m.logger.Warn("initial credential fetch failed: ", err)
|
||||
} else {
|
||||
m.logger.Debug("initial credential fetch succeeded, protocols=", len(m.protocolUsers))
|
||||
}
|
||||
|
||||
router := service.FromContext[adapter.Router](m.ctx)
|
||||
|
|
@ -187,6 +190,10 @@ func (m *Manager) Close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) Name() string {
|
||||
return "user_manager[" + m.Tag() + "]"
|
||||
}
|
||||
|
||||
func (m *Manager) Authenticate(ctx context.Context, protocol string, credential string, addr string) (string, error) {
|
||||
if credential == "" {
|
||||
return "", E.New("empty credential")
|
||||
|
|
@ -303,6 +310,9 @@ func (m *Manager) refreshCredentials() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if m.apiSecret != "" {
|
||||
httpReq.Header.Set("Authorization", "Bearer "+m.apiSecret)
|
||||
}
|
||||
resp, err := m.httpClient.Do(httpReq)
|
||||
if err != nil {
|
||||
return E.Cause(err, "fetch credentials")
|
||||
|
|
@ -556,6 +566,9 @@ func (m *Manager) reportTrafficToServer() {
|
|||
return
|
||||
}
|
||||
httpReq.Header.Set("Content-Type", "application/json")
|
||||
if m.apiSecret != "" {
|
||||
httpReq.Header.Set("Authorization", "Bearer "+m.apiSecret)
|
||||
}
|
||||
resp, err := m.httpClient.Do(httpReq)
|
||||
if err != nil {
|
||||
m.logger.Warn("traffic report failed: ", err)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue