boxdd: Add insecure mode

This commit is contained in:
世界
2026-08-30 17:41:43 +08:00
parent b4600dd4f7
commit 0a4e4c8061
60 changed files with 1055 additions and 285 deletions
+8 -1
View File
@@ -9,6 +9,7 @@ import (
"encoding/json"
"net/http"
"net/url"
"os"
"reflect"
"slices"
"strings"
@@ -24,6 +25,7 @@ import (
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/filemanager"
"github.com/caddyserver/certmagic"
"github.com/caddyserver/zerossl"
@@ -78,7 +80,12 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
var storage certmagic.Storage
if options.DataDirectory != "" {
storage = &certmagic.FileStorage{Path: options.DataDirectory}
dataDirectory := filemanager.BasePath(ctx, os.ExpandEnv(options.DataDirectory))
err := filemanager.MkdirAll(ctx, dataDirectory, 0o700)
if err != nil {
return nil, E.Cause(err, "create ACME data directory")
}
storage = &certmagic.FileStorage{Path: dataDirectory}
} else {
storage = certmagic.Default.Storage
}
+9 -5
View File
@@ -74,6 +74,10 @@ func newDashboard(ctx context.Context, logger log.ContextLogger, options option.
}
func (d *dashboard) start() error {
_, err := filemanager.ReadDir(d.ctx, d.path)
if err != nil && !os.IsNotExist(err) {
return E.Cause(err, "read dashboard directory")
}
transport, err := d.resolveTransport()
if err != nil {
return E.Cause(err, "create dashboard http client")
@@ -147,7 +151,7 @@ func (d *dashboard) loopUpdate() {
}
func (d *dashboard) loadState() dashboardStatus {
entries, err := os.ReadDir(d.path)
entries, err := filemanager.ReadDir(d.ctx, d.path)
if err != nil {
return dashboardEmpty
}
@@ -155,12 +159,12 @@ func (d *dashboard) loadState() dashboardStatus {
return dashboardEmpty
}
etagPath := filepath.Join(d.path, dashboardEtagFileName)
etagBytes, err := os.ReadFile(etagPath)
etagBytes, err := filemanager.ReadFile(d.ctx, etagPath)
if err != nil {
return dashboardUserProvided
}
d.lastEtag = strings.TrimSpace(string(etagBytes))
info, err := os.Stat(etagPath)
info, err := filemanager.Stat(d.ctx, etagPath)
if err == nil {
d.lastUpdated = info.ModTime()
}
@@ -212,7 +216,7 @@ func (d *dashboard) extract(body io.Reader, etag string) error {
return err
}
tempZipPath := tempFile.Name()
defer os.Remove(tempZipPath)
defer filemanager.Remove(d.ctx, tempZipPath)
_, err = io.Copy(tempFile, body)
tempFile.Close()
if err != nil {
@@ -271,7 +275,7 @@ func (d *dashboard) extract(body io.Reader, etag string) error {
if err != nil {
return err
}
return os.Rename(tempDir, d.path)
return filemanager.Rename(d.ctx, tempDir, d.path)
}
func extractZipEntry(ctx context.Context, file *zip.File, savePath string) error {
+6 -4
View File
@@ -2,6 +2,7 @@ package ccm
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
@@ -11,6 +12,7 @@ import (
"time"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/service/filemanager"
)
const (
@@ -42,8 +44,8 @@ func getDefaultCredentialsPath() (string, error) {
return filepath.Join(userInfo.HomeDir, ".claude", ".credentials.json"), nil
}
func readCredentialsFromFile(path string) (*oauthCredentials, error) {
data, err := os.ReadFile(path)
func readCredentialsFromFile(ctx context.Context, path string) (*oauthCredentials, error) {
data, err := filemanager.ReadFile(ctx, path)
if err != nil {
return nil, err
}
@@ -60,14 +62,14 @@ func readCredentialsFromFile(path string) (*oauthCredentials, error) {
return credentialsContainer.ClaudeAIAuth, nil
}
func writeCredentialsToFile(oauthCredentials *oauthCredentials, path string) error {
func writeCredentialsToFile(ctx context.Context, oauthCredentials *oauthCredentials, path string) error {
data, err := json.MarshalIndent(map[string]any{
"claudeAiOauth": oauthCredentials,
}, "", " ")
if err != nil {
return err
}
return os.WriteFile(path, data, 0o600)
return filemanager.WriteFile(ctx, path, data, 0o600)
}
type oauthCredentials struct {
+7 -6
View File
@@ -3,6 +3,7 @@
package ccm
import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
@@ -33,9 +34,9 @@ func getKeychainServiceName() string {
return "Claude Code-credentials-" + hex.EncodeToString(hash[:])[:8]
}
func platformReadCredentials(customPath string) (*oauthCredentials, error) {
func platformReadCredentials(ctx context.Context, customPath string) (*oauthCredentials, error) {
if customPath != "" {
return readCredentialsFromFile(customPath)
return readCredentialsFromFile(ctx, customPath)
}
userInfo, err := getRealUser()
@@ -66,12 +67,12 @@ func platformReadCredentials(customPath string) (*oauthCredentials, error) {
if err != nil {
return nil, err
}
return readCredentialsFromFile(defaultPath)
return readCredentialsFromFile(ctx, defaultPath)
}
func platformWriteCredentials(oauthCredentials *oauthCredentials, customPath string) error {
func platformWriteCredentials(ctx context.Context, oauthCredentials *oauthCredentials, customPath string) error {
if customPath != "" {
return writeCredentialsToFile(oauthCredentials, customPath)
return writeCredentialsToFile(ctx, oauthCredentials, customPath)
}
userInfo, err := getRealUser()
@@ -112,5 +113,5 @@ func platformWriteCredentials(oauthCredentials *oauthCredentials, customPath str
if err != nil {
return err
}
return writeCredentialsToFile(oauthCredentials, defaultPath)
return writeCredentialsToFile(ctx, oauthCredentials, defaultPath)
}
+6 -4
View File
@@ -2,7 +2,9 @@
package ccm
func platformReadCredentials(customPath string) (*oauthCredentials, error) {
import "context"
func platformReadCredentials(ctx context.Context, customPath string) (*oauthCredentials, error) {
if customPath == "" {
var err error
customPath, err = getDefaultCredentialsPath()
@@ -10,10 +12,10 @@ func platformReadCredentials(customPath string) (*oauthCredentials, error) {
return nil, err
}
}
return readCredentialsFromFile(customPath)
return readCredentialsFromFile(ctx, customPath)
}
func platformWriteCredentials(oauthCredentials *oauthCredentials, customPath string) error {
func platformWriteCredentials(ctx context.Context, oauthCredentials *oauthCredentials, customPath string) error {
if customPath == "" {
var err error
customPath, err = getDefaultCredentialsPath()
@@ -21,5 +23,5 @@ func platformWriteCredentials(oauthCredentials *oauthCredentials, customPath str
return err
}
}
return writeCredentialsToFile(oauthCredentials, customPath)
return writeCredentialsToFile(ctx, oauthCredentials, customPath)
}
+3 -2
View File
@@ -160,6 +160,7 @@ func NewService(ctx context.Context, logger log.ContextLogger, tag string, optio
usageTracker = &AggregatedUsage{
LastUpdated: time.Now(),
Combinations: make([]CostCombination, 0),
ctx: ctx,
filePath: options.UsagesPath,
logger: logger,
}
@@ -201,7 +202,7 @@ func (s *Service) Start(stage adapter.StartStage) error {
s.userManager.UpdateUsers(s.users)
credentials, err := platformReadCredentials(s.credentialPath)
credentials, err := platformReadCredentials(s.ctx, s.credentialPath)
if err != nil {
return E.Cause(err, "read credentials")
}
@@ -271,7 +272,7 @@ func (s *Service) getAccessToken() (string, error) {
s.credentials = newCredentials
err = platformWriteCredentials(newCredentials, s.credentialPath)
err = platformWriteCredentials(s.ctx, newCredentials, s.credentialPath)
if err != nil {
s.logger.Warn("persist refreshed token: ", err)
}
+7 -4
View File
@@ -1,6 +1,7 @@
package ccm
import (
"context"
"encoding/json"
"fmt"
"math"
@@ -11,6 +12,7 @@ import (
"github.com/sagernet/sing-box/log"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/service/filemanager"
)
type UsageStats struct {
@@ -36,6 +38,7 @@ type AggregatedUsage struct {
LastUpdated time.Time `json:"last_updated"`
Combinations []CostCombination `json:"combinations"`
mutex sync.Mutex
ctx context.Context
filePath string
logger log.ContextLogger
lastSaveTime time.Time
@@ -567,7 +570,7 @@ func (u *AggregatedUsage) Load() error {
u.LastUpdated = time.Time{}
u.Combinations = nil
data, err := os.ReadFile(u.filePath)
data, err := filemanager.ReadFile(u.ctx, u.filePath)
if err != nil {
if os.IsNotExist(err) {
return nil
@@ -601,12 +604,12 @@ func (u *AggregatedUsage) Save() error {
}
tmpFile := u.filePath + ".tmp"
err = os.WriteFile(tmpFile, data, 0o644)
err = filemanager.WriteFile(u.ctx, tmpFile, data, 0o644)
if err != nil {
return err
}
defer os.Remove(tmpFile)
err = os.Rename(tmpFile, u.filePath)
defer filemanager.Remove(u.ctx, tmpFile)
err = filemanager.Rename(u.ctx, tmpFile, u.filePath)
if err == nil {
u.saveMutex.Lock()
u.lastSaveTime = time.Now()
+8 -8
View File
@@ -137,7 +137,7 @@ func NewService(ctx context.Context, logger log.ContextLogger, tag string, optio
func (d *Service) Start(stage adapter.StartStage) error {
switch stage {
case adapter.StartStateStart:
config, err := readDERPConfig(filemanager.BasePath(d.ctx, d.configPath))
config, err := readDERPConfig(d.ctx, filemanager.BasePath(d.ctx, d.configPath))
if err != nil {
return err
}
@@ -166,7 +166,7 @@ func (d *Service) Start(stage adapter.StartStage) error {
server.SetMeshKey(d.meshKey)
} else if d.meshKeyPath != "" {
var meshKeyContent []byte
meshKeyContent, err = os.ReadFile(d.meshKeyPath)
meshKeyContent, err = filemanager.ReadFile(d.ctx, d.meshKeyPath)
if err != nil {
return err
}
@@ -447,11 +447,11 @@ type derpConfig struct {
PrivateKey key.NodePrivate
}
func readDERPConfig(path string) (*derpConfig, error) {
content, err := os.ReadFile(path)
func readDERPConfig(ctx context.Context, path string) (*derpConfig, error) {
content, err := filemanager.ReadFile(ctx, path)
if err != nil {
if os.IsNotExist(err) {
return writeNewDERPConfig(path)
return writeNewDERPConfig(ctx, path)
}
return nil, err
}
@@ -463,9 +463,9 @@ func readDERPConfig(path string) (*derpConfig, error) {
return &config, nil
}
func writeNewDERPConfig(path string) (*derpConfig, error) {
func writeNewDERPConfig(ctx context.Context, path string) (*derpConfig, error) {
newKey := key.NewNode()
err := os.MkdirAll(filepath.Dir(path), 0o777)
err := filemanager.MkdirAll(ctx, filepath.Dir(path), 0o777)
if err != nil {
return nil, err
}
@@ -476,7 +476,7 @@ func writeNewDERPConfig(path string) (*derpConfig, error) {
if err != nil {
return nil, err
}
err = os.WriteFile(path, content, 0o644)
err = filemanager.WriteFile(ctx, path, content, 0o644)
if err != nil {
return nil, err
}
+6 -4
View File
@@ -2,6 +2,7 @@ package ocm
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
@@ -11,6 +12,7 @@ import (
"time"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/service/filemanager"
)
const (
@@ -42,8 +44,8 @@ func getDefaultCredentialsPath() (string, error) {
return filepath.Join(userInfo.HomeDir, ".codex", "auth.json"), nil
}
func readCredentialsFromFile(path string) (*oauthCredentials, error) {
data, err := os.ReadFile(path)
func readCredentialsFromFile(ctx context.Context, path string) (*oauthCredentials, error) {
data, err := filemanager.ReadFile(ctx, path)
if err != nil {
return nil, err
}
@@ -55,12 +57,12 @@ func readCredentialsFromFile(path string) (*oauthCredentials, error) {
return &credentials, nil
}
func writeCredentialsToFile(credentials *oauthCredentials, path string) error {
func writeCredentialsToFile(ctx context.Context, credentials *oauthCredentials, path string) error {
data, err := json.MarshalIndent(credentials, "", " ")
if err != nil {
return err
}
return os.WriteFile(path, data, 0o600)
return filemanager.WriteFile(ctx, path, data, 0o600)
}
type oauthCredentials struct {
+6 -4
View File
@@ -2,7 +2,9 @@
package ocm
func platformReadCredentials(customPath string) (*oauthCredentials, error) {
import "context"
func platformReadCredentials(ctx context.Context, customPath string) (*oauthCredentials, error) {
if customPath == "" {
var err error
customPath, err = getDefaultCredentialsPath()
@@ -10,10 +12,10 @@ func platformReadCredentials(customPath string) (*oauthCredentials, error) {
return nil, err
}
}
return readCredentialsFromFile(customPath)
return readCredentialsFromFile(ctx, customPath)
}
func platformWriteCredentials(credentials *oauthCredentials, customPath string) error {
func platformWriteCredentials(ctx context.Context, credentials *oauthCredentials, customPath string) error {
if customPath == "" {
var err error
customPath, err = getDefaultCredentialsPath()
@@ -21,5 +23,5 @@ func platformWriteCredentials(credentials *oauthCredentials, customPath string)
return err
}
}
return writeCredentialsToFile(credentials, customPath)
return writeCredentialsToFile(ctx, credentials, customPath)
}
+6 -4
View File
@@ -2,7 +2,9 @@
package ocm
func platformReadCredentials(customPath string) (*oauthCredentials, error) {
import "context"
func platformReadCredentials(ctx context.Context, customPath string) (*oauthCredentials, error) {
if customPath == "" {
var err error
customPath, err = getDefaultCredentialsPath()
@@ -10,10 +12,10 @@ func platformReadCredentials(customPath string) (*oauthCredentials, error) {
return nil, err
}
}
return readCredentialsFromFile(customPath)
return readCredentialsFromFile(ctx, customPath)
}
func platformWriteCredentials(credentials *oauthCredentials, customPath string) error {
func platformWriteCredentials(ctx context.Context, credentials *oauthCredentials, customPath string) error {
if customPath == "" {
var err error
customPath, err = getDefaultCredentialsPath()
@@ -21,5 +23,5 @@ func platformWriteCredentials(credentials *oauthCredentials, customPath string)
return err
}
}
return writeCredentialsToFile(credentials, customPath)
return writeCredentialsToFile(ctx, credentials, customPath)
}
+3 -2
View File
@@ -179,6 +179,7 @@ func NewService(ctx context.Context, logger log.ContextLogger, tag string, optio
usageTracker = &AggregatedUsage{
LastUpdated: time.Now(),
Combinations: make([]CostCombination, 0),
ctx: ctx,
filePath: options.UsagesPath,
logger: logger,
}
@@ -222,7 +223,7 @@ func (s *Service) Start(stage adapter.StartStage) error {
s.userManager.UpdateUsers(s.users)
credentials, err := platformReadCredentials(s.credentialPath)
credentials, err := platformReadCredentials(s.ctx, s.credentialPath)
if err != nil {
return E.Cause(err, "read credentials")
}
@@ -292,7 +293,7 @@ func (s *Service) getAccessToken() (string, error) {
s.credentials = newCredentials
err = platformWriteCredentials(newCredentials, s.credentialPath)
err = platformWriteCredentials(s.ctx, newCredentials, s.credentialPath)
if err != nil {
s.logger.Warn("persist refreshed token: ", err)
}
+7 -4
View File
@@ -1,6 +1,7 @@
package ocm
import (
"context"
"encoding/json"
"fmt"
"math"
@@ -12,6 +13,7 @@ import (
"github.com/sagernet/sing-box/log"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/service/filemanager"
)
type UsageStats struct {
@@ -56,6 +58,7 @@ type AggregatedUsage struct {
LastUpdated time.Time `json:"last_updated"`
Combinations []CostCombination `json:"combinations"`
mutex sync.Mutex
ctx context.Context
filePath string
logger log.ContextLogger
lastSaveTime time.Time
@@ -1072,7 +1075,7 @@ func (u *AggregatedUsage) Load() error {
u.LastUpdated = time.Time{}
u.Combinations = nil
data, err := os.ReadFile(u.filePath)
data, err := filemanager.ReadFile(u.ctx, u.filePath)
if err != nil {
if os.IsNotExist(err) {
return nil
@@ -1106,12 +1109,12 @@ func (u *AggregatedUsage) Save() error {
}
tmpFile := u.filePath + ".tmp"
err = os.WriteFile(tmpFile, data, 0o644)
err = filemanager.WriteFile(u.ctx, tmpFile, data, 0o644)
if err != nil {
return err
}
defer os.Remove(tmpFile)
err = os.Rename(tmpFile, u.filePath)
defer filemanager.Remove(u.ctx, tmpFile)
err = filemanager.Rename(u.ctx, tmpFile, u.filePath)
if err == nil {
u.saveMutex.Lock()
u.lastSaveTime = time.Now()
+9 -1
View File
@@ -18,6 +18,7 @@ import (
"io/fs"
"net"
"net/http"
"os"
"slices"
"strconv"
"strings"
@@ -33,6 +34,7 @@ import (
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/ntp"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/filemanager"
"github.com/caddyserver/certmagic"
)
@@ -109,7 +111,13 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
}
var storage certmagic.Storage
if options.DataDirectory != "" {
storage = &certmagic.FileStorage{Path: options.DataDirectory}
dataDirectory := filemanager.BasePath(ctx, os.ExpandEnv(options.DataDirectory))
mkdirErr := filemanager.MkdirAll(ctx, dataDirectory, 0o700)
if mkdirErr != nil {
cancel()
return nil, E.Cause(mkdirErr, "create data directory")
}
storage = &certmagic.FileStorage{Path: dataDirectory}
} else {
storage = certmagic.Default.Storage
}
+4 -4
View File
@@ -37,7 +37,7 @@ func (s *Service) loadCache() error {
return nil
}
basePath := filemanager.BasePath(s.ctx, s.cachePath)
cacheBinary, err := os.ReadFile(basePath)
cacheBinary, err := filemanager.ReadFile(s.ctx, basePath)
if err != nil {
if os.IsNotExist(err) {
return nil
@@ -46,7 +46,7 @@ func (s *Service) loadCache() error {
}
err = s.decodeCache(cacheBinary)
if err != nil {
os.RemoveAll(basePath)
filemanager.RemoveAll(s.ctx, basePath)
return err
}
s.cacheMutex.Lock()
@@ -73,11 +73,11 @@ func (s *Service) saveCache() error {
func (s *Service) writeCache(cacheBinary []byte) error {
basePath := filemanager.BasePath(s.ctx, s.cachePath)
err := os.MkdirAll(filepath.Dir(basePath), 0o777)
err := filemanager.MkdirAll(s.ctx, filepath.Dir(basePath), 0o777)
if err != nil {
return err
}
err = os.WriteFile(basePath, cacheBinary, 0o644)
err = filemanager.WriteFile(s.ctx, basePath, cacheBinary, 0o644)
if err != nil {
return err
}