Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: show how to use the experimental tls factory #20

Merged
merged 3 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions example/example-proxy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Example of using TLSClientFactory

This example shows how you can use `TLSClientFactory` to force this
library to use `refraction-networking/utls` for proxied conns.

* [main.go](main.go) sets up an `oohttp.Transport` instance and uses
the `Proxy` field to configure a SOCKS5 proxy;

* [utls.go](utls.go) contains the code to replace `tls` with `utls`
when using a proxy through the `TLSClientFactory`.
16 changes: 16 additions & 0 deletions example/example-proxy/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module github.com/ooni/oohttp/example/example-proxy

go 1.17

require (
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
github.com/ooni/oohttp v0.0.0-20220104151715-47436feafc4c
github.com/refraction-networking/utls v1.0.0
)

require (
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/text v0.3.7 // indirect
)
22 changes: 22 additions & 0 deletions example/example-proxy/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/ooni/oohttp v0.0.0-20220104151715-47436feafc4c h1:9iEGMyxk72orD7hPxU8dzQL4frjOUEX1YTqMvK2/idM=
github.com/ooni/oohttp v0.0.0-20220104151715-47436feafc4c/go.mod h1:IhQrrBqPX6/Pb8mGKdw3wskNOk5r8ngqmqAXrH3j7vw=
github.com/refraction-networking/utls v1.0.0 h1:6XQHSjDmeBCF9sPq8p2zMVGq7Ud3rTD2q88Fw8Tz1tA=
github.com/refraction-networking/utls v1.0.0/go.mod h1:tz9gX959MEFfFN5whTIocCLUG57WiILqtdVxI8c6Wj0=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211205041911-012df41ee64c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
70 changes: 70 additions & 0 deletions example/example-proxy/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package main

import (
"flag"
"fmt"
"io"
"log"
"net/http"
"net/url"
"time"

"github.com/armon/go-socks5"
oohttp "github.com/ooni/oohttp"
)

// startProxyServer starts a proxy server at the given endpoint.
func startProxyServer(endpoint string) {
conf := &socks5.Config{}
server, err := socks5.New(conf)
if err != nil {
log.Fatal(err)
}
if err := server.ListenAndServe("tcp", endpoint); err != nil {
log.Fatal(err)
}
}

// useProxy uses the oohttp library to possibly use refraction-networking/utls
// when communicating with a remote TLS endpoint through the given proxy.
func useProxy(URL, proxy string) {
w := &oohttp.StdlibTransport{
Transport: &oohttp.Transport{
Proxy: func(*oohttp.Request) (*url.URL, error) {
return &url.URL{Scheme: "socks5", Host: proxy}, nil
},
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}
clnt := &http.Client{Transport: w}
resp, err := clnt.Get(URL)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
r := io.LimitReader(resp.Body, 1<<22)
data, err := io.ReadAll(r)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", string(data))
}

func main() {
proxy := flag.String("proxy", "127.0.0.1:54321", "where the proxy shold listen")
bassosimone marked this conversation as resolved.
Show resolved Hide resolved
// The default URL we use should return us the JA3 fingerprint
// we're using to communicate with the server. We expect such a
// fingerprint to change when we use the `-utls` flag.
url := flag.String("url", "https://ja3er.com/json", "the URL to get")
utls := flag.Bool("utls", false, "try using uTLS")
flag.Parse()
if *utls {
useUTLS()
}
go startProxyServer(*proxy)
useProxy(*url, *proxy)
}
72 changes: 72 additions & 0 deletions example/example-proxy/tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package main

import (
"context"
"crypto/tls"
"net"

oohttp "github.com/ooni/oohttp"
utls "github.com/refraction-networking/utls"
)

// utlsConnAdapter adapts utls.UConn to the oohttp.TLSConn interface.
type utlsConnAdapter struct {
*utls.UConn
}

var _ oohttp.TLSConn = &utlsConnAdapter{}

// ConnectionState implements TLSConn's ConnectionState.
func (c *utlsConnAdapter) ConnectionState() tls.ConnectionState {
ustate := c.UConn.ConnectionState()
return tls.ConnectionState{
Version: ustate.Version,
HandshakeComplete: ustate.HandshakeComplete,
DidResume: ustate.DidResume,
CipherSuite: ustate.CipherSuite,
NegotiatedProtocol: ustate.NegotiatedProtocol,
NegotiatedProtocolIsMutual: ustate.NegotiatedProtocolIsMutual,
ServerName: ustate.ServerName,
PeerCertificates: ustate.PeerCertificates,
VerifiedChains: ustate.VerifiedChains,
SignedCertificateTimestamps: ustate.SignedCertificateTimestamps,
OCSPResponse: ustate.OCSPResponse,
TLSUnique: ustate.TLSUnique,
}
}

// HandshakeContext implements TLSConn's HandshakeContext.
func (c *utlsConnAdapter) HandshakeContext(ctx context.Context) error {
errch := make(chan error, 1)
go func() {
errch <- c.UConn.Handshake()
}()
select {
case err := <-errch:
return err
case <-ctx.Done():
return ctx.Err()
}
}

// useUTLS configures oohttp to use uTLS
func useUTLS() {
// Warning: this code modifies TLSClientFactory without locking it, which is
// a race-safe pattern only when you do that before you use HTTP code.
//
// What we basically do here is the following:
//
// 1. we create an utls.UConn
//
// 2. we use an adapter so the oohttp library sees it as a TLSConn
oohttp.TLSClientFactory = func(conn net.Conn, config *tls.Config) oohttp.TLSConn {
uConfig := &utls.Config{
RootCAs: config.RootCAs,
NextProtos: config.NextProtos,
ServerName: config.ServerName,
InsecureSkipVerify: config.InsecureSkipVerify,
DynamicRecordSizingDisabled: config.DynamicRecordSizingDisabled,
}
return &utlsConnAdapter{utls.UClient(conn, uConfig, utls.HelloFirefox_55)}
}
}
4 changes: 2 additions & 2 deletions example/example-utls/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ module github.com/ooni/oohttp/example/example-utls

go 1.17

require github.com/ooni/oohttp v0.0.0-20211206145729-209dd31a30a4
require github.com/ooni/oohttp v0.0.0-20220104151715-47436feafc4c

require (
github.com/refraction-networking/utls v1.0.0
golang.org/x/net v0.0.0-20211205041911-012df41ee64c // indirect
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect
golang.org/x/text v0.3.7 // indirect
)

Expand Down
7 changes: 4 additions & 3 deletions example/example-utls/go.sum
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
github.com/ooni/oohttp v0.0.0-20211206145729-209dd31a30a4 h1:epdBKp+qNzXw4xb18H8DWz8/GzwF4kL6AG84w5FdO2s=
github.com/ooni/oohttp v0.0.0-20211206145729-209dd31a30a4/go.mod h1:IhQrrBqPX6/Pb8mGKdw3wskNOk5r8ngqmqAXrH3j7vw=
github.com/ooni/oohttp v0.0.0-20220104151715-47436feafc4c h1:9iEGMyxk72orD7hPxU8dzQL4frjOUEX1YTqMvK2/idM=
github.com/ooni/oohttp v0.0.0-20220104151715-47436feafc4c/go.mod h1:IhQrrBqPX6/Pb8mGKdw3wskNOk5r8ngqmqAXrH3j7vw=
github.com/refraction-networking/utls v1.0.0 h1:6XQHSjDmeBCF9sPq8p2zMVGq7Ud3rTD2q88Fw8Tz1tA=
github.com/refraction-networking/utls v1.0.0/go.mod h1:tz9gX959MEFfFN5whTIocCLUG57WiILqtdVxI8c6Wj0=
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8=
golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211205041911-012df41ee64c h1:7SfqwP5fxEtl/P02w5IhKc86ziJ+A25yFrkVgoy2FT8=
golang.org/x/net v0.0.0-20211205041911-012df41ee64c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM=
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down