Compare commits

..

1 Commits

Author SHA1 Message Date
Fangliding
e86e0f9e02 Verify for self signed ca 2026-01-10 16:59:41 +08:00
3 changed files with 39 additions and 42 deletions

2
go.mod
View File

@@ -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

View File

@@ -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")
}

View File

@@ -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 {