Comments (10)
test link is https://01-tx.audience.gcc.teams.microsoft.com:11024/.
from utls.
Can you provide a minimal reproducible example along with optional pcap?
from utls.
Apparently these two errors have something to do with how you set things up.
By simply doing the following
conn, err := net.Dial("tcp", "01-tx.audience.gcc.teams.microsoft.com:11024")
if err != nil {
panic(err)
}
tlsConn := tls.UClient(conn, &tls.Config{ServerName: "01-tx.audience.gcc.teams.microsoft.com"}, tls.HelloChrome_120)
if err := tlsConn.Handshake(); err != nil {
panic(err)
}
Handshake could complete without any problem for HelloChrome_120
and HelloFirefox_120
, and I am too lazy to test the rest of them.
from utls.
Below is my test code.
package main
import (
"bufio"
"fmt"
tls "github.com/refraction-networking/utls"
"golang.org/x/net/http2"
"io"
"log"
"math/rand"
"net"
"net/http"
"strings"
"time"
)
func main() {
cli := http.Client{
Transport: NewUTransport(30),
}
req, err := http.NewRequest(http.MethodGet, "https://01-tx.audience.gcc.teams.microsoft.com:11024/", nil)
//req, err = http.NewRequest(http.MethodGet, "https://google.com", nil)
if err != nil {
log.Fatalln(err)
}
resp, err := cli.Do(req)
if err != nil {
log.Fatalln(err)
}
defer resp.Body.Close()
all, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
}
fmt.Println("BodyLength", len(all))
fmt.Println("StatusCode", resp.StatusCode)
}
// ref: https://sxyz.blog/bypass-cloudflare-shield/
type UTransport struct {
timeout int
tr *http2.Transport
}
func NewUTransport(timeout int) *UTransport {
return &UTransport{
timeout: timeout,
tr: &http2.Transport{},
}
}
func (u *UTransport) newSpec() (*tls.ClientHelloSpec, error) {
ids := []tls.ClientHelloID{
//tls.HelloFirefox_102,
//tls.HelloFirefox_105,
//tls.HelloFirefox_120,
tls.HelloChrome_100,
tls.HelloChrome_102,
tls.HelloChrome_106_Shuffle,
tls.HelloChrome_120,
tls.HelloEdge_106,
tls.HelloSafari_16_0,
}
spec, err := tls.UTLSIdToSpec(ids[rand.Intn(len(ids))])
return &spec, err
}
func (u *UTransport) RoundTrip(req *http.Request) (*http.Response, error) {
if strings.ToLower(req.URL.Scheme) != "https" {
return nil, fmt.Errorf("unsupported scheme: %s", req.URL.Scheme)
}
res_ := &http.Response{}
err_ := make(chan error)
fin_ := make(chan interface{})
go func(r *http.Request) {
var err error
res_, err = u.connect(r)
if err != nil {
err_ <- err
return
}
fin_ <- nil
}(req)
select {
case <-time.After(time.Duration(u.timeout) * time.Second):
return nil, fmt.Errorf("%s timeout", req.URL)
case err := <-err_:
return nil, err
case <-fin_:
return res_, nil
}
}
func (u *UTransport) connect(req *http.Request) (*http.Response, error) {
port := req.URL.Port()
if port == "" {
port = "443"
}
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%s", strings.Split(req.URL.Host, ":")[0], port), time.Duration(u.timeout)*time.Second)
if err != nil {
return nil, fmt.Errorf("net.DialTimeout error: %+v", err)
}
uConn := tls.UClient(conn, &tls.Config{
ServerName: "01-tx.audience.gcc.teams.microsoft.com",
}, tls.HelloCustom)
spec, err := u.newSpec()
if err != nil {
return nil, err
}
if err = uConn.ApplyPreset(spec); err != nil {
return nil, fmt.Errorf("uConn.ApplyPreset() error: %+v", err)
}
if err = uConn.Handshake(); err != nil {
return nil, fmt.Errorf("uConn.Handshake() error: %+v", err)
}
alpn := uConn.ConnectionState().NegotiatedProtocol
switch alpn {
case "h2":
req.Proto = "HTTP/2.0"
req.ProtoMajor = 2
req.ProtoMinor = 0
if c, err := u.tr.NewClientConn(uConn); err == nil {
return c.RoundTrip(req)
} else {
return nil, fmt.Errorf("http2.Transport.NewClientConn() error: %+v", err)
}
case "http/1.1", "":
req.Proto = "HTTP/1.1"
req.ProtoMajor = 1
req.ProtoMinor = 1
if err = req.Write(uConn); err == nil {
return http.ReadResponse(bufio.NewReader(uConn), req)
} else {
return nil, fmt.Errorf("http.Request.Write() error: %+v", err)
}
default:
return nil, fmt.Errorf("unsupported ALPN: %v", alpn)
}
}
from utls.
Can you provide a minimal reproducible example
Please try to reduce the unnecessary/irrelevant code next time.
From your code I think the critical part is
func newSpec() (*tls.ClientHelloSpec, error) {
ids := []tls.ClientHelloID{
//tls.HelloFirefox_102,
//tls.HelloFirefox_105,
//tls.HelloFirefox_120,
tls.HelloChrome_100,
tls.HelloChrome_102,
tls.HelloChrome_106_Shuffle,
tls.HelloChrome_120,
tls.HelloEdge_106,
tls.HelloSafari_16_0,
}
spec, err := tls.UTLSIdToSpec(ids[rand.Intn(len(ids))])
return &spec, err
}
func main() {
conn, err := net.DialTimeout("tcp", "01-tx.audience.gcc.teams.microsoft.com:11024", 10*time.Second)
if err != nil {
panic(err)
}
uConn := tls.UClient(conn, &tls.Config{
ServerName: "01-tx.audience.gcc.teams.microsoft.com",
}, tls.HelloCustom)
spec, err := newSpec()
if err != nil {
panic(err)
}
if err = uConn.ApplyPreset(spec); err != nil {
panic(err)
}
if err = uConn.Handshake(); err != nil {
panic(err)
}
}
However the code above does not give me any error so far.
Further investigation with pcap (that's why you REALLY should provide one) shows the problem is actually due to the server sending a Hello Request AFTER a TLS Handshake is done. Major web browsers at this moment will renegotiate over the same TCP connection by sending another ClientHello and this is not supported by uTLS at the moment. I'm not sure if this is supported by our upstream crypto/tls
either.
from utls.
As of why the error message differs, I have no idea. Perhaps due to different states of an internal variable due to different set of TLS Extensions are being advertised/selected. But anyways, the server essentially sent the same message, a encrypted Hello Request with 0x00, 0x00, 0x00, 0x00
as its plaintext payload.
from utls.
For now unless our upstream supports it, this feature will not be implemented by our team. But if you want a PR is always welcomed. I will leave this issue open.
This is a confirmed bug.
from utls.
An update to this: the example code no longer work due to now the server requires the client to be advertising HTTP/1.1 instead of HTTP/2.
And I have been looking into this problem. It seems uTLS does not really support renegotiation and caused this problem. I am currently working on it.
from utls.
#291 is related.
from utls.
Note: you will still need to manually advertise HTTP/1.1 after #292 fixes the underlying bug.
from utls.
Related Issues (20)
- bump Auto parrot for Firefox and Chrome
- bug: configuration for GREASE ECH parrot for Chrome 120 doesn't match BoringSSL HOT 7
- HelloFirefox* gets an ECDSA verification failure HOT 4
- FingerprintClientHello support for GREASE ECH extension
- Weird observation regarding ClientId and Spec HOT 9
- B uTLS does not support 0xFB1A as max version,add ja3 tls error,roundTripper error HOT 7
- crypto/ecdh is not in GOROOT (Go 1.18) HOT 1
- What is the hash function of the fingerprint in utls? HOT 6
- HTTP2 (akamai) fingerprint always same? HOT 1
- Example ImportTLSClientHelloFromJSON HOT 6
- Towards better versioning policy HOT 4
- bug: `(*Conn).Handshake()` is called upon `(*UConn).Read()` HOT 3
- *.tlsfingerprint.io down? HOT 6
- Any plans implements in Python HOT 1
- UnmarshalClientHello returns nil
- Request for TLS 1.3 Fingerprint Draft 26 Support
- Test coverage is too low
- can test this websocket from website HOT 1
- How can I check clientHello in server HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from utls.