Refactor: HTTP clients, unified HTTP2/QUIC options, Apple engines
This commit is contained in:
+10
-29
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
@@ -17,14 +16,13 @@ import (
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/adapter/certificate"
|
||||
"github.com/sagernet/sing-box/common/dialer"
|
||||
boxtls "github.com/sagernet/sing-box/common/tls"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/sagernet/sing/common/ntp"
|
||||
"github.com/sagernet/sing/service"
|
||||
|
||||
"github.com/caddyserver/certmagic"
|
||||
"github.com/caddyserver/zerossl"
|
||||
@@ -125,7 +123,7 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
|
||||
AltTLSALPNPort: int(options.AlternativeTLSPort),
|
||||
Logger: zapLogger,
|
||||
}
|
||||
acmeHTTPClient, err := newACMEHTTPClient(ctx, options.Detour)
|
||||
acmeHTTPClient, err := newACMEHTTPClient(ctx, logger, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -310,33 +308,16 @@ func createZeroSSLExternalAccountBinding(ctx context.Context, acmeIssuer *certma
|
||||
}, account, nil
|
||||
}
|
||||
|
||||
func newACMEHTTPClient(ctx context.Context, detour string) (*http.Client, error) {
|
||||
outboundDialer, err := dialer.NewWithOptions(dialer.Options{
|
||||
Context: ctx,
|
||||
Options: option.DialerOptions{
|
||||
Detour: detour,
|
||||
},
|
||||
RemoteIsDomain: true,
|
||||
})
|
||||
func newACMEHTTPClient(ctx context.Context, logger log.ContextLogger, options option.ACMECertificateProviderOptions) (*http.Client, error) {
|
||||
httpClientOptions := common.PtrValueOrDefault(options.HTTPClient)
|
||||
httpClientManager := service.FromContext[adapter.HTTPClientManager](ctx)
|
||||
transport, err := httpClientManager.ResolveTransport(ctx, logger, httpClientOptions)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create ACME provider dialer")
|
||||
return nil, E.Cause(err, "create ACME provider http client")
|
||||
}
|
||||
return &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return outboundDialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
},
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: adapter.RootPoolFromContext(ctx),
|
||||
Time: ntp.TimeFuncFromContext(ctx),
|
||||
},
|
||||
// from certmagic defaults (acmeissuer.go)
|
||||
TLSHandshakeTimeout: 30 * time.Second,
|
||||
ResponseHeaderTimeout: 30 * time.Second,
|
||||
ExpectContinueTimeout: 2 * time.Second,
|
||||
ForceAttemptHTTP2: true,
|
||||
},
|
||||
Timeout: certmagic.HTTPTimeout,
|
||||
Transport: transport,
|
||||
Timeout: certmagic.HTTPTimeout,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
+8
-24
@@ -5,7 +5,6 @@ package derp
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
stdTLS "crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -34,7 +33,6 @@ import (
|
||||
"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"
|
||||
aTLS "github.com/sagernet/sing/common/tls"
|
||||
"github.com/sagernet/sing/service"
|
||||
"github.com/sagernet/sing/service/filemanager"
|
||||
@@ -151,29 +149,14 @@ func (d *Service) Start(stage adapter.StartStage) error {
|
||||
if len(d.verifyClientURL) > 0 {
|
||||
var httpClients []*http.Client
|
||||
var urls []string
|
||||
for index, options := range d.verifyClientURL {
|
||||
verifyDialer, createErr := dialer.NewWithOptions(dialer.Options{
|
||||
Context: d.ctx,
|
||||
Options: options.DialerOptions,
|
||||
RemoteIsDomain: options.ServerIsDomain(),
|
||||
NewDialer: true,
|
||||
})
|
||||
httpClientManager := service.FromContext[adapter.HTTPClientManager](d.ctx)
|
||||
for index, verifyOptions := range d.verifyClientURL {
|
||||
transport, createErr := httpClientManager.ResolveTransport(d.ctx, d.logger, verifyOptions.HTTPClientOptions)
|
||||
if createErr != nil {
|
||||
return E.Cause(createErr, "verify_client_url[", index, "]")
|
||||
}
|
||||
httpClients = append(httpClients, &http.Client{
|
||||
Transport: &http.Transport{
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSClientConfig: &stdTLS.Config{
|
||||
RootCAs: adapter.RootPoolFromContext(d.ctx),
|
||||
Time: ntp.TimeFuncFromContext(d.ctx),
|
||||
},
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return verifyDialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
},
|
||||
},
|
||||
})
|
||||
urls = append(urls, options.URL)
|
||||
httpClients = append(httpClients, &http.Client{Transport: transport})
|
||||
urls = append(urls, verifyOptions.URL)
|
||||
}
|
||||
server.SetVerifyClientHTTPClient(httpClients)
|
||||
server.SetVerifyClientURL(urls)
|
||||
@@ -310,7 +293,7 @@ func (d *Service) startMeshWithHost(derpServer *derpserver.Server, server *optio
|
||||
}
|
||||
var stdConfig *tls.STDConfig
|
||||
if server.TLS != nil && server.TLS.Enabled {
|
||||
tlsConfig, err := tls.NewClient(d.ctx, d.logger, hostname, common.PtrValueOrDefault(server.TLS))
|
||||
tlsConfig, err := tls.NewClient(d.ctx, d.logger, hostname, *server.TLS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -352,10 +335,11 @@ func (d *Service) startMeshWithHost(derpServer *derpserver.Server, server *optio
|
||||
}
|
||||
|
||||
func (d *Service) Close() error {
|
||||
return common.Close(
|
||||
err := common.Close(
|
||||
common.PtrOrNil(d.listener),
|
||||
d.tlsConfig,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
var homePage = `
|
||||
|
||||
@@ -26,13 +26,13 @@ import (
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/adapter/certificate"
|
||||
"github.com/sagernet/sing-box/common/dialer"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/sagernet/sing/common/ntp"
|
||||
"github.com/sagernet/sing/service"
|
||||
|
||||
"github.com/caddyserver/certmagic"
|
||||
)
|
||||
@@ -102,16 +102,10 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
|
||||
requestedValidity = defaultRequestedValidity
|
||||
}
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
serviceDialer, err := dialer.NewWithOptions(dialer.Options{
|
||||
Context: ctx,
|
||||
Options: option.DialerOptions{
|
||||
Detour: options.Detour,
|
||||
},
|
||||
RemoteIsDomain: true,
|
||||
})
|
||||
httpClient, err := originCAHTTPClient(ctx, logger, options)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, E.Cause(err, "create Cloudflare Origin CA dialer")
|
||||
return nil, err
|
||||
}
|
||||
var storage certmagic.Storage
|
||||
if options.DataDirectory != "" {
|
||||
@@ -131,21 +125,12 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
|
||||
certmagic.StorageKeys.Safe(storageNamesKey),
|
||||
}, "/")
|
||||
return &Service{
|
||||
Adapter: certificate.NewAdapter(C.TypeCloudflareOriginCA, tag),
|
||||
logger: logger,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
timeFunc: timeFunc,
|
||||
httpClient: &http.Client{Transport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return serviceDialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||
},
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: adapter.RootPoolFromContext(ctx),
|
||||
Time: timeFunc,
|
||||
},
|
||||
ForceAttemptHTTP2: true,
|
||||
}},
|
||||
Adapter: certificate.NewAdapter(C.TypeCloudflareOriginCA, tag),
|
||||
logger: logger,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
timeFunc: timeFunc,
|
||||
httpClient: httpClient,
|
||||
storage: storage,
|
||||
storageIssuerKey: storageIssuerKey,
|
||||
storageNamesKey: storageNamesKey,
|
||||
@@ -158,6 +143,16 @@ func NewCertificateProvider(ctx context.Context, logger log.ContextLogger, tag s
|
||||
}, nil
|
||||
}
|
||||
|
||||
func originCAHTTPClient(ctx context.Context, logger log.ContextLogger, options option.CloudflareOriginCACertificateProviderOptions) (*http.Client, error) {
|
||||
httpClientOptions := common.PtrValueOrDefault(options.HTTPClient)
|
||||
httpClientManager := service.FromContext[adapter.HTTPClientManager](ctx)
|
||||
transport, err := httpClientManager.ResolveTransport(ctx, logger, httpClientOptions)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create Cloudflare Origin CA http client")
|
||||
}
|
||||
return &http.Client{Transport: transport}, nil
|
||||
}
|
||||
|
||||
func (s *Service) Start(stage adapter.StartStage) error {
|
||||
if stage != adapter.StartStateStart {
|
||||
return nil
|
||||
@@ -189,9 +184,6 @@ func (s *Service) Close() error {
|
||||
if done := s.done; done != nil {
|
||||
<-done
|
||||
}
|
||||
if transport, loaded := s.httpClient.Transport.(*http.Transport); loaded {
|
||||
transport.CloseIdleConnections()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -374,6 +366,7 @@ func (s *Service) requestCertificate(ctx context.Context) ([]byte, []byte, *tls.
|
||||
} else {
|
||||
request.Header.Set("X-Auth-User-Service-Key", s.originCAKey)
|
||||
}
|
||||
defer s.httpClient.CloseIdleConnections()
|
||||
response, err := s.httpClient.Do(request)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, E.Cause(err, "request certificate from Cloudflare")
|
||||
|
||||
Reference in New Issue
Block a user