mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-15 22:10:26 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12ee51e4bb | ||
|
|
957e5a6b15 | ||
|
|
0710c2b195 | ||
|
|
4632984b66 | ||
|
|
b7a22c729b |
@@ -34,6 +34,22 @@ jobs:
|
||||
if: steps.check-assets.outputs.missing == 'true'
|
||||
run: sleep 90
|
||||
|
||||
check-proto:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v6
|
||||
- name: Check Proto Version Header
|
||||
run: |
|
||||
head -n 4 core/config.pb.go > ref.txt
|
||||
find . -name "*.pb.go" ! -name "*_grpc.pb.go" -print0 | while IFS= read -r -d '' file; do
|
||||
if ! cmp -s ref.txt <(head -n 4 "$file"); then
|
||||
echo "Error: Header mismatch in $file"
|
||||
head -n 4 "$file"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
test:
|
||||
needs: check-assets
|
||||
permissions:
|
||||
|
||||
@@ -214,6 +214,7 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
|
||||
|
||||
req.Header.Add("Accept", "application/dns-message")
|
||||
req.Header.Add("Content-Type", "application/dns-message")
|
||||
req.Header.Set("User-Agent", utils.ChromeUA)
|
||||
req.Header.Set("X-Padding", utils.H2Base62Pad(crypto.RandBetween(100, 1000)))
|
||||
|
||||
hc := s.httpClient
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/utils"
|
||||
"github.com/xtls/xray-core/features/routing"
|
||||
"github.com/xtls/xray-core/transport/internet/tagged"
|
||||
)
|
||||
@@ -61,6 +62,7 @@ func (s *pingClient) MeasureDelay(httpMethod string) (time.Duration, error) {
|
||||
if err != nil {
|
||||
return rttFailed, err
|
||||
}
|
||||
req.Header.Set("User-Agent", utils.ChromeUA)
|
||||
|
||||
start := time.Now()
|
||||
resp, err := s.httpClient.Do(req)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
"github.com/xtls/xray-core/common/signal/done"
|
||||
"github.com/xtls/xray-core/common/task"
|
||||
"github.com/xtls/xray-core/common/utils"
|
||||
"github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/features/extension"
|
||||
"github.com/xtls/xray-core/features/outbound"
|
||||
@@ -162,7 +163,9 @@ func (o *Observer) probe(outbound string) ProbeResult {
|
||||
if o.config.ProbeUrl != "" {
|
||||
probeURL = o.config.ProbeUrl
|
||||
}
|
||||
response, err := httpClient.Get(probeURL)
|
||||
req, _ := http.NewRequest(http.MethodGet, probeURL, nil)
|
||||
req.Header.Set("User-Agent", utils.ChromeUA)
|
||||
response, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return errors.New("outbound failed to relay connection").Base(err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/klauspost/cpuid/v2"
|
||||
)
|
||||
|
||||
func ChromeVersion() int {
|
||||
// Use only CPU info as seed for PRNG
|
||||
seed := int64(cpuid.CPU.Family + cpuid.CPU.Model + cpuid.CPU.PhysicalCores + cpuid.CPU.LogicalCores + cpuid.CPU.CacheLine)
|
||||
rng := rand.New(rand.NewSource(seed))
|
||||
// Start from Chrome 144 released on 2026.1.13
|
||||
releaseDate := time.Date(2026, 1, 13, 0, 0, 0, 0, time.UTC)
|
||||
version := 144
|
||||
now := time.Now()
|
||||
// Each version has random 25-45 day interval
|
||||
for releaseDate.Before(now) {
|
||||
releaseDate = releaseDate.AddDate(0, 0, rng.Intn(21)+25)
|
||||
version++
|
||||
}
|
||||
return version - 1
|
||||
}
|
||||
|
||||
// ChromeUA provides default browser User-Agent based on CPU-seeded PRNG.
|
||||
var ChromeUA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" + strconv.Itoa(ChromeVersion()) + ".0.0.0 Safari/537.36"
|
||||
+1
-1
@@ -19,7 +19,7 @@ import (
|
||||
var (
|
||||
Version_x byte = 26
|
||||
Version_y byte = 2
|
||||
Version_z byte = 4
|
||||
Version_z byte = 6
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/xtls/xray-core
|
||||
|
||||
go 1.25.6
|
||||
go 1.25.7
|
||||
|
||||
require (
|
||||
github.com/apernet/quic-go v0.57.2-0.20260111184307-eec823306178
|
||||
@@ -9,6 +9,7 @@ require (
|
||||
github.com/golang/mock v1.7.0-rc.1
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/klauspost/cpuid/v2 v2.0.12
|
||||
github.com/miekg/dns v1.1.72
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/pires/go-proxyproto v0.9.2
|
||||
@@ -39,7 +40,6 @@ require (
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/juju/ratelimit v1.0.2 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"sort"
|
||||
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/utils"
|
||||
"github.com/xtls/xray-core/transport/internet/headers/http"
|
||||
"github.com/xtls/xray-core/transport/internet/headers/noop"
|
||||
"google.golang.org/protobuf/proto"
|
||||
@@ -40,11 +41,8 @@ func (v *AuthenticatorRequest) Build() (*http.RequestConfig, error) {
|
||||
Value: []string{"www.baidu.com", "www.bing.com"},
|
||||
},
|
||||
{
|
||||
Name: "User-Agent",
|
||||
Value: []string{
|
||||
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 10_0_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/53.0.2785.109 Mobile/14A456 Safari/601.1.46",
|
||||
},
|
||||
Name: "User-Agent",
|
||||
Value: []string{utils.ChromeUA},
|
||||
},
|
||||
{
|
||||
Name: "Accept-Encoding",
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package tls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/xtls/xray-core/main/commands/base"
|
||||
. "github.com/xtls/xray-core/transport/internet/tls"
|
||||
)
|
||||
|
||||
var cmdHash = &base.Command{
|
||||
UsageLine: "{{.Exec}} tls hash",
|
||||
Short: "Calculate TLS certificate hash.",
|
||||
Long: `
|
||||
xray tls hash --cert <cert.pem>
|
||||
Calculate TLS certificate hash.
|
||||
`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdHash.Run = executeHash // break init loop
|
||||
}
|
||||
|
||||
var input = cmdHash.Flag.String("cert", "fullchain.pem", "The file path of the certificate")
|
||||
|
||||
func executeHash(cmd *base.Command, args []string) {
|
||||
fs := flag.NewFlagSet("hash", flag.ContinueOnError)
|
||||
if err := fs.Parse(args); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
certContent, err := os.ReadFile(*input)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
var certs []*x509.Certificate
|
||||
if bytes.Contains(certContent, []byte("BEGIN")) {
|
||||
for {
|
||||
block, remain := pem.Decode(certContent)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
fmt.Println("Unable to decode certificate:", err)
|
||||
return
|
||||
}
|
||||
certs = append(certs, cert)
|
||||
certContent = remain
|
||||
}
|
||||
} else {
|
||||
certs, err = x509.ParseCertificates(certContent)
|
||||
if err != nil {
|
||||
fmt.Println("Unable to parse certificates:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(certs) == 0 {
|
||||
fmt.Println("No certificates found")
|
||||
return
|
||||
}
|
||||
tabWriter := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
for i, cert := range certs {
|
||||
hash := GenerateCertHashHex(cert)
|
||||
if i == 0 {
|
||||
fmt.Fprintf(tabWriter, "Leaf SHA256:\t%s\n", hash)
|
||||
} else {
|
||||
fmt.Fprintf(tabWriter, "CA <%s> SHA256:\t%s\n", cert.Subject.CommonName, hash)
|
||||
}
|
||||
}
|
||||
tabWriter.Flush()
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package tls
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/xtls/xray-core/main/commands/base"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
)
|
||||
|
||||
var cmdLeafCertHash = &base.Command{
|
||||
UsageLine: "{{.Exec}} tls leafCertHash",
|
||||
Short: "Calculate TLS leaf certificate hash.",
|
||||
Long: `
|
||||
xray tls leafCertHash --cert <cert.pem>
|
||||
Calculate TLS leaf certificate hash.
|
||||
`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdLeafCertHash.Run = executeLeafCertHash // break init loop
|
||||
}
|
||||
|
||||
var input = cmdLeafCertHash.Flag.String("cert", "fullchain.pem", "The file path of the leaf certificate")
|
||||
|
||||
func executeLeafCertHash(cmd *base.Command, args []string) {
|
||||
fs := flag.NewFlagSet("leafCertHash", flag.ContinueOnError)
|
||||
if err := fs.Parse(args); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
certContent, err := os.ReadFile(*input)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
certChainHashB64, err := tls.CalculatePEMLeafCertSHA256Hash(certContent)
|
||||
if err != nil {
|
||||
fmt.Println("failed to decode cert", err)
|
||||
return
|
||||
}
|
||||
fmt.Println(certChainHashB64)
|
||||
}
|
||||
@@ -135,15 +135,15 @@ func printCertificates(tabWriter *tabwriter.Writer, certs []*x509.Certificate) {
|
||||
CAs = append(CAs, cert)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(tabWriter, "Certificate chain's total length: \t %d (certs count: %s)\n", length, strconv.Itoa(len(certs)))
|
||||
fmt.Fprintf(tabWriter, "Certificate chain's total length:\t%d (certs count: %s)\n", length, strconv.Itoa(len(certs)))
|
||||
if leaf != nil {
|
||||
fmt.Fprintf(tabWriter, "Cert's signature algorithm: \t %s\n", leaf.SignatureAlgorithm.String())
|
||||
fmt.Fprintf(tabWriter, "Cert's publicKey algorithm: \t %s\n", leaf.PublicKeyAlgorithm.String())
|
||||
fmt.Fprintf(tabWriter, "Cert's leaf SHA256: \t %s\n", hex.EncodeToString(GenerateCertHash(leaf)))
|
||||
fmt.Fprintf(tabWriter, "Cert's signature algorithm:\t%s\n", leaf.SignatureAlgorithm.String())
|
||||
fmt.Fprintf(tabWriter, "Cert's publicKey algorithm:\t%s\n", leaf.PublicKeyAlgorithm.String())
|
||||
fmt.Fprintf(tabWriter, "Cert's leaf SHA256:\t%s\n", hex.EncodeToString(GenerateCertHash(leaf)))
|
||||
for _, ca := range CAs {
|
||||
fmt.Fprintf(tabWriter, "Cert's CA: %s SHA256: \t %s\n", ca.Subject.CommonName, hex.EncodeToString(GenerateCertHash(ca)))
|
||||
fmt.Fprintf(tabWriter, "Cert's CA <%s> SHA256:\t%s\n", ca.Subject.CommonName, hex.EncodeToString(GenerateCertHash(ca)))
|
||||
}
|
||||
fmt.Fprintf(tabWriter, "Cert's allowed domains: \t %v\n", leaf.DNSNames)
|
||||
fmt.Fprintf(tabWriter, "Cert's allowed domains:\t%v\n", leaf.DNSNames)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,11 +156,11 @@ func printTLSConnDetail(tabWriter *tabwriter.Writer, tlsConn *utls.UConn) {
|
||||
case gotls.VersionTLS12:
|
||||
tlsVersion = "TLS 1.2"
|
||||
}
|
||||
fmt.Fprintf(tabWriter, "TLS Version: \t %s\n", tlsVersion)
|
||||
fmt.Fprintf(tabWriter, "TLS Version:\t%s\n", tlsVersion)
|
||||
curveID := utils.AccessField[utls.CurveID](tlsConn.Conn, "curveID")
|
||||
if curveID != nil {
|
||||
PostQuantum := (*curveID == utls.X25519MLKEM768)
|
||||
fmt.Fprintf(tabWriter, "TLS Post-Quantum key exchange: \t %t (%s)\n", PostQuantum, curveID.String())
|
||||
fmt.Fprintf(tabWriter, "TLS Post-Quantum key exchange:\t%t (%s)\n", PostQuantum, curveID.String())
|
||||
} else {
|
||||
fmt.Fprintf(tabWriter, "TLS Post-Quantum key exchange: false (RSA Exchange)\n")
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ var CmdTLS = &base.Command{
|
||||
Commands: []*base.Command{
|
||||
cmdCert,
|
||||
cmdPing,
|
||||
cmdLeafCertHash,
|
||||
cmdHash,
|
||||
cmdECH,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
"github.com/xtls/xray-core/common/signal"
|
||||
"github.com/xtls/xray-core/common/task"
|
||||
"github.com/xtls/xray-core/common/utils"
|
||||
"github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/features/policy"
|
||||
"github.com/xtls/xray-core/transport"
|
||||
@@ -219,6 +220,9 @@ func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, u
|
||||
for _, h := range header {
|
||||
req.Header.Set(h.Key, h.Value)
|
||||
}
|
||||
if req.Header.Get("User-Agent") == "" {
|
||||
req.Header.Set("User-Agent", utils.ChromeUA)
|
||||
}
|
||||
|
||||
connectHTTP1 := func(rawConn net.Conn) (net.Conn, error) {
|
||||
req.Header.Set("Proxy-Connection", "Keep-Alive")
|
||||
|
||||
@@ -20,6 +20,7 @@ const (
|
||||
maxPollDelay = 10 * time.Second
|
||||
pollDelayMultiplier = 2.0
|
||||
pollLimit = 16
|
||||
windowSize = 1000
|
||||
)
|
||||
|
||||
type packet struct {
|
||||
@@ -30,7 +31,6 @@ type packet struct {
|
||||
type seqStatus struct {
|
||||
needSeqByte bool
|
||||
seqByte byte
|
||||
received bool
|
||||
}
|
||||
|
||||
type xicmpConnClient struct {
|
||||
@@ -129,12 +129,14 @@ func (c *xicmpConnClient) encode(p []byte) ([]byte, error) {
|
||||
c.seqStatus[c.seq] = &seqStatus{
|
||||
needSeqByte: needSeqByte,
|
||||
seqByte: seqByte,
|
||||
received: false,
|
||||
}
|
||||
|
||||
delete(c.seqStatus, int(uint16(c.seq-windowSize)))
|
||||
|
||||
c.seq++
|
||||
|
||||
if c.seq == 65536 {
|
||||
delete(c.seqStatus, int(uint16(c.seq-windowSize)))
|
||||
c.seq = 1
|
||||
}
|
||||
|
||||
@@ -168,16 +170,14 @@ func (c *xicmpConnClient) recvLoop() {
|
||||
continue
|
||||
}
|
||||
|
||||
c.mutex.Lock()
|
||||
seqStatus, ok := c.seqStatus[echo.Seq]
|
||||
c.mutex.Unlock()
|
||||
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if seqStatus.received {
|
||||
continue
|
||||
}
|
||||
|
||||
if seqStatus.needSeqByte {
|
||||
if len(echo.Data) <= 1 {
|
||||
continue
|
||||
@@ -189,7 +189,9 @@ func (c *xicmpConnClient) recvLoop() {
|
||||
}
|
||||
|
||||
if len(echo.Data) > 0 {
|
||||
seqStatus.received = true
|
||||
c.mutex.Lock()
|
||||
delete(c.seqStatus, echo.Seq)
|
||||
c.mutex.Unlock()
|
||||
|
||||
buf := make([]byte, len(echo.Data))
|
||||
copy(buf, echo.Data)
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
"github.com/xtls/xray-core/common/utils"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/grpc/encoding"
|
||||
"github.com/xtls/xray-core/transport/internet/reality"
|
||||
@@ -167,9 +168,11 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
|
||||
dialOptions = append(dialOptions, grpc.WithInitialWindowSize(grpcSettings.InitialWindowsSize))
|
||||
}
|
||||
|
||||
if grpcSettings.UserAgent != "" {
|
||||
dialOptions = append(dialOptions, grpc.WithUserAgent(grpcSettings.UserAgent))
|
||||
userAgent := grpcSettings.UserAgent
|
||||
if userAgent == "" {
|
||||
userAgent = utils.ChromeUA
|
||||
}
|
||||
dialOptions = append(dialOptions, grpc.WithUserAgent(userAgent))
|
||||
|
||||
var grpcDestHost string
|
||||
if dest.Address.Family().IsDomain() {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/utils"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
@@ -86,6 +87,9 @@ func dialhttpUpgrade(ctx context.Context, dest net.Destination, streamSettings *
|
||||
for key, value := range transportConfiguration.Header {
|
||||
AddHeader(req.Header, key, value)
|
||||
}
|
||||
if req.Header.Get("User-Agent") == "" {
|
||||
req.Header.Set("User-Agent", utils.ChromeUA)
|
||||
}
|
||||
req.Header.Set("Connection", "Upgrade")
|
||||
req.Header.Set("Upgrade", "websocket")
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/crypto"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/utils"
|
||||
"github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
@@ -222,7 +223,7 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
|
||||
if req == nil {
|
||||
return
|
||||
}
|
||||
req.Header.Set("User-Agent", fingerprint.Client) // TODO: User-Agent map
|
||||
req.Header.Set("User-Agent", utils.ChromeUA)
|
||||
if first && config.Show {
|
||||
fmt.Printf("REALITY localAddr: %v\treq.UserAgent(): %v\n", localAddr, req.UserAgent())
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/crypto"
|
||||
"github.com/xtls/xray-core/common/utils"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
|
||||
@@ -47,6 +48,9 @@ func (c *Config) GetRequestHeader() http.Header {
|
||||
for k, v := range c.Headers {
|
||||
header.Add(k, v)
|
||||
}
|
||||
if header.Get("User-Agent") == "" {
|
||||
header.Set("User-Agent", utils.ChromeUA)
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
|
||||
@@ -289,9 +289,6 @@ func (r *RandCarrier) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509
|
||||
if len(certs) == 0 {
|
||||
return errors.New("unexpected certs")
|
||||
}
|
||||
if certs[0].IsCA {
|
||||
slices.Reverse(certs)
|
||||
}
|
||||
|
||||
// directly return success if pinned cert is leaf
|
||||
// or replace RootCAs if pinned cert is CA (and can be used in VerifyPeerCertByName)
|
||||
@@ -558,14 +555,19 @@ const (
|
||||
)
|
||||
|
||||
func verifyChain(certs []*x509.Certificate, pinnedPeerCertSha256 [][]byte) (verifyResult, *x509.Certificate) {
|
||||
leafHash := GenerateCertHash(certs[0])
|
||||
for _, c := range pinnedPeerCertSha256 {
|
||||
if hmac.Equal(leafHash, c) {
|
||||
return foundLeaf, nil
|
||||
}
|
||||
}
|
||||
certs = certs[1:] // skip leaf
|
||||
for _, cert := range certs {
|
||||
certHash := GenerateCertHash(cert)
|
||||
for _, c := range pinnedPeerCertSha256 {
|
||||
if hmac.Equal(certHash, c) {
|
||||
if cert.IsCA {
|
||||
return foundCA, cert
|
||||
} else {
|
||||
return foundLeaf, cert
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,6 +257,7 @@ func dnsQuery(server string, domain string, sockopt *internet.SocketConfig) ([]b
|
||||
}
|
||||
req.Header.Set("Accept", "application/dns-message")
|
||||
req.Header.Set("Content-Type", "application/dns-message")
|
||||
req.Header.Set("User-Agent", utils.ChromeUA)
|
||||
req.Header.Set("X-Padding", utils.H2Base62Pad(crypto.RandBetween(100, 1000)))
|
||||
|
||||
resp, err := client.Do(req)
|
||||
|
||||
@@ -4,28 +4,8 @@ import (
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
)
|
||||
|
||||
func CalculatePEMLeafCertSHA256Hash(certContent []byte) (string, error) {
|
||||
var leafCert *x509.Certificate
|
||||
for {
|
||||
var err error
|
||||
block, remain := pem.Decode(certContent)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
leafCert, err = x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
certContent = remain
|
||||
}
|
||||
certHash := GenerateCertHash(leafCert)
|
||||
certHashHex := hex.EncodeToString(certHash)
|
||||
return certHashHex, nil
|
||||
}
|
||||
|
||||
// []byte must be ASN.1 DER content
|
||||
func GenerateCertHash[T *x509.Certificate | []byte](cert T) []byte {
|
||||
var out [32]byte
|
||||
@@ -37,3 +17,14 @@ func GenerateCertHash[T *x509.Certificate | []byte](cert T) []byte {
|
||||
}
|
||||
return out[:]
|
||||
}
|
||||
|
||||
func GenerateCertHashHex[T *x509.Certificate | []byte](cert T) string {
|
||||
var out [32]byte
|
||||
switch v := any(cert).(type) {
|
||||
case *x509.Certificate:
|
||||
out = sha256.Sum256(v.Raw)
|
||||
case []byte:
|
||||
out = sha256.Sum256(v)
|
||||
}
|
||||
return hex.EncodeToString(out[:])
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/utils"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
|
||||
@@ -23,6 +24,9 @@ func (c *Config) GetRequestHeader() http.Header {
|
||||
for k, v := range c.Header {
|
||||
header.Add(k, v)
|
||||
}
|
||||
if header.Get("User-Agent") == "" {
|
||||
header.Set("User-Agent", utils.ChromeUA)
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user