mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-01-14 22:52:36 +08:00
Compare commits
1 Commits
copilot/fi
...
cert-pin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e86e0f9e02 |
2
go.mod
2
go.mod
@@ -25,7 +25,6 @@ require (
|
||||
golang.org/x/net v0.48.0
|
||||
golang.org/x/sync v0.19.0
|
||||
golang.org/x/sys v0.39.0
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
google.golang.org/grpc v1.78.0
|
||||
google.golang.org/protobuf v1.36.11
|
||||
@@ -51,6 +50,7 @@ require (
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
golang.org/x/tools v0.39.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
@@ -224,8 +224,7 @@ func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
switchToDirectCopy = &w.trafficState.Outbound.DownlinkReaderDirectCopy
|
||||
}
|
||||
|
||||
if *switchToDirectCopy && w.input == nil {
|
||||
// Already switched to direct copy mode
|
||||
if *switchToDirectCopy {
|
||||
if w.directReadCounter != nil {
|
||||
w.directReadCounter.Add(int64(buffer.Len()))
|
||||
}
|
||||
@@ -258,18 +257,11 @@ func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
|
||||
if *switchToDirectCopy {
|
||||
// XTLS Vision processes TLS-like conn's input and rawInput
|
||||
// input contains decrypted application data - safe to merge
|
||||
if inputBuffer, err := buf.ReadFrom(w.input); err == nil && !inputBuffer.IsEmpty() {
|
||||
buffer, _ = buf.MergeMulti(buffer, inputBuffer)
|
||||
}
|
||||
// rawInput may contain encrypted bytes for the next TLS record
|
||||
// If rawInput is not empty, we should NOT switch to direct mode yet
|
||||
// because those bytes need to be processed by the TLS layer first
|
||||
if w.rawInput != nil && w.rawInput.Len() > 0 {
|
||||
// rawInput has pending data - defer direct copy to next read
|
||||
// *switchToDirectCopy remains true (unchanged), so we will retry on the next ReadMultiBuffer call
|
||||
// This ensures we don't mix encrypted bytes with application data
|
||||
return buffer, err
|
||||
if rawInputBuffer, err := buf.ReadFrom(w.rawInput); err == nil && !rawInputBuffer.IsEmpty() {
|
||||
buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
|
||||
}
|
||||
*w.input = bytes.Reader{} // release memory
|
||||
w.input = nil
|
||||
|
||||
@@ -290,8 +290,10 @@ func (r *RandCarrier) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509
|
||||
// directly return success if pinned cert is leaf
|
||||
// or add the CA to RootCAs if pinned cert is CA(and can be used in VerifyPeerCertInNames for Self signed CA)
|
||||
RootCAs := r.RootCAs
|
||||
var verifyResult verifyResult
|
||||
var verifiedCert *x509.Certificate
|
||||
if r.PinnedPeerCertSha256 != nil {
|
||||
verifyResult, verifiedCert := verifyChain(certs, r.PinnedPeerCertSha256)
|
||||
verifyResult, verifiedCert = verifyChain(certs, r.PinnedPeerCertSha256)
|
||||
switch verifyResult {
|
||||
case certNotFound:
|
||||
return errors.New("peer cert is unrecognized")
|
||||
@@ -305,27 +307,39 @@ func (r *RandCarrier) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509
|
||||
}
|
||||
}
|
||||
|
||||
if r.VerifyPeerCertInNames != nil {
|
||||
if len(r.VerifyPeerCertInNames) > 0 {
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: RootCAs,
|
||||
CurrentTime: time.Now(),
|
||||
Intermediates: x509.NewCertPool(),
|
||||
}
|
||||
for _, cert := range certs[1:] {
|
||||
opts.Intermediates.AddCert(cert)
|
||||
}
|
||||
for _, opts.DNSName = range r.VerifyPeerCertInNames {
|
||||
if _, err := certs[0].Verify(opts); err == nil {
|
||||
return nil
|
||||
}
|
||||
if len(r.VerifyPeerCertInNames) > 0 {
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: RootCAs,
|
||||
CurrentTime: time.Now(),
|
||||
Intermediates: x509.NewCertPool(),
|
||||
}
|
||||
for _, cert := range certs[1:] {
|
||||
opts.Intermediates.AddCert(cert)
|
||||
}
|
||||
for _, opts.DNSName = range r.VerifyPeerCertInNames {
|
||||
if _, err := certs[0].Verify(opts); err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else if len(verifiedChains) == 0 && verifyResult == foundCA { // if found ca and verifiedChains is empty, we need to verify here
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: RootCAs,
|
||||
CurrentTime: time.Now(),
|
||||
Intermediates: x509.NewCertPool(),
|
||||
DNSName: r.Config.ServerName,
|
||||
}
|
||||
for _, cert := range certs[1:] {
|
||||
opts.Intermediates.AddCert(cert)
|
||||
}
|
||||
if _, err := certs[0].Verify(opts); err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RandCarrier struct {
|
||||
Config *tls.Config
|
||||
RootCAs *x509.CertPool
|
||||
VerifyPeerCertInNames []string
|
||||
PinnedPeerCertSha256 [][]byte
|
||||
@@ -366,6 +380,7 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
|
||||
SessionTicketsDisabled: !c.EnableSessionResumption,
|
||||
VerifyPeerCertificate: randCarrier.verifyPeerCert,
|
||||
}
|
||||
randCarrier.Config = config
|
||||
if len(c.VerifyPeerCertInNames) > 0 {
|
||||
config.InsecureSkipVerify = true
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user