mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 00:21:30 +00:00
Add NTP service
This commit is contained in:
parent
f26785c0ba
commit
611d6bbfc5
|
@ -41,6 +41,8 @@ type Router interface {
|
||||||
PackageManager() tun.PackageManager
|
PackageManager() tun.PackageManager
|
||||||
Rules() []Rule
|
Rules() []Rule
|
||||||
|
|
||||||
|
TimeService
|
||||||
|
|
||||||
ClashServer() ClashServer
|
ClashServer() ClashServer
|
||||||
SetClashServer(server ClashServer)
|
SetClashServer(server ClashServer)
|
||||||
|
|
||||||
|
|
8
adapter/time.go
Normal file
8
adapter/time.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package adapter
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type TimeService interface {
|
||||||
|
Service
|
||||||
|
TimeFunc() func() time.Time
|
||||||
|
}
|
1
box.go
1
box.go
|
@ -107,6 +107,7 @@ func New(ctx context.Context, options option.Options) (*Box, error) {
|
||||||
logFactory,
|
logFactory,
|
||||||
common.PtrValueOrDefault(options.Route),
|
common.PtrValueOrDefault(options.Route),
|
||||||
common.PtrValueOrDefault(options.DNS),
|
common.PtrValueOrDefault(options.DNS),
|
||||||
|
common.PtrValueOrDefault(options.NTP),
|
||||||
options.Inbounds,
|
options.Inbounds,
|
||||||
options.PlatformInterface,
|
options.PlatformInterface,
|
||||||
)
|
)
|
||||||
|
|
|
@ -34,7 +34,7 @@ func NewClient(router adapter.Router, serverAddress string, options option.Outbo
|
||||||
} else if options.UTLS != nil && options.UTLS.Enabled {
|
} else if options.UTLS != nil && options.UTLS.Enabled {
|
||||||
return NewUTLSClient(router, serverAddress, options)
|
return NewUTLSClient(router, serverAddress, options)
|
||||||
} else {
|
} else {
|
||||||
return NewSTDClient(serverAddress, options)
|
return NewSTDClient(router, serverAddress, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ func NewECHClient(router adapter.Router, serverAddress string, options option.Ou
|
||||||
}
|
}
|
||||||
|
|
||||||
var tlsConfig cftls.Config
|
var tlsConfig cftls.Config
|
||||||
|
tlsConfig.Time = router.TimeFunc()
|
||||||
if options.DisableSNI {
|
if options.DisableSNI {
|
||||||
tlsConfig.ServerName = "127.0.0.1"
|
tlsConfig.ServerName = "127.0.0.1"
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,7 +11,10 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenerateKeyPair(serverName string) (*tls.Certificate, error) {
|
func GenerateKeyPair(timeFunc func() time.Time, serverName string) (*tls.Certificate, error) {
|
||||||
|
if timeFunc == nil {
|
||||||
|
timeFunc = time.Now
|
||||||
|
}
|
||||||
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -22,8 +25,8 @@ func GenerateKeyPair(serverName string) (*tls.Certificate, error) {
|
||||||
}
|
}
|
||||||
template := &x509.Certificate{
|
template := &x509.Certificate{
|
||||||
SerialNumber: serialNumber,
|
SerialNumber: serialNumber,
|
||||||
NotBefore: time.Now().Add(time.Hour * -1),
|
NotBefore: timeFunc().Add(time.Hour * -1),
|
||||||
NotAfter: time.Now().Add(time.Hour),
|
NotAfter: timeFunc().Add(time.Hour),
|
||||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||||
BasicConstraintsValid: true,
|
BasicConstraintsValid: true,
|
||||||
|
|
|
@ -5,17 +5,18 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/badtls"
|
"github.com/sagernet/sing-box/common/badtls"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
|
func NewServer(ctx context.Context, router adapter.Router, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
|
||||||
if !options.Enabled {
|
if !options.Enabled {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return NewSTDServer(ctx, logger, options)
|
return NewSTDServer(ctx, router, logger, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServerHandshake(ctx context.Context, conn net.Conn, config ServerConfig) (Conn, error) {
|
func ServerHandshake(ctx context.Context, conn net.Conn, config ServerConfig) (Conn, error) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
)
|
)
|
||||||
|
@ -43,7 +44,7 @@ func (s *STDClientConfig) Clone() Config {
|
||||||
return &STDClientConfig{s.config.Clone()}
|
return &STDClientConfig{s.config.Clone()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSTDClient(serverAddress string, options option.OutboundTLSOptions) (Config, error) {
|
func NewSTDClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
|
||||||
var serverName string
|
var serverName string
|
||||||
if options.ServerName != "" {
|
if options.ServerName != "" {
|
||||||
serverName = options.ServerName
|
serverName = options.ServerName
|
||||||
|
@ -57,6 +58,7 @@ func NewSTDClient(serverAddress string, options option.OutboundTLSOptions) (Conf
|
||||||
}
|
}
|
||||||
|
|
||||||
var tlsConfig tls.Config
|
var tlsConfig tls.Config
|
||||||
|
tlsConfig.Time = router.TimeFunc()
|
||||||
if options.DisableSNI {
|
if options.DisableSNI {
|
||||||
tlsConfig.ServerName = "127.0.0.1"
|
tlsConfig.ServerName = "127.0.0.1"
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -156,7 +156,7 @@ func (c *STDServerConfig) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSTDServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
|
func NewSTDServer(ctx context.Context, router adapter.Router, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
|
||||||
if !options.Enabled {
|
if !options.Enabled {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -175,6 +175,7 @@ func NewSTDServer(ctx context.Context, logger log.Logger, options option.Inbound
|
||||||
} else {
|
} else {
|
||||||
tlsConfig = &tls.Config{}
|
tlsConfig = &tls.Config{}
|
||||||
}
|
}
|
||||||
|
tlsConfig.Time = router.TimeFunc()
|
||||||
if options.ServerName != "" {
|
if options.ServerName != "" {
|
||||||
tlsConfig.ServerName = options.ServerName
|
tlsConfig.ServerName = options.ServerName
|
||||||
}
|
}
|
||||||
|
@ -230,7 +231,7 @@ func NewSTDServer(ctx context.Context, logger log.Logger, options option.Inbound
|
||||||
}
|
}
|
||||||
if certificate == nil && key == nil && options.Insecure {
|
if certificate == nil && key == nil && options.Insecure {
|
||||||
tlsConfig.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
tlsConfig.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
return GenerateKeyPair(info.ServerName)
|
return GenerateKeyPair(router.TimeFunc(), info.ServerName)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if certificate == nil {
|
if certificate == nil {
|
||||||
|
|
|
@ -91,6 +91,7 @@ func NewUTLSClient(router adapter.Router, serverAddress string, options option.O
|
||||||
}
|
}
|
||||||
|
|
||||||
var tlsConfig utls.Config
|
var tlsConfig utls.Config
|
||||||
|
tlsConfig.Time = router.TimeFunc()
|
||||||
if options.DisableSNI {
|
if options.DisableSNI {
|
||||||
tlsConfig.ServerName = "127.0.0.1"
|
tlsConfig.ServerName = "127.0.0.1"
|
||||||
} else {
|
} else {
|
||||||
|
|
6
go.mod
6
go.mod
|
@ -23,9 +23,9 @@ require (
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0
|
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0
|
||||||
github.com/sagernet/gomobile v0.0.0-20221130124640-349ebaa752ca
|
github.com/sagernet/gomobile v0.0.0-20221130124640-349ebaa752ca
|
||||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
||||||
github.com/sagernet/sing v0.1.7
|
github.com/sagernet/sing v0.1.8-0.20230221060643-3401d210384b
|
||||||
github.com/sagernet/sing-dns v0.1.4
|
github.com/sagernet/sing-dns v0.1.4
|
||||||
github.com/sagernet/sing-shadowsocks v0.1.1
|
github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9
|
||||||
github.com/sagernet/sing-shadowtls v0.0.0-20230220055143-e986e9cd9eb9
|
github.com/sagernet/sing-shadowtls v0.0.0-20230220055143-e986e9cd9eb9
|
||||||
github.com/sagernet/sing-tun v0.1.1
|
github.com/sagernet/sing-tun v0.1.1
|
||||||
github.com/sagernet/sing-vmess v0.1.2
|
github.com/sagernet/sing-vmess v0.1.2
|
||||||
|
@ -49,8 +49,6 @@ require (
|
||||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c
|
||||||
)
|
)
|
||||||
|
|
||||||
//replace github.com/sagernet/sing => ../sing
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -127,12 +127,12 @@ github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 h1:tztuJB+giOWNRK
|
||||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32/go.mod h1:QMCkxXAC3CvBgDZVIJp43NWTuwGBScCzMLVLynjERL8=
|
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32/go.mod h1:QMCkxXAC3CvBgDZVIJp43NWTuwGBScCzMLVLynjERL8=
|
||||||
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.1.7 h1:g4vjr3q8SUlBZSx97Emz5OBfSMBxxW5Q8C2PfdoSo08=
|
github.com/sagernet/sing v0.1.8-0.20230221060643-3401d210384b h1:Ji2AfGlc4j9AitobOx4k3BCj7eS5nSxL1cgaL81zvlo=
|
||||||
github.com/sagernet/sing v0.1.7/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.8-0.20230221060643-3401d210384b/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
||||||
github.com/sagernet/sing-dns v0.1.4 h1:7VxgeoSCiiazDSaXXQVcvrTBxFpOePPq/4XdgnUDN+0=
|
github.com/sagernet/sing-dns v0.1.4 h1:7VxgeoSCiiazDSaXXQVcvrTBxFpOePPq/4XdgnUDN+0=
|
||||||
github.com/sagernet/sing-dns v0.1.4/go.mod h1:1+6pCa48B1AI78lD+/i/dLgpw4MwfnsSpZo0Ds8wzzk=
|
github.com/sagernet/sing-dns v0.1.4/go.mod h1:1+6pCa48B1AI78lD+/i/dLgpw4MwfnsSpZo0Ds8wzzk=
|
||||||
github.com/sagernet/sing-shadowsocks v0.1.1 h1:uFK2rlVeD/b1xhDwSMbUI2goWc6fOKxp+ZeKHZq6C9Q=
|
github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9 h1:qS39eA4C7x+zhEkySbASrtmb6ebdy5v0y2M6mgkmSO0=
|
||||||
github.com/sagernet/sing-shadowsocks v0.1.1/go.mod h1:f3mHTy5shnVM9l8UocMlJgC/1G/zdj5FuEuVXhDinGU=
|
github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9/go.mod h1:f3mHTy5shnVM9l8UocMlJgC/1G/zdj5FuEuVXhDinGU=
|
||||||
github.com/sagernet/sing-shadowtls v0.0.0-20230220055143-e986e9cd9eb9 h1:k1nXJL/00TSzlhFzTPpeo6VkbUyreIFVdGcd8pD7lrY=
|
github.com/sagernet/sing-shadowtls v0.0.0-20230220055143-e986e9cd9eb9 h1:k1nXJL/00TSzlhFzTPpeo6VkbUyreIFVdGcd8pD7lrY=
|
||||||
github.com/sagernet/sing-shadowtls v0.0.0-20230220055143-e986e9cd9eb9/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
|
github.com/sagernet/sing-shadowtls v0.0.0-20230220055143-e986e9cd9eb9/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
|
||||||
github.com/sagernet/sing-tun v0.1.1 h1:2Hg3GAyJWzQ7Ua1j74dE+mI06vaqSBO9yD4tkTjggn4=
|
github.com/sagernet/sing-tun v0.1.1 h1:2Hg3GAyJWzQ7Ua1j74dE+mI06vaqSBO9yD4tkTjggn4=
|
||||||
|
|
|
@ -44,7 +44,7 @@ func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogge
|
||||||
authenticator: auth.NewAuthenticator(options.Users),
|
authenticator: auth.NewAuthenticator(options.Users),
|
||||||
}
|
}
|
||||||
if options.TLS != nil {
|
if options.TLS != nil {
|
||||||
tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
tlsConfig, err := tls.NewServer(ctx, router, logger, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||||
if len(options.TLS.ALPN) == 0 {
|
if len(options.TLS.ALPN) == 0 {
|
||||||
options.TLS.ALPN = []string{hysteria.DefaultALPN}
|
options.TLS.ALPN = []string{hysteria.DefaultALPN}
|
||||||
}
|
}
|
||||||
tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
tlsConfig, err := tls.NewServer(ctx, router, logger, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ func NewNaive(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
return nil, E.New("missing users")
|
return nil, E.New("missing users")
|
||||||
}
|
}
|
||||||
if options.TLS != nil {
|
if options.TLS != nil {
|
||||||
tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
tlsConfig, err := tls.NewServer(ctx, router, logger, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ func newShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
|
||||||
case common.Contains(shadowaead.List, options.Method):
|
case common.Contains(shadowaead.List, options.Method):
|
||||||
inbound.service, err = shadowaead.NewService(options.Method, nil, options.Password, udpTimeout, inbound.upstreamContextHandler())
|
inbound.service, err = shadowaead.NewService(options.Method, nil, options.Password, udpTimeout, inbound.upstreamContextHandler())
|
||||||
case common.Contains(shadowaead_2022.List, options.Method):
|
case common.Contains(shadowaead_2022.List, options.Method):
|
||||||
inbound.service, err = shadowaead_2022.NewServiceWithPassword(options.Method, options.Password, udpTimeout, inbound.upstreamContextHandler())
|
inbound.service, err = shadowaead_2022.NewServiceWithPassword(options.Method, options.Password, udpTimeout, inbound.upstreamContextHandler(), router.TimeFunc())
|
||||||
default:
|
default:
|
||||||
err = E.New("unsupported method: ", options.Method)
|
err = E.New("unsupported method: ", options.Method)
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.
|
||||||
options.Password,
|
options.Password,
|
||||||
udpTimeout,
|
udpTimeout,
|
||||||
adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound),
|
adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound),
|
||||||
|
router.TimeFunc(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -49,7 +49,7 @@ func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLog
|
||||||
users: options.Users,
|
users: options.Users,
|
||||||
}
|
}
|
||||||
if options.TLS != nil {
|
if options.TLS != nil {
|
||||||
tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
tlsConfig, err := tls.NewServer(ctx, router, logger, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,9 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
users: options.Users,
|
users: options.Users,
|
||||||
}
|
}
|
||||||
var serviceOptions []vmess.ServiceOption
|
var serviceOptions []vmess.ServiceOption
|
||||||
|
if timeFunc := router.TimeFunc(); timeFunc != nil {
|
||||||
|
serviceOptions = append(serviceOptions, vmess.ServiceWithTimeFunc(timeFunc))
|
||||||
|
}
|
||||||
if options.Transport != nil && options.Transport.Type != "" {
|
if options.Transport != nil && options.Transport.Type != "" {
|
||||||
serviceOptions = append(serviceOptions, vmess.ServiceWithDisableHeaderProtection())
|
serviceOptions = append(serviceOptions, vmess.ServiceWithDisableHeaderProtection())
|
||||||
}
|
}
|
||||||
|
@ -66,7 +69,7 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if options.TLS != nil {
|
if options.TLS != nil {
|
||||||
inbound.tlsConfig, err = tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
inbound.tlsConfig, err = tls.NewServer(ctx, router, logger, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ func ContextWithOverrideLevel(ctx context.Context, level Level) context.Context
|
||||||
|
|
||||||
func OverrideLevelFromContext(origin Level, ctx context.Context) Level {
|
func OverrideLevelFromContext(origin Level, ctx context.Context) Level {
|
||||||
level, loaded := ctx.Value((*overrideLevelKey)(nil)).(Level)
|
level, loaded := ctx.Value((*overrideLevelKey)(nil)).(Level)
|
||||||
if !loaded || origin < level {
|
if !loaded || origin > level {
|
||||||
return origin
|
return origin
|
||||||
}
|
}
|
||||||
return level
|
return level
|
||||||
|
|
99
ntp/service.go
Normal file
99
ntp/service.go
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
package ntp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/dialer"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/logger"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/common/ntp"
|
||||||
|
)
|
||||||
|
|
||||||
|
const timeLayout = "2006-01-02 15:04:05 -0700"
|
||||||
|
|
||||||
|
var _ adapter.TimeService = (*Service)(nil)
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
ctx context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
|
server M.Socksaddr
|
||||||
|
dialer N.Dialer
|
||||||
|
logger logger.Logger
|
||||||
|
|
||||||
|
ticker *time.Ticker
|
||||||
|
clockOffset time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewService(ctx context.Context, router adapter.Router, logger logger.Logger, options option.NTPOptions) *Service {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
server := options.ServerOptions.Build()
|
||||||
|
if server.Port == 0 {
|
||||||
|
server.Port = 123
|
||||||
|
}
|
||||||
|
var interval time.Duration
|
||||||
|
if options.Interval > 0 {
|
||||||
|
interval = time.Duration(options.Interval) * time.Second
|
||||||
|
} else {
|
||||||
|
interval = 30 * time.Minute
|
||||||
|
}
|
||||||
|
return &Service{
|
||||||
|
ctx: ctx,
|
||||||
|
cancel: cancel,
|
||||||
|
server: server,
|
||||||
|
dialer: dialer.New(router, options.DialerOptions),
|
||||||
|
logger: logger,
|
||||||
|
ticker: time.NewTicker(interval),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) Start() error {
|
||||||
|
err := s.update()
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "initialize time")
|
||||||
|
}
|
||||||
|
s.logger.Info("updated time: ", s.TimeFunc()().Local().Format(timeLayout))
|
||||||
|
go s.loopUpdate()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) Close() error {
|
||||||
|
s.ticker.Stop()
|
||||||
|
s.cancel()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) TimeFunc() func() time.Time {
|
||||||
|
return func() time.Time {
|
||||||
|
return time.Now().Add(s.clockOffset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) loopUpdate() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-s.ctx.Done():
|
||||||
|
return
|
||||||
|
case <-s.ticker.C:
|
||||||
|
}
|
||||||
|
err := s.update()
|
||||||
|
if err == nil {
|
||||||
|
s.logger.Debug("updated time: ", s.TimeFunc()().Local().Format(timeLayout))
|
||||||
|
} else {
|
||||||
|
s.logger.Warn("update time: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) update() error {
|
||||||
|
response, err := ntp.Exchange(s.ctx, s.dialer, s.server)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.clockOffset = response.ClockOffset
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import (
|
||||||
type _Options struct {
|
type _Options struct {
|
||||||
Log *LogOptions `json:"log,omitempty"`
|
Log *LogOptions `json:"log,omitempty"`
|
||||||
DNS *DNSOptions `json:"dns,omitempty"`
|
DNS *DNSOptions `json:"dns,omitempty"`
|
||||||
|
NTP *NTPOptions `json:"ntp,omitempty"`
|
||||||
Inbounds []Inbound `json:"inbounds,omitempty"`
|
Inbounds []Inbound `json:"inbounds,omitempty"`
|
||||||
Outbounds []Outbound `json:"outbounds,omitempty"`
|
Outbounds []Outbound `json:"outbounds,omitempty"`
|
||||||
Route *RouteOptions `json:"route,omitempty"`
|
Route *RouteOptions `json:"route,omitempty"`
|
||||||
|
|
8
option/ntp.go
Normal file
8
option/ntp.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package option
|
||||||
|
|
||||||
|
type NTPOptions struct {
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
Interval Duration `json:"interval,omitempty"`
|
||||||
|
ServerOptions
|
||||||
|
DialerOptions
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ type Shadowsocks struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksOutboundOptions) (*Shadowsocks, error) {
|
func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksOutboundOptions) (*Shadowsocks, error) {
|
||||||
method, err := shadowimpl.FetchMethod(options.Method, options.Password)
|
method, err := shadowimpl.FetchMethod(options.Method, options.Password, router.TimeFunc())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,9 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
return nil, E.New("unknown packet encoding: ", options.PacketEncoding)
|
return nil, E.New("unknown packet encoding: ", options.PacketEncoding)
|
||||||
}
|
}
|
||||||
var clientOptions []vmess.ClientOption
|
var clientOptions []vmess.ClientOption
|
||||||
|
if timeFunc := router.TimeFunc(); timeFunc != nil {
|
||||||
|
clientOptions = append(clientOptions, vmess.ClientWithTimeFunc(timeFunc))
|
||||||
|
}
|
||||||
if options.GlobalPadding {
|
if options.GlobalPadding {
|
||||||
clientOptions = append(clientOptions, vmess.ClientWithGlobalPadding())
|
clientOptions = append(clientOptions, vmess.ClientWithGlobalPadding())
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
"github.com/sagernet/sing-box/experimental/libbox/platform"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
|
"github.com/sagernet/sing-box/ntp"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
"github.com/sagernet/sing-tun"
|
"github.com/sagernet/sing-tun"
|
||||||
|
@ -96,12 +97,21 @@ type Router struct {
|
||||||
interfaceMonitor tun.DefaultInterfaceMonitor
|
interfaceMonitor tun.DefaultInterfaceMonitor
|
||||||
packageManager tun.PackageManager
|
packageManager tun.PackageManager
|
||||||
processSearcher process.Searcher
|
processSearcher process.Searcher
|
||||||
|
timeService adapter.TimeService
|
||||||
clashServer adapter.ClashServer
|
clashServer adapter.ClashServer
|
||||||
v2rayServer adapter.V2RayServer
|
v2rayServer adapter.V2RayServer
|
||||||
platformInterface platform.Interface
|
platformInterface platform.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouter(ctx context.Context, logFactory log.Factory, options option.RouteOptions, dnsOptions option.DNSOptions, inbounds []option.Inbound, platformInterface platform.Interface) (*Router, error) {
|
func NewRouter(
|
||||||
|
ctx context.Context,
|
||||||
|
logFactory log.Factory,
|
||||||
|
options option.RouteOptions,
|
||||||
|
dnsOptions option.DNSOptions,
|
||||||
|
ntpOptions option.NTPOptions,
|
||||||
|
inbounds []option.Inbound,
|
||||||
|
platformInterface platform.Interface,
|
||||||
|
) (*Router, error) {
|
||||||
if options.DefaultInterface != "" {
|
if options.DefaultInterface != "" {
|
||||||
warnDefaultInterfaceOnUnsupportedPlatform.Check()
|
warnDefaultInterfaceOnUnsupportedPlatform.Check()
|
||||||
}
|
}
|
||||||
|
@ -302,6 +312,9 @@ func NewRouter(ctx context.Context, logFactory log.Factory, options option.Route
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ntpOptions.Enabled {
|
||||||
|
router.timeService = ntp.NewService(ctx, router, logFactory.NewLogger("ntp"), ntpOptions)
|
||||||
|
}
|
||||||
return router, nil
|
return router, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,6 +473,12 @@ func (r *Router) Start() error {
|
||||||
return E.Cause(err, "initialize DNS server[", i, "]")
|
return E.Cause(err, "initialize DNS server[", i, "]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if r.timeService != nil {
|
||||||
|
err := r.timeService.Start()
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "initialize time service")
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,6 +506,7 @@ func (r *Router) Close() error {
|
||||||
r.interfaceMonitor,
|
r.interfaceMonitor,
|
||||||
r.networkMonitor,
|
r.networkMonitor,
|
||||||
r.packageManager,
|
r.packageManager,
|
||||||
|
r.timeService,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,6 +803,13 @@ func (r *Router) PackageManager() tun.PackageManager {
|
||||||
return r.packageManager
|
return r.packageManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Router) TimeFunc() func() time.Time {
|
||||||
|
if r.timeService == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return r.timeService.TimeFunc()
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Router) ClashServer() adapter.ClashServer {
|
func (r *Router) ClashServer() adapter.ClashServer {
|
||||||
return r.clashServer
|
return r.clashServer
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue