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/option"
|
||||||
"github.com/sagernet/sing-box/protocol/direct"
|
"github.com/sagernet/sing-box/protocol/direct"
|
||||||
"github.com/sagernet/sing-box/route"
|
"github.com/sagernet/sing-box/route"
|
||||||
|
"github.com/sagernet/sing-box/service/usermanager"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
F "github.com/sagernet/sing/common/format"
|
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, "]")
|
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 {
|
for i, inboundOptions := range options.Inbounds {
|
||||||
var tag string
|
var tag string
|
||||||
if inboundOptions.Tag != "" {
|
if inboundOptions.Tag != "" {
|
||||||
|
|
@ -561,7 +575,7 @@ func (s *Box) start() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -284,24 +284,29 @@ func (h *Inbound) Start(stage adapter.StartStage) error {
|
||||||
return h.service.Start(packetConn)
|
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() {
|
func (h *Inbound) credentialLoop() {
|
||||||
|
h.syncCredentials()
|
||||||
ticker := time.NewTicker(30 * time.Second)
|
ticker := time.NewTicker(30 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
creds, err := h.userManager.GetCredentials(C.TypeHysteria2)
|
h.syncCredentials()
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -157,19 +157,24 @@ func (n *Inbound) Start(stage adapter.StartStage) error {
|
||||||
return nil
|
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() {
|
func (n *Inbound) credentialLoop() {
|
||||||
|
n.syncCredentials()
|
||||||
ticker := time.NewTicker(30 * time.Second)
|
ticker := time.NewTicker(30 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
creds, err := n.userManager.GetCredentials(C.TypeNaive)
|
n.syncCredentials()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -212,40 +212,45 @@ func (h *Inbound) Start(stage adapter.StartStage) error {
|
||||||
return h.server.Start(packetConn)
|
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() {
|
func (h *Inbound) credentialLoop() {
|
||||||
|
h.syncCredentials()
|
||||||
ticker := time.NewTicker(30 * time.Second)
|
ticker := time.NewTicker(30 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
creds, err := h.userManager.GetCredentials(C.TypeTUIC)
|
h.syncCredentials()
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||||
for i, c := range creds {
|
for i, c := range creds {
|
||||||
userIndices[i] = i
|
userIndices[i] = i
|
||||||
userUUIDs[i] = c.Credential
|
userUUIDs[i] = c.Credential
|
||||||
userFlows[i] = ""
|
userFlows[i] = "xtls-rprx-vision"
|
||||||
userNameList[i] = c.Username
|
userNameList[i] = c.Username
|
||||||
}
|
}
|
||||||
service.UpdateUsers(userIndices, userUUIDs, userFlows)
|
service.UpdateUsers(userIndices, userUUIDs, userFlows)
|
||||||
|
|
@ -171,26 +171,37 @@ func (h *Inbound) Start(stage adapter.StartStage) error {
|
||||||
return nil
|
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() {
|
func (h *Inbound) credentialLoop() {
|
||||||
|
h.syncCredentials()
|
||||||
ticker := time.NewTicker(30 * time.Second)
|
ticker := time.NewTicker(30 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
creds, err := h.userManager.GetCredentials(C.TypeVLESS)
|
h.syncCredentials()
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,8 +127,11 @@ func (m *Manager) Start(stage adapter.StartStage) error {
|
||||||
}
|
}
|
||||||
m.logger.Info("starting user manager")
|
m.logger.Info("starting user manager")
|
||||||
|
|
||||||
|
m.logger.Debug("running initial credential fetch")
|
||||||
if err := m.refreshCredentials(); err != nil {
|
if err := m.refreshCredentials(); err != nil {
|
||||||
m.logger.Warn("initial credential fetch failed: ", err)
|
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)
|
router := service.FromContext[adapter.Router](m.ctx)
|
||||||
|
|
@ -187,6 +190,10 @@ func (m *Manager) Close() error {
|
||||||
return nil
|
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) {
|
func (m *Manager) Authenticate(ctx context.Context, protocol string, credential string, addr string) (string, error) {
|
||||||
if credential == "" {
|
if credential == "" {
|
||||||
return "", E.New("empty credential")
|
return "", E.New("empty credential")
|
||||||
|
|
@ -303,6 +310,9 @@ func (m *Manager) refreshCredentials() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if m.apiSecret != "" {
|
||||||
|
httpReq.Header.Set("Authorization", "Bearer "+m.apiSecret)
|
||||||
|
}
|
||||||
resp, err := m.httpClient.Do(httpReq)
|
resp, err := m.httpClient.Do(httpReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "fetch credentials")
|
return E.Cause(err, "fetch credentials")
|
||||||
|
|
@ -556,6 +566,9 @@ func (m *Manager) reportTrafficToServer() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
httpReq.Header.Set("Content-Type", "application/json")
|
httpReq.Header.Set("Content-Type", "application/json")
|
||||||
|
if m.apiSecret != "" {
|
||||||
|
httpReq.Header.Set("Authorization", "Bearer "+m.apiSecret)
|
||||||
|
}
|
||||||
resp, err := m.httpClient.Do(httpReq)
|
resp, err := m.httpClient.Do(httpReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.logger.Warn("traffic report failed: ", err)
|
m.logger.Warn("traffic report failed: ", err)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue