mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-16 00:01:02 +00:00
7ecd88b9e3
* fix(mtls): invalidate pooled clients after credential rotation * fix(mtls): make connection reload read-only --------- Co-authored-by: n0ctal <293235942+n0ctal@users.noreply.github.com>
62 lines
2.1 KiB
Go
62 lines
2.1 KiB
Go
package service
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"strings"
|
|
|
|
"github.com/mhsanaei/3x-ui/v3/internal/util/common"
|
|
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
|
)
|
|
|
|
// NodeMtlsCaCert returns the PEM of this panel's node-auth CA certificate (the
|
|
// public half) to copy into a node's mTLS trust setting, minting the CA and the
|
|
// master client cert on first call so the panel is ready to present a client
|
|
// certificate to mtls nodes.
|
|
func (s *NodeService) NodeMtlsCaCert() (string, error) {
|
|
settings := SettingService{}
|
|
ca, err := settings.EnsureNodeMtlsCA()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if _, err := settings.EnsureMasterClientCert(); err != nil {
|
|
return "", err
|
|
}
|
|
return string(ca.CertPEM), nil
|
|
}
|
|
|
|
// ReloadMasterMtlsClient validates the master credential currently stored by
|
|
// the panel and drops cached mTLS connection pools. This makes an intentional
|
|
// out-of-process credential rotation take effect without restarting x-ui (and
|
|
// therefore without stopping the xray child process in the same service).
|
|
func (s *NodeService) ReloadMasterMtlsClient() error {
|
|
stored, err := (&SettingService{}).LoadMasterClientCert()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := tls.X509KeyPair(stored.CertPEM, stored.KeyPEM); err != nil {
|
|
return err
|
|
}
|
|
runtime.InvalidateMasterClientConnections()
|
|
return nil
|
|
}
|
|
|
|
// SetNodeMtlsTrustCA stores the CA certificate this panel trusts for incoming
|
|
// node-API client certificates. An empty value clears it (mTLS off). A
|
|
// non-empty value must be a PEM certificate (fail closed). Takes effect on the
|
|
// next panel restart, when the listener's ClientCAs is rebuilt.
|
|
func (s *NodeService) SetNodeMtlsTrustCA(caPem string) error {
|
|
caPem = strings.TrimSpace(caPem)
|
|
if caPem != "" {
|
|
block, _ := pem.Decode([]byte(caPem))
|
|
if block == nil || block.Type != "CERTIFICATE" {
|
|
return common.NewError("trust CA must be a PEM-encoded certificate")
|
|
}
|
|
if _, err := x509.ParseCertificate(block.Bytes); err != nil {
|
|
return common.NewError("invalid trust CA certificate: " + err.Error())
|
|
}
|
|
}
|
|
return (&SettingService{}).setString(settingNodeMtlsClientCA, caPem)
|
|
}
|