Skip to content

Commit

Permalink
Support hot reloading of certificate and key files (XTLS#225)
Browse files Browse the repository at this point in the history
  • Loading branch information
eMeab authored Feb 12, 2021
1 parent df39991 commit 81d9931
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 97 deletions.
4 changes: 4 additions & 0 deletions infra/conf/transport_internet.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,13 +264,15 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
return nil, newError("failed to parse certificate").Base(err)
}
certificate.Certificate = cert
certificate.CertificatePath = c.CertFile

if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
key, err := readFileOrString(c.KeyFile, c.KeyStr)
if err != nil {
return nil, newError("failed to parse key").Base(err)
}
certificate.Key = key
certificate.KeyPath = c.KeyFile
}

switch strings.ToLower(c.Usage) {
Expand Down Expand Up @@ -348,13 +350,15 @@ func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) {
return nil, newError("failed to parse certificate").Base(err)
}
certificate.Certificate = cert
certificate.CertificatePath = c.CertFile

if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
key, err := readFileOrString(c.KeyFile, c.KeyStr)
if err != nil {
return nil, newError("failed to parse key").Base(err)
}
certificate.Key = key
certificate.KeyPath = c.KeyFile
}

switch strings.ToLower(c.Usage) {
Expand Down
41 changes: 36 additions & 5 deletions transport/internet/tls/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/ocsp"
"github.com/xtls/xray-core/common/platform/filesystem"
"github.com/xtls/xray-core/common/protocol/tls/cert"
"github.com/xtls/xray-core/transport/internet"
)
Expand Down Expand Up @@ -60,17 +61,47 @@ func (c *Config) BuildCertificates() []*tls.Certificate {
}
certs = append(certs, &keyPair)
if entry.OcspStapling != 0 {
go func(cert *tls.Certificate) {
index := len(certs) - 1
go func(cert *tls.Certificate, index int) {
t := time.NewTicker(time.Duration(entry.OcspStapling) * time.Second)
for {
if newData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
if entry.CertificatePath != "" && entry.KeyPath != "" {
newCert, err := filesystem.ReadFile(entry.CertificatePath)
if err != nil {
newError("failed to parse certificate").Base(err).AtError().WriteToLog()
<-t.C
continue
}
newKey, err := filesystem.ReadFile(entry.KeyPath)
if err != nil {
newError("failed to parse key").Base(err).AtError().WriteToLog()
<-t.C
continue
}
if string(newCert) != string(entry.Certificate) && string(newKey) != string(entry.Key) {
newKeyPair, err := tls.X509KeyPair(newCert, newKey)
if err != nil {
newError("ignoring invalid X509 key pair").Base(err).AtError().WriteToLog()
<-t.C
continue
}
if newKeyPair.Leaf, err = x509.ParseCertificate(newKeyPair.Certificate[0]); err != nil {
newError("ignoring invalid certificate").Base(err).AtError().WriteToLog()
<-t.C
continue
}
cert = &newKeyPair
}
}
if newOCSPData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
} else if string(newData) != string(cert.OCSPStaple) {
cert.OCSPStaple = newData
} else if string(newOCSPData) != string(cert.OCSPStaple) {
cert.OCSPStaple = newOCSPData
}
certs[index] = cert
<-t.C
}
}(certs[len(certs)-1])
}(certs[len(certs)-1], index)
}
}
return certs
Expand Down
108 changes: 65 additions & 43 deletions transport/internet/tls/config.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions transport/internet/tls/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ message Certificate {
Usage usage = 3;

int64 ocsp_stapling = 4;

// TLS certificate path
string certificate_path = 5;

// TLS Key path
string key_path = 6;
}

message Config {
Expand Down
41 changes: 36 additions & 5 deletions transport/internet/xtls/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/ocsp"
"github.com/xtls/xray-core/common/platform/filesystem"
"github.com/xtls/xray-core/common/protocol/tls/cert"
"github.com/xtls/xray-core/transport/internet"
)
Expand Down Expand Up @@ -59,17 +60,47 @@ func (c *Config) BuildCertificates() []*xtls.Certificate {
}
certs = append(certs, &keyPair)
if entry.OcspStapling != 0 {
go func(cert *xtls.Certificate) {
index := len(certs) - 1
go func(cert *xtls.Certificate, index int) {
t := time.NewTicker(time.Duration(entry.OcspStapling) * time.Second)
for {
if newData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
if entry.CertificatePath != "" && entry.KeyPath != "" {
newCert, err := filesystem.ReadFile(entry.CertificatePath)
if err != nil {
newError("failed to parse certificate").Base(err).AtError().WriteToLog()
<-t.C
continue
}
newKey, err := filesystem.ReadFile(entry.KeyPath)
if err != nil {
newError("failed to parse key").Base(err).AtError().WriteToLog()
<-t.C
continue
}
if string(newCert) != string(entry.Certificate) && string(newKey) != string(entry.Key) {
newKeyPair, err := xtls.X509KeyPair(newCert, newKey)
if err != nil {
newError("ignoring invalid X509 key pair").Base(err).AtError().WriteToLog()
<-t.C
continue
}
if newKeyPair.Leaf, err = x509.ParseCertificate(newKeyPair.Certificate[0]); err != nil {
newError("ignoring invalid certificate").Base(err).AtError().WriteToLog()
<-t.C
continue
}
cert = &newKeyPair
}
}
if newOCSPData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
} else if string(newData) != string(cert.OCSPStaple) {
cert.OCSPStaple = newData
} else if string(newOCSPData) != string(cert.OCSPStaple) {
cert.OCSPStaple = newOCSPData
}
certs[index] = cert
<-t.C
}
}(certs[len(certs)-1])
}(certs[len(certs)-1], index)
}
}
return certs
Expand Down
Loading

0 comments on commit 81d9931

Please sign in to comment.