mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-11 17:47:20 +10:00
Fix missing mTLS support in client options
This commit is contained in:
@@ -169,6 +169,35 @@ func NewSTDClient(ctx context.Context, logger logger.ContextLogger, serverAddres
|
||||
}
|
||||
tlsConfig.RootCAs = certPool
|
||||
}
|
||||
var clientCertificate []byte
|
||||
if len(options.ClientCertificate) > 0 {
|
||||
clientCertificate = []byte(strings.Join(options.ClientCertificate, "\n"))
|
||||
} else if options.ClientCertificatePath != "" {
|
||||
content, err := os.ReadFile(options.ClientCertificatePath)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "read client certificate")
|
||||
}
|
||||
clientCertificate = content
|
||||
}
|
||||
var clientKey []byte
|
||||
if len(options.ClientKey) > 0 {
|
||||
clientKey = []byte(strings.Join(options.ClientKey, "\n"))
|
||||
} else if options.ClientKeyPath != "" {
|
||||
content, err := os.ReadFile(options.ClientKeyPath)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "read client key")
|
||||
}
|
||||
clientKey = content
|
||||
}
|
||||
if len(clientCertificate) > 0 && len(clientKey) > 0 {
|
||||
keyPair, err := tls.X509KeyPair(clientCertificate, clientKey)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse client x509 key pair")
|
||||
}
|
||||
tlsConfig.Certificates = []tls.Certificate{keyPair}
|
||||
} else if len(clientCertificate) > 0 || len(clientKey) > 0 {
|
||||
return nil, E.New("client certificate and client key must be provided together")
|
||||
}
|
||||
var config Config = &STDClientConfig{ctx, &tlsConfig, options.Fragment, time.Duration(options.FragmentFallbackDelay), options.RecordFragment}
|
||||
if options.ECH != nil && options.ECH.Enabled {
|
||||
var err error
|
||||
|
||||
@@ -222,6 +222,35 @@ func NewUTLSClient(ctx context.Context, logger logger.ContextLogger, serverAddre
|
||||
}
|
||||
tlsConfig.RootCAs = certPool
|
||||
}
|
||||
var clientCertificate []byte
|
||||
if len(options.ClientCertificate) > 0 {
|
||||
clientCertificate = []byte(strings.Join(options.ClientCertificate, "\n"))
|
||||
} else if options.ClientCertificatePath != "" {
|
||||
content, err := os.ReadFile(options.ClientCertificatePath)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "read client certificate")
|
||||
}
|
||||
clientCertificate = content
|
||||
}
|
||||
var clientKey []byte
|
||||
if len(options.ClientKey) > 0 {
|
||||
clientKey = []byte(strings.Join(options.ClientKey, "\n"))
|
||||
} else if options.ClientKeyPath != "" {
|
||||
content, err := os.ReadFile(options.ClientKeyPath)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "read client key")
|
||||
}
|
||||
clientKey = content
|
||||
}
|
||||
if len(clientCertificate) > 0 && len(clientKey) > 0 {
|
||||
keyPair, err := utls.X509KeyPair(clientCertificate, clientKey)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse client x509 key pair")
|
||||
}
|
||||
tlsConfig.Certificates = []utls.Certificate{keyPair}
|
||||
} else if len(clientCertificate) > 0 || len(clientKey) > 0 {
|
||||
return nil, E.New("client certificate and client key must be provided together")
|
||||
}
|
||||
id, err := uTLSClientHelloID(options.UTLS.Fingerprint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -4,13 +4,15 @@ icon: material/new-box
|
||||
|
||||
!!! quote "Changes in sing-box 1.13.0"
|
||||
|
||||
:material-plus: [kernel_tx](#kernel_tx)
|
||||
:material-plus: [kernel_rx](#kernel_rx)
|
||||
:material-plus: [curve_preferences](#curve_preferences)
|
||||
:material-plus: [certificate_public_key_sha256](#certificate_public_key_sha256)
|
||||
:material-plus: [client_authentication](#client_authentication)
|
||||
:material-plus: [client_certificate](#client_certificate)
|
||||
:material-plus: [client_certificate_path](#client_certificate_path)
|
||||
:material-plus: [kernel_tx](#kernel_tx)
|
||||
:material-plus: [kernel_rx](#kernel_rx)
|
||||
:material-plus: [curve_preferences](#curve_preferences)
|
||||
:material-plus: [certificate_public_key_sha256](#certificate_public_key_sha256)
|
||||
:material-plus: [client_certificate](#client_certificate)
|
||||
:material-plus: [client_certificate_path](#client_certificate_path)
|
||||
:material-plus: [client_key](#client_key)
|
||||
:material-plus: [client_key_path](#client_key_path)
|
||||
:material-plus: [client_authentication](#client_authentication)
|
||||
:material-plus: [client_certificate_public_key_sha256](#client_certificate_public_key_sha256)
|
||||
|
||||
!!! quote "Changes in sing-box 1.12.0"
|
||||
@@ -101,9 +103,14 @@ icon: material/new-box
|
||||
"min_version": "",
|
||||
"max_version": "",
|
||||
"cipher_suites": [],
|
||||
"curve_preferences": [],
|
||||
"certificate": "",
|
||||
"certificate_path": "",
|
||||
"certificate_public_key_sha256": [],
|
||||
"client_certificate": [],
|
||||
"client_certificate_path": "",
|
||||
"client_key": [],
|
||||
"client_key_path": "",
|
||||
"fragment": false,
|
||||
"fragment_fallback_delay": "",
|
||||
"record_fragment": false,
|
||||
@@ -258,6 +265,38 @@ openssl x509 -in certificate.pem -pubkey -noout | openssl pkey -pubin -outform d
|
||||
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
|
||||
```
|
||||
|
||||
#### client_certificate
|
||||
|
||||
!!! question "Since sing-box 1.13.0"
|
||||
|
||||
==Client only==
|
||||
|
||||
Client certificate chain line array, in PEM format.
|
||||
|
||||
#### client_certificate_path
|
||||
|
||||
!!! question "Since sing-box 1.13.0"
|
||||
|
||||
==Client only==
|
||||
|
||||
The path to client certificate chain, in PEM format.
|
||||
|
||||
#### client_key
|
||||
|
||||
!!! question "Since sing-box 1.13.0"
|
||||
|
||||
==Client only==
|
||||
|
||||
Client private key line array, in PEM format.
|
||||
|
||||
#### client_key_path
|
||||
|
||||
!!! question "Since sing-box 1.13.0"
|
||||
|
||||
==Client only==
|
||||
|
||||
The path to client private key, in PEM format.
|
||||
|
||||
#### key
|
||||
|
||||
==Server only==
|
||||
|
||||
@@ -8,9 +8,11 @@ icon: material/new-box
|
||||
:material-plus: [kernel_rx](#kernel_rx)
|
||||
:material-plus: [curve_preferences](#curve_preferences)
|
||||
:material-plus: [certificate_public_key_sha256](#certificate_public_key_sha256)
|
||||
:material-plus: [client_authentication](#client_authentication)
|
||||
:material-plus: [client_certificate](#client_certificate)
|
||||
:material-plus: [client_certificate_path](#client_certificate_path)
|
||||
:material-plus: [client_key](#client_key)
|
||||
:material-plus: [client_key_path](#client_key_path)
|
||||
:material-plus: [client_authentication](#client_authentication)
|
||||
:material-plus: [client_certificate_public_key_sha256](#client_certificate_public_key_sha256)
|
||||
|
||||
!!! quote "sing-box 1.12.0 中的更改"
|
||||
@@ -101,9 +103,14 @@ icon: material/new-box
|
||||
"min_version": "",
|
||||
"max_version": "",
|
||||
"cipher_suites": [],
|
||||
"curve_preferences": [],
|
||||
"certificate": "",
|
||||
"certificate_path": "",
|
||||
"certificate_public_key_sha256": [],
|
||||
"client_certificate": [],
|
||||
"client_certificate_path": "",
|
||||
"client_key": [],
|
||||
"client_key_path": "",
|
||||
"fragment": false,
|
||||
"fragment_fallback_delay": "",
|
||||
"record_fragment": false,
|
||||
@@ -253,6 +260,38 @@ openssl x509 -in certificate.pem -pubkey -noout | openssl pkey -pubin -outform d
|
||||
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
|
||||
```
|
||||
|
||||
#### client_certificate
|
||||
|
||||
!!! question "自 sing-box 1.13.0 起"
|
||||
|
||||
==仅客户端==
|
||||
|
||||
客户端证书链行数组,PEM 格式。
|
||||
|
||||
#### client_certificate_path
|
||||
|
||||
!!! question "自 sing-box 1.13.0 起"
|
||||
|
||||
==仅客户端==
|
||||
|
||||
客户端证书链路径,PEM 格式。
|
||||
|
||||
#### client_key
|
||||
|
||||
!!! question "自 sing-box 1.13.0 起"
|
||||
|
||||
==仅客户端==
|
||||
|
||||
客户端私钥行数组,PEM 格式。
|
||||
|
||||
#### client_key_path
|
||||
|
||||
!!! question "自 sing-box 1.13.0 起"
|
||||
|
||||
==仅客户端==
|
||||
|
||||
客户端私钥路径,PEM 格式。
|
||||
|
||||
#### key
|
||||
|
||||
==仅服务器==
|
||||
|
||||
@@ -107,6 +107,10 @@ type OutboundTLSOptions struct {
|
||||
Certificate badoption.Listable[string] `json:"certificate,omitempty"`
|
||||
CertificatePath string `json:"certificate_path,omitempty"`
|
||||
CertificatePublicKeySHA256 badoption.Listable[[]byte] `json:"certificate_public_key_sha256,omitempty"`
|
||||
ClientCertificate badoption.Listable[string] `json:"client_certificate,omitempty"`
|
||||
ClientCertificatePath string `json:"client_certificate_path,omitempty"`
|
||||
ClientKey badoption.Listable[string] `json:"client_key,omitempty"`
|
||||
ClientKeyPath string `json:"client_key_path,omitempty"`
|
||||
Fragment bool `json:"fragment,omitempty"`
|
||||
FragmentFallbackDelay badoption.Duration `json:"fragment_fallback_delay,omitempty"`
|
||||
RecordFragment bool `json:"record_fragment,omitempty"`
|
||||
|
||||
Reference in New Issue
Block a user