mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-01-13 06:07:14 +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
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
goerrors "errors"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
@@ -27,7 +26,6 @@ var nullDestination = net.TCPDestination(net.AnyIP, 0)
|
||||
type Server struct {
|
||||
bindServer *netBindServer
|
||||
|
||||
infoMu sync.RWMutex
|
||||
info routingInfo
|
||||
policyManager policy.Manager
|
||||
}
|
||||
@@ -80,14 +78,12 @@ func (*Server) Network() []net.Network {
|
||||
|
||||
// Process implements proxy.Inbound.
|
||||
func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error {
|
||||
s.infoMu.Lock()
|
||||
s.info = routingInfo{
|
||||
ctx: ctx,
|
||||
dispatcher: dispatcher,
|
||||
inboundTag: session.InboundFromContext(ctx),
|
||||
contentTag: session.ContentFromContext(ctx),
|
||||
}
|
||||
s.infoMu.Unlock()
|
||||
|
||||
ep, err := s.bindServer.ParseEndpoint(conn.RemoteAddr().String())
|
||||
if err != nil {
|
||||
@@ -124,23 +120,18 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
|
||||
}
|
||||
|
||||
func (s *Server) forwardConnection(dest net.Destination, conn net.Conn) {
|
||||
// Make a thread-safe copy of routing info
|
||||
s.infoMu.RLock()
|
||||
info := s.info
|
||||
s.infoMu.RUnlock()
|
||||
|
||||
if info.dispatcher == nil {
|
||||
errors.LogError(info.ctx, "unexpected: dispatcher == nil")
|
||||
if s.info.dispatcher == nil {
|
||||
errors.LogError(s.info.ctx, "unexpected: dispatcher == nil")
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
ctx, cancel := context.WithCancel(core.ToBackgroundDetachedContext(info.ctx))
|
||||
ctx, cancel := context.WithCancel(core.ToBackgroundDetachedContext(s.info.ctx))
|
||||
sid := session.NewID()
|
||||
ctx = c.ContextWithID(ctx, sid)
|
||||
inbound := session.Inbound{} // since promiscuousModeHandler mixed-up context, we shallow copy inbound (tag) and content (configs)
|
||||
if info.inboundTag != nil {
|
||||
inbound = *info.inboundTag
|
||||
if s.info.inboundTag != nil {
|
||||
inbound = *s.info.inboundTag
|
||||
}
|
||||
inbound.Name = "wireguard"
|
||||
inbound.CanSpliceCopy = 3
|
||||
@@ -150,8 +141,8 @@ func (s *Server) forwardConnection(dest net.Destination, conn net.Conn) {
|
||||
// Currently we have no way to link to the original source address
|
||||
inbound.Source = net.DestinationFromAddr(conn.RemoteAddr())
|
||||
ctx = session.ContextWithInbound(ctx, &inbound)
|
||||
if info.contentTag != nil {
|
||||
ctx = session.ContextWithContent(ctx, info.contentTag)
|
||||
if s.info.contentTag != nil {
|
||||
ctx = session.ContextWithContent(ctx, s.info.contentTag)
|
||||
}
|
||||
ctx = session.SubContextFromMuxInbound(ctx)
|
||||
|
||||
@@ -165,16 +156,7 @@ func (s *Server) forwardConnection(dest net.Destination, conn net.Conn) {
|
||||
Reason: "",
|
||||
})
|
||||
|
||||
// Set inbound and content tags from routing info for proper routing
|
||||
// These were commented out in PR #4030 but are needed for domain-based routing
|
||||
if info.inboundTag != nil {
|
||||
ctx = session.ContextWithInbound(ctx, info.inboundTag)
|
||||
}
|
||||
if info.contentTag != nil {
|
||||
ctx = session.ContextWithContent(ctx, info.contentTag)
|
||||
}
|
||||
|
||||
link, err := info.dispatcher.Dispatch(ctx, dest)
|
||||
link, err := s.info.dispatcher.Dispatch(ctx, dest)
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "dispatch connection")
|
||||
}
|
||||
|
||||
@@ -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