mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-02-07 01:59:24 +03:00
MITM: Allow using local received SNI in the outgoing serverName
& verifyPeerCertInNames
https://github.com/XTLS/Xray-core/issues/4348#issuecomment-2637370175 Local received SNI was sent by browser/app. In freedom RAW's `tlsSettings`, set `"serverName": "fromMitm"` to forward it to the real website. In freedom RAW's `tlsSettings`, set `"verifyPeerCertInNames": ["fromMitm"]` to use all possible names to verify the certificate.
This commit is contained in:
parent
9b7841178a
commit
c6a31f457c
@ -24,6 +24,7 @@ const (
|
|||||||
allowedNetworkKey ctx.SessionKey = 9
|
allowedNetworkKey ctx.SessionKey = 9
|
||||||
handlerSessionKey ctx.SessionKey = 10
|
handlerSessionKey ctx.SessionKey = 10
|
||||||
mitmAlpn11Key ctx.SessionKey = 11
|
mitmAlpn11Key ctx.SessionKey = 11
|
||||||
|
mitmServerNameKey ctx.SessionKey = 12
|
||||||
)
|
)
|
||||||
|
|
||||||
func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context {
|
func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context {
|
||||||
@ -174,3 +175,14 @@ func MitmAlpn11FromContext(ctx context.Context) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ContextWithMitmServerName(ctx context.Context, serverName string) context.Context {
|
||||||
|
return context.WithValue(ctx, mitmServerNameKey, serverName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MitmServerNameFromContext(ctx context.Context) string {
|
||||||
|
if val, ok := ctx.Value(mitmServerNameKey).(string); ok {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
@ -411,6 +411,7 @@ type TLSConfig struct {
|
|||||||
CurvePreferences *StringList `json:"curvePreferences"`
|
CurvePreferences *StringList `json:"curvePreferences"`
|
||||||
MasterKeyLog string `json:"masterKeyLog"`
|
MasterKeyLog string `json:"masterKeyLog"`
|
||||||
ServerNameToVerify string `json:"serverNameToVerify"`
|
ServerNameToVerify string `json:"serverNameToVerify"`
|
||||||
|
VerifyPeerCertInNames []string `json:"verifyPeerCertInNames"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
@ -469,10 +470,11 @@ func (c *TLSConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.MasterKeyLog = c.MasterKeyLog
|
config.MasterKeyLog = c.MasterKeyLog
|
||||||
config.ServerNameToVerify = c.ServerNameToVerify
|
|
||||||
if config.ServerNameToVerify != "" && config.Fingerprint == "unsafe" {
|
if c.ServerNameToVerify != "" {
|
||||||
return nil, errors.New(`serverNameToVerify only works with uTLS for now`)
|
return nil, errors.PrintRemovedFeatureError("serverNameToVerify", "verifyPeerCertInNames")
|
||||||
}
|
}
|
||||||
|
config.VerifyPeerCertInNames = c.VerifyPeerCertInNames
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
@ -64,10 +64,6 @@ func (d *DokodemoDoor) policy() policy.Session {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
type hasHandshakeAddressContext interface {
|
|
||||||
HandshakeAddressContext(ctx context.Context) net.Address
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process implements proxy.Inbound.
|
// Process implements proxy.Inbound.
|
||||||
func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error {
|
func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error {
|
||||||
errors.LogDebug(ctx, "processing connection from: ", conn.RemoteAddr())
|
errors.LogDebug(ctx, "processing connection from: ", conn.RemoteAddr())
|
||||||
@ -87,14 +83,14 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
|
|||||||
destinationOverridden = true
|
destinationOverridden = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if handshake, ok := conn.(hasHandshakeAddressContext); ok && !destinationOverridden {
|
if tlsConn, ok := conn.(tls.Interface); ok && !destinationOverridden {
|
||||||
addr := handshake.HandshakeAddressContext(ctx)
|
if serverName := tlsConn.HandshakeContextServerName(ctx); serverName != "" {
|
||||||
if addr != nil {
|
dest.Address = net.DomainAddress(serverName)
|
||||||
dest.Address = addr
|
|
||||||
if conn.(*tls.Conn).ConnectionState().NegotiatedProtocol == "http/1.1" {
|
|
||||||
ctx = session.ContextWithMitmAlpn11(ctx, true)
|
|
||||||
}
|
|
||||||
destinationOverridden = true
|
destinationOverridden = true
|
||||||
|
ctx = session.ContextWithMitmServerName(ctx, serverName)
|
||||||
|
}
|
||||||
|
if tlsConn.NegotiatedProtocol() == "http/1.1" {
|
||||||
|
ctx = session.ContextWithMitmAlpn11(ctx, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,10 @@ import (
|
|||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func IsFromMitm(str string) bool {
|
||||||
|
return strings.ToLower(str) == "frommitm"
|
||||||
|
}
|
||||||
|
|
||||||
// Dial dials a new TCP connection to the given destination.
|
// Dial dials a new TCP connection to the given destination.
|
||||||
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {
|
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {
|
||||||
errors.LogInfo(ctx, "dialing TCP to ", dest)
|
errors.LogInfo(ctx, "dialing TCP to ", dest)
|
||||||
@ -23,11 +27,28 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
|
mitmServerName := session.MitmServerNameFromContext(ctx)
|
||||||
|
mitmAlpn11 := session.MitmAlpn11FromContext(ctx)
|
||||||
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
|
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
|
||||||
|
if IsFromMitm(tlsConfig.ServerName) {
|
||||||
|
tlsConfig.ServerName = mitmServerName
|
||||||
|
}
|
||||||
|
if r, ok := tlsConfig.Rand.(*tls.RandCarrier); ok && len(r.VerifyPeerCertInNames) > 0 && IsFromMitm(r.VerifyPeerCertInNames[0]) {
|
||||||
|
r.VerifyPeerCertInNames = r.VerifyPeerCertInNames[1:]
|
||||||
|
after := mitmServerName
|
||||||
|
for {
|
||||||
|
if len(after) > 0 {
|
||||||
|
r.VerifyPeerCertInNames = append(r.VerifyPeerCertInNames, after)
|
||||||
|
}
|
||||||
|
_, after, _ = strings.Cut(after, ".")
|
||||||
|
if !strings.Contains(after, ".") {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if fingerprint := tls.GetFingerprint(config.Fingerprint); fingerprint != nil {
|
if fingerprint := tls.GetFingerprint(config.Fingerprint); fingerprint != nil {
|
||||||
conn = tls.UClient(conn, tlsConfig, fingerprint)
|
conn = tls.UClient(conn, tlsConfig, fingerprint)
|
||||||
if len(tlsConfig.NextProtos) == 1 && (tlsConfig.NextProtos[0] == "http/1.1" ||
|
if len(tlsConfig.NextProtos) == 1 && (tlsConfig.NextProtos[0] == "http/1.1" || (IsFromMitm(tlsConfig.NextProtos[0]) && mitmAlpn11)) {
|
||||||
(strings.ToLower(tlsConfig.NextProtos[0]) == "frommitm" && session.MitmAlpn11FromContext(ctx))) {
|
|
||||||
if err := conn.(*tls.UConn).WebsocketHandshakeContext(ctx); err != nil {
|
if err := conn.(*tls.UConn).WebsocketHandshakeContext(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -37,14 +58,17 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if len(tlsConfig.NextProtos) == 1 && strings.ToLower(tlsConfig.NextProtos[0]) == "frommitm" {
|
if len(tlsConfig.NextProtos) == 1 && IsFromMitm(tlsConfig.NextProtos[0]) {
|
||||||
if session.MitmAlpn11FromContext(ctx) {
|
if mitmAlpn11 {
|
||||||
tlsConfig.NextProtos = []string{"http/1.1"} // new slice
|
tlsConfig.NextProtos[0] = "http/1.1"
|
||||||
} else {
|
} else {
|
||||||
tlsConfig.NextProtos = nil
|
tlsConfig.NextProtos = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn = tls.Client(conn, tlsConfig)
|
conn = tls.Client(conn, tlsConfig)
|
||||||
|
if err := conn.(*tls.Conn).HandshakeContext(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
|
} else if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
if conn, err = reality.UClient(conn, config, ctx, dest); err != nil {
|
if conn, err = reality.UClient(conn, config, ctx, dest); err != nil {
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -277,10 +278,35 @@ func (c *Config) parseServerName() string {
|
|||||||
return c.ServerName
|
return c.ServerName
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
func (r *RandCarrier) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
||||||
if c.PinnedPeerCertificateChainSha256 != nil {
|
if r.VerifyPeerCertInNames != nil {
|
||||||
|
if len(r.VerifyPeerCertInNames) > 0 {
|
||||||
|
certs := make([]*x509.Certificate, len(rawCerts))
|
||||||
|
for i, asn1Data := range rawCerts {
|
||||||
|
certs[i], _ = x509.ParseCertificate(asn1Data)
|
||||||
|
}
|
||||||
|
opts := x509.VerifyOptions{
|
||||||
|
Roots: r.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 r.PinnedPeerCertificateChainSha256 == nil {
|
||||||
|
errors.New("peer cert is invalid.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.PinnedPeerCertificateChainSha256 != nil {
|
||||||
hashValue := GenerateCertChainHash(rawCerts)
|
hashValue := GenerateCertChainHash(rawCerts)
|
||||||
for _, v := range c.PinnedPeerCertificateChainSha256 {
|
for _, v := range r.PinnedPeerCertificateChainSha256 {
|
||||||
if hmac.Equal(hashValue, v) {
|
if hmac.Equal(hashValue, v) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -288,11 +314,11 @@ func (c *Config) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Cert
|
|||||||
return errors.New("peer cert is unrecognized: ", base64.StdEncoding.EncodeToString(hashValue))
|
return errors.New("peer cert is unrecognized: ", base64.StdEncoding.EncodeToString(hashValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.PinnedPeerCertificatePublicKeySha256 != nil {
|
if r.PinnedPeerCertificatePublicKeySha256 != nil {
|
||||||
for _, v := range verifiedChains {
|
for _, v := range verifiedChains {
|
||||||
for _, cert := range v {
|
for _, cert := range v {
|
||||||
publicHash := GenerateCertPublicKeyHash(cert)
|
publicHash := GenerateCertPublicKeyHash(cert)
|
||||||
for _, c := range c.PinnedPeerCertificatePublicKeySha256 {
|
for _, c := range r.PinnedPeerCertificatePublicKeySha256 {
|
||||||
if hmac.Equal(publicHash, c) {
|
if hmac.Equal(publicHash, c) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -305,7 +331,10 @@ func (c *Config) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Cert
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RandCarrier struct {
|
type RandCarrier struct {
|
||||||
ServerNameToVerify string
|
RootCAs *x509.CertPool
|
||||||
|
VerifyPeerCertInNames []string
|
||||||
|
PinnedPeerCertificateChainSha256 [][]byte
|
||||||
|
PinnedPeerCertificatePublicKeySha256 [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RandCarrier) Read(p []byte) (n int, err error) {
|
func (r *RandCarrier) Read(p []byte) (n int, err error) {
|
||||||
@ -329,16 +358,25 @@ func (c *Config) GetTLSConfig(opts ...Option) *tls.Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
randCarrier := &RandCarrier{
|
||||||
|
RootCAs: root,
|
||||||
|
VerifyPeerCertInNames: slices.Clone(c.VerifyPeerCertInNames),
|
||||||
|
PinnedPeerCertificateChainSha256: c.PinnedPeerCertificateChainSha256,
|
||||||
|
PinnedPeerCertificatePublicKeySha256: c.PinnedPeerCertificatePublicKeySha256,
|
||||||
|
}
|
||||||
config := &tls.Config{
|
config := &tls.Config{
|
||||||
Rand: &RandCarrier{
|
Rand: randCarrier,
|
||||||
ServerNameToVerify: c.ServerNameToVerify,
|
|
||||||
},
|
|
||||||
ClientSessionCache: globalSessionCache,
|
ClientSessionCache: globalSessionCache,
|
||||||
RootCAs: root,
|
RootCAs: root,
|
||||||
InsecureSkipVerify: c.AllowInsecure,
|
InsecureSkipVerify: c.AllowInsecure,
|
||||||
NextProtos: c.NextProtocol,
|
NextProtos: slices.Clone(c.NextProtocol),
|
||||||
SessionTicketsDisabled: !c.EnableSessionResumption,
|
SessionTicketsDisabled: !c.EnableSessionResumption,
|
||||||
VerifyPeerCertificate: c.verifyPeerCert,
|
VerifyPeerCertificate: randCarrier.verifyPeerCert,
|
||||||
|
}
|
||||||
|
if len(c.VerifyPeerCertInNames) > 0 {
|
||||||
|
config.InsecureSkipVerify = true
|
||||||
|
} else {
|
||||||
|
randCarrier.VerifyPeerCertInNames = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
|
@ -202,20 +202,21 @@ type Config struct {
|
|||||||
// TLS Client Hello fingerprint (uTLS).
|
// TLS Client Hello fingerprint (uTLS).
|
||||||
Fingerprint string `protobuf:"bytes,11,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"`
|
Fingerprint string `protobuf:"bytes,11,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"`
|
||||||
RejectUnknownSni bool `protobuf:"varint,12,opt,name=reject_unknown_sni,json=rejectUnknownSni,proto3" json:"reject_unknown_sni,omitempty"`
|
RejectUnknownSni bool `protobuf:"varint,12,opt,name=reject_unknown_sni,json=rejectUnknownSni,proto3" json:"reject_unknown_sni,omitempty"`
|
||||||
// @Document A pinned certificate chain sha256 hash.
|
// @Document Some certificate chain sha256 hashes.
|
||||||
// @Document If the server's hash does not match this value, the connection will be aborted.
|
// @Document After normal validation or allow_insecure, if the server's cert chain hash does not match any of these values, the connection will be aborted.
|
||||||
// @Document This value replace allow_insecure.
|
|
||||||
// @Critical
|
// @Critical
|
||||||
PinnedPeerCertificateChainSha256 [][]byte `protobuf:"bytes,13,rep,name=pinned_peer_certificate_chain_sha256,json=pinnedPeerCertificateChainSha256,proto3" json:"pinned_peer_certificate_chain_sha256,omitempty"`
|
PinnedPeerCertificateChainSha256 [][]byte `protobuf:"bytes,13,rep,name=pinned_peer_certificate_chain_sha256,json=pinnedPeerCertificateChainSha256,proto3" json:"pinned_peer_certificate_chain_sha256,omitempty"`
|
||||||
// @Document A pinned certificate public key sha256 hash.
|
// @Document Some certificate public key sha256 hashes.
|
||||||
// @Document If the server's public key hash does not match this value, the connection will be aborted.
|
// @Document After normal validation (required), if the verified cert's public key hash does not match any of these values, the connection will be aborted.
|
||||||
// @Document This value replace allow_insecure.
|
|
||||||
// @Critical
|
// @Critical
|
||||||
PinnedPeerCertificatePublicKeySha256 [][]byte `protobuf:"bytes,14,rep,name=pinned_peer_certificate_public_key_sha256,json=pinnedPeerCertificatePublicKeySha256,proto3" json:"pinned_peer_certificate_public_key_sha256,omitempty"`
|
PinnedPeerCertificatePublicKeySha256 [][]byte `protobuf:"bytes,14,rep,name=pinned_peer_certificate_public_key_sha256,json=pinnedPeerCertificatePublicKeySha256,proto3" json:"pinned_peer_certificate_public_key_sha256,omitempty"`
|
||||||
MasterKeyLog string `protobuf:"bytes,15,opt,name=master_key_log,json=masterKeyLog,proto3" json:"master_key_log,omitempty"`
|
MasterKeyLog string `protobuf:"bytes,15,opt,name=master_key_log,json=masterKeyLog,proto3" json:"master_key_log,omitempty"`
|
||||||
// Lists of string as CurvePreferences values.
|
// Lists of string as CurvePreferences values.
|
||||||
CurvePreferences []string `protobuf:"bytes,16,rep,name=curve_preferences,json=curvePreferences,proto3" json:"curve_preferences,omitempty"`
|
CurvePreferences []string `protobuf:"bytes,16,rep,name=curve_preferences,json=curvePreferences,proto3" json:"curve_preferences,omitempty"`
|
||||||
ServerNameToVerify string `protobuf:"bytes,17,opt,name=server_name_to_verify,json=serverNameToVerify,proto3" json:"server_name_to_verify,omitempty"`
|
// @Document Replaces server_name to verify the peer cert.
|
||||||
|
// @Document After allow_insecure (automatically), if the server's cert can't be verified by any of these names, pinned_peer_certificate_chain_sha256 will be tried.
|
||||||
|
// @Critical
|
||||||
|
VerifyPeerCertInNames []string `protobuf:"bytes,17,rep,name=verify_peer_cert_in_names,json=verifyPeerCertInNames,proto3" json:"verify_peer_cert_in_names,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@ -353,11 +354,11 @@ func (x *Config) GetCurvePreferences() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetServerNameToVerify() string {
|
func (x *Config) GetVerifyPeerCertInNames() []string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.ServerNameToVerify
|
return x.VerifyPeerCertInNames
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var File_transport_internet_tls_config_proto protoreflect.FileDescriptor
|
var File_transport_internet_tls_config_proto protoreflect.FileDescriptor
|
||||||
@ -391,7 +392,7 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
|||||||
0x4e, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x14, 0x0a,
|
0x4e, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x14, 0x0a,
|
||||||
0x10, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46,
|
0x10, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x56, 0x45, 0x52, 0x49, 0x46,
|
||||||
0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59,
|
0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59,
|
||||||
0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0x93, 0x06, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
|
0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0x9a, 0x06, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
|
||||||
0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x73,
|
0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x73,
|
||||||
0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c,
|
0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c,
|
||||||
0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x63, 0x65,
|
0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x63, 0x65,
|
||||||
@ -437,18 +438,19 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
|||||||
0x52, 0x0c, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x4c, 0x6f, 0x67, 0x12, 0x2b,
|
0x52, 0x0c, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x4c, 0x6f, 0x67, 0x12, 0x2b,
|
||||||
0x0a, 0x11, 0x63, 0x75, 0x72, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e,
|
0x0a, 0x11, 0x63, 0x75, 0x72, 0x76, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e,
|
||||||
0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x63, 0x75, 0x72, 0x76, 0x65,
|
0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x63, 0x75, 0x72, 0x76, 0x65,
|
||||||
0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x73,
|
0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x19, 0x76,
|
||||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x76, 0x65,
|
0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x5f,
|
||||||
0x72, 0x69, 0x66, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x73, 0x65, 0x72, 0x76,
|
0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15,
|
||||||
0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x42, 0x73,
|
0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x49, 0x6e,
|
||||||
0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73,
|
0x4e, 0x61, 0x6d, 0x65, 0x73, 0x42, 0x73, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61,
|
||||||
0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c,
|
0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65,
|
||||||
0x73, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68,
|
||||||
0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74,
|
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f,
|
||||||
0x74, 0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61,
|
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b, 0x58,
|
||||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e,
|
||||||
0x54, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||||
|
0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -69,16 +69,14 @@ message Config {
|
|||||||
|
|
||||||
bool reject_unknown_sni = 12;
|
bool reject_unknown_sni = 12;
|
||||||
|
|
||||||
/* @Document A pinned certificate chain sha256 hash.
|
/* @Document Some certificate chain sha256 hashes.
|
||||||
@Document If the server's hash does not match this value, the connection will be aborted.
|
@Document After normal validation or allow_insecure, if the server's cert chain hash does not match any of these values, the connection will be aborted.
|
||||||
@Document This value replace allow_insecure.
|
|
||||||
@Critical
|
@Critical
|
||||||
*/
|
*/
|
||||||
repeated bytes pinned_peer_certificate_chain_sha256 = 13;
|
repeated bytes pinned_peer_certificate_chain_sha256 = 13;
|
||||||
|
|
||||||
/* @Document A pinned certificate public key sha256 hash.
|
/* @Document Some certificate public key sha256 hashes.
|
||||||
@Document If the server's public key hash does not match this value, the connection will be aborted.
|
@Document After normal validation (required), if the verified cert's public key hash does not match any of these values, the connection will be aborted.
|
||||||
@Document This value replace allow_insecure.
|
|
||||||
@Critical
|
@Critical
|
||||||
*/
|
*/
|
||||||
repeated bytes pinned_peer_certificate_public_key_sha256 = 14;
|
repeated bytes pinned_peer_certificate_public_key_sha256 = 14;
|
||||||
@ -88,5 +86,9 @@ message Config {
|
|||||||
// Lists of string as CurvePreferences values.
|
// Lists of string as CurvePreferences values.
|
||||||
repeated string curve_preferences = 16;
|
repeated string curve_preferences = 16;
|
||||||
|
|
||||||
string server_name_to_verify = 17;
|
/* @Document Replaces server_name to verify the peer cert.
|
||||||
|
@Document After allow_insecure (automatically), if the server's cert can't be verified by any of these names, pinned_peer_certificate_chain_sha256 will be tried.
|
||||||
|
@Critical
|
||||||
|
*/
|
||||||
|
repeated string verify_peer_cert_in_names = 17;
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ type Interface interface {
|
|||||||
net.Conn
|
net.Conn
|
||||||
HandshakeContext(ctx context.Context) error
|
HandshakeContext(ctx context.Context) error
|
||||||
VerifyHostname(host string) error
|
VerifyHostname(host string) error
|
||||||
|
HandshakeContextServerName(ctx context.Context) string
|
||||||
NegotiatedProtocol() string
|
NegotiatedProtocol() string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,15 +44,11 @@ func (c *Conn) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) HandshakeAddressContext(ctx context.Context) net.Address {
|
func (c *Conn) HandshakeContextServerName(ctx context.Context) string {
|
||||||
if err := c.HandshakeContext(ctx); err != nil {
|
if err := c.HandshakeContext(ctx); err != nil {
|
||||||
return nil
|
return ""
|
||||||
}
|
}
|
||||||
state := c.ConnectionState()
|
return c.ConnectionState().ServerName
|
||||||
if state.ServerName == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return net.ParseAddress(state.ServerName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) NegotiatedProtocol() string {
|
func (c *Conn) NegotiatedProtocol() string {
|
||||||
@ -85,15 +82,11 @@ func (c *UConn) Close() error {
|
|||||||
return c.Conn.Close()
|
return c.Conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *UConn) HandshakeAddressContext(ctx context.Context) net.Address {
|
func (c *UConn) HandshakeContextServerName(ctx context.Context) string {
|
||||||
if err := c.HandshakeContext(ctx); err != nil {
|
if err := c.HandshakeContext(ctx); err != nil {
|
||||||
return nil
|
return ""
|
||||||
}
|
}
|
||||||
state := c.ConnectionState()
|
return c.ConnectionState().ServerName
|
||||||
if state.ServerName == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return net.ParseAddress(state.ServerName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebsocketHandshake basically calls UConn.Handshake inside it but it will only send
|
// WebsocketHandshake basically calls UConn.Handshake inside it but it will only send
|
||||||
@ -134,17 +127,13 @@ func UClient(c net.Conn, config *tls.Config, fingerprint *utls.ClientHelloID) ne
|
|||||||
}
|
}
|
||||||
|
|
||||||
func copyConfig(c *tls.Config) *utls.Config {
|
func copyConfig(c *tls.Config) *utls.Config {
|
||||||
serverNameToVerify := ""
|
|
||||||
if r, ok := c.Rand.(*RandCarrier); ok {
|
|
||||||
serverNameToVerify = r.ServerNameToVerify
|
|
||||||
}
|
|
||||||
return &utls.Config{
|
return &utls.Config{
|
||||||
RootCAs: c.RootCAs,
|
Rand: c.Rand,
|
||||||
ServerName: c.ServerName,
|
RootCAs: c.RootCAs,
|
||||||
InsecureSkipVerify: c.InsecureSkipVerify,
|
ServerName: c.ServerName,
|
||||||
VerifyPeerCertificate: c.VerifyPeerCertificate,
|
InsecureSkipVerify: c.InsecureSkipVerify,
|
||||||
KeyLogWriter: c.KeyLogWriter,
|
VerifyPeerCertificate: c.VerifyPeerCertificate,
|
||||||
InsecureServerNameToVerify: serverNameToVerify,
|
KeyLogWriter: c.KeyLogWriter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user