mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-13 21:54:13 +08:00
feat: add tls support for clash external controller api && v2ray gRPC api
This commit is contained in:
parent
3ae595dc12
commit
b25107e6aa
2
box.go
2
box.go
@ -176,7 +176,7 @@ func New(options Options) (*Box, error) {
|
||||
preServices2["clash api"] = clashServer
|
||||
}
|
||||
if needV2RayAPI {
|
||||
v2rayServer, err := experimental.NewV2RayServer(logFactory.NewLogger("v2ray-api"), common.PtrValueOrDefault(experimentalOptions.V2RayAPI))
|
||||
v2rayServer, err := experimental.NewV2RayServer(ctx, logFactory.NewLogger("v2ray-api"), common.PtrValueOrDefault(experimentalOptions.V2RayAPI))
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create v2ray api server")
|
||||
}
|
||||
|
58
common/tls/listener.go
Normal file
58
common/tls/listener.go
Normal file
@ -0,0 +1,58 @@
|
||||
package tls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/sing/common/tls"
|
||||
)
|
||||
|
||||
var _ net.Listener = (*Listener)(nil)
|
||||
|
||||
type Listener struct {
|
||||
ctx context.Context
|
||||
l net.Listener
|
||||
tls tls.ServerConfig
|
||||
}
|
||||
|
||||
func (t *Listener) Addr() net.Addr {
|
||||
return t.l.Addr()
|
||||
}
|
||||
|
||||
func (t *Listener) Accept() (net.Conn, error) {
|
||||
if t.tls == nil {
|
||||
return t.l.Accept()
|
||||
}
|
||||
for {
|
||||
conn, err := t.l.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn, err = tls.ServerHandshake(t.ctx, conn, t.tls)
|
||||
if err == nil {
|
||||
return conn, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Listener) Close() error {
|
||||
if err := t.l.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
if t.tls != nil {
|
||||
return t.tls.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewListener(ctx context.Context, address string, config ServerConfig) (net.Listener, error) {
|
||||
l, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Listener{
|
||||
ctx: ctx,
|
||||
l: l,
|
||||
tls: config,
|
||||
}, nil
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
"external_ui_download_detour": "",
|
||||
"secret": "",
|
||||
"default_mode": "",
|
||||
"tls": {},
|
||||
|
||||
// Deprecated
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
"external_ui_download_detour": "",
|
||||
"secret": "",
|
||||
"default_mode": "",
|
||||
"tls": {},
|
||||
|
||||
// Deprecated
|
||||
|
||||
|
@ -19,7 +19,8 @@
|
||||
"users": [
|
||||
"sekai"
|
||||
]
|
||||
}
|
||||
},
|
||||
"tls": {}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -19,7 +19,8 @@
|
||||
"users": [
|
||||
"sekai"
|
||||
]
|
||||
}
|
||||
},
|
||||
"tls": {}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/tls"
|
||||
"github.com/sagernet/sing-box/common/urltest"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/experimental"
|
||||
@ -47,6 +48,7 @@ type Server struct {
|
||||
mode string
|
||||
modeList []string
|
||||
modeUpdateHook chan<- struct{}
|
||||
tlsConfig tls.ServerConfig
|
||||
|
||||
externalController bool
|
||||
externalUI string
|
||||
@ -124,6 +126,13 @@ func NewServer(ctx context.Context, router adapter.Router, logFactory log.Observ
|
||||
})
|
||||
})
|
||||
}
|
||||
if options.TLS != nil {
|
||||
tlsConfig, err := tls.NewServer(ctx, server.logger, common.PtrValueOrDefault(options.TLS))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
server.tlsConfig = tlsConfig
|
||||
}
|
||||
return server, nil
|
||||
}
|
||||
|
||||
@ -141,9 +150,15 @@ func (s *Server) PreStart() error {
|
||||
}
|
||||
|
||||
func (s *Server) Start() error {
|
||||
if s.tlsConfig != nil {
|
||||
err := s.tlsConfig.Start()
|
||||
if err != nil {
|
||||
return E.Cause(err, "create TLS config")
|
||||
}
|
||||
}
|
||||
if s.externalController {
|
||||
s.checkAndDownloadExternalUI()
|
||||
listener, err := net.Listen("tcp", s.httpServer.Addr)
|
||||
listener, err := tls.NewListener(s.ctx, s.httpServer.Addr, s.tlsConfig)
|
||||
if err != nil {
|
||||
return E.Cause(err, "external controller listen error")
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package experimental
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@ -8,7 +9,7 @@ import (
|
||||
"github.com/sagernet/sing-box/option"
|
||||
)
|
||||
|
||||
type V2RayServerConstructor = func(logger log.Logger, options option.V2RayAPIOptions) (adapter.V2RayServer, error)
|
||||
type V2RayServerConstructor = func(ctx context.Context, logger log.Logger, options option.V2RayAPIOptions) (adapter.V2RayServer, error)
|
||||
|
||||
var v2rayServerConstructor V2RayServerConstructor
|
||||
|
||||
@ -16,9 +17,9 @@ func RegisterV2RayServerConstructor(constructor V2RayServerConstructor) {
|
||||
v2rayServerConstructor = constructor
|
||||
}
|
||||
|
||||
func NewV2RayServer(logger log.Logger, options option.V2RayAPIOptions) (adapter.V2RayServer, error) {
|
||||
func NewV2RayServer(ctx context.Context, logger log.Logger, options option.V2RayAPIOptions) (adapter.V2RayServer, error) {
|
||||
if v2rayServerConstructor == nil {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
return v2rayServerConstructor(logger, options)
|
||||
return v2rayServerConstructor(ctx, logger, options)
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
package v2rayapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/tls"
|
||||
"github.com/sagernet/sing-box/experimental"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
@ -22,30 +25,48 @@ func init() {
|
||||
var _ adapter.V2RayServer = (*Server)(nil)
|
||||
|
||||
type Server struct {
|
||||
ctx context.Context
|
||||
logger log.Logger
|
||||
listen string
|
||||
tcpListener net.Listener
|
||||
grpcServer *grpc.Server
|
||||
statsService *StatsService
|
||||
tlsConfig tls.ServerConfig
|
||||
}
|
||||
|
||||
func NewServer(logger log.Logger, options option.V2RayAPIOptions) (adapter.V2RayServer, error) {
|
||||
func NewServer(ctx context.Context, logger log.Logger, options option.V2RayAPIOptions) (adapter.V2RayServer, error) {
|
||||
grpcServer := grpc.NewServer(grpc.Creds(insecure.NewCredentials()))
|
||||
statsService := NewStatsService(common.PtrValueOrDefault(options.Stats))
|
||||
if statsService != nil {
|
||||
RegisterStatsServiceServer(grpcServer, statsService)
|
||||
}
|
||||
var tlsConfig tls.ServerConfig
|
||||
if options.TLS != nil {
|
||||
var err error
|
||||
tlsConfig, err = tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
server := &Server{
|
||||
ctx: ctx,
|
||||
logger: logger,
|
||||
listen: options.Listen,
|
||||
grpcServer: grpcServer,
|
||||
statsService: statsService,
|
||||
tlsConfig: tlsConfig,
|
||||
}
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func (s *Server) Start() error {
|
||||
listener, err := net.Listen("tcp", s.listen)
|
||||
if s.tlsConfig != nil {
|
||||
err := s.tlsConfig.Start()
|
||||
if err != nil {
|
||||
return E.Cause(err, "create TLS config")
|
||||
}
|
||||
}
|
||||
listener, err := tls.NewListener(s.ctx, s.listen, s.tlsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
package include
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/experimental"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
@ -11,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
experimental.RegisterV2RayServerConstructor(func(logger log.Logger, options option.V2RayAPIOptions) (adapter.V2RayServer, error) {
|
||||
experimental.RegisterV2RayServerConstructor(func(ctx context.Context, logger log.Logger, options option.V2RayAPIOptions) (adapter.V2RayServer, error) {
|
||||
return nil, E.New(`v2ray api is not included in this build, rebuild with -tags with_v2ray_api`)
|
||||
})
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ type ClashAPIOptions struct {
|
||||
DefaultMode string `json:"default_mode,omitempty"`
|
||||
ModeList []string `json:"-"`
|
||||
|
||||
InboundTLSOptionsContainer
|
||||
|
||||
// Deprecated: migrated to global cache file
|
||||
CacheFile string `json:"cache_file,omitempty"`
|
||||
// Deprecated: migrated to global cache file
|
||||
@ -40,6 +42,7 @@ type ClashAPIOptions struct {
|
||||
type V2RayAPIOptions struct {
|
||||
Listen string `json:"listen,omitempty"`
|
||||
Stats *V2RayStatsServiceOptions `json:"stats,omitempty"`
|
||||
InboundTLSOptionsContainer
|
||||
}
|
||||
|
||||
type V2RayStatsServiceOptions struct {
|
||||
|
Loading…
x
Reference in New Issue
Block a user