Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pierov/lyrebird
  • eta/lyrebird
  • tpo/anti-censorship/pluggable-transports/lyrebird
  • meskio/obfs4
  • vbauerster/lyrebird
  • Gedsh/lyrebird
  • danialbehzadi/lyrebird
  • shelikhoo/lyrebird
  • jmwample/lyrebird
  • cohosh/lyrebird
  • Odups/lyrebird
  • tla/lyrebird
  • akwizgran/lyrebird
13 results
Show changes
Commits on Source (51)
Showing
with 575 additions and 144 deletions
Changes in version 0.5.0 - 2024-11-07:
- Add snowflake transport to Lyrebird
- Add event logging support for all transports
Changes in version 0.4.0 - 2024-10-08:
- Use go 1.21
Changes in version 0.3.0 - 2024-08-07:
- report lyrebird version and implementation to Tor
- fix IPv6 support in webtunnel
- simplify copyloop
Changes in version 0.2.0 - 2024-03-27:
- Socks5 Support general improvement
- Fixed expected import path of package x25519ell2
- Add WebTunnel Client Support
- Updated dependencies
Changes in version 0.1.0 - 2023-05-31:
- Rename the project to lyrebird
- Bring back meek uTLS support
......
VERSION = $(shell git describe | sed 's/lyrebird-//')
build:
CGO_ENABLED=0 go build -ldflags="-X main.lyrebirdVersion=$(VERSION)" ./cmd/lyrebird
......@@ -42,7 +42,7 @@ the same dependency versions, while `go get -d` always downloads master.
To build:
`go build ./cmd/lyrebird`
`make build`
To install, copy `./lyrebird` to a permanent location
(Eg: `/usr/local/bin`)
......
......@@ -38,23 +38,24 @@ import (
"net/url"
"os"
"path"
"sync"
"slices"
"syscall"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/log"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/socks5"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/transports"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/transports/base"
sf "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/client/lib"
"golang.org/x/net/proxy"
)
const (
lyrebirdVersion = "0.0.14"
lyrebirdLogFile = "lyrebird.log"
socksAddr = "127.0.0.1:0"
)
var lyrebirdVersion = "devel"
var stateDir string
var termMon *termMonitor
......@@ -63,8 +64,9 @@ func clientSetup() (launched bool, listeners []net.Listener) {
if err != nil {
golog.Fatal(err)
}
pt.ReportVersion("lyrebird", lyrebirdVersion)
ptClientProxy, err := ptGetProxy()
ptClientProxy, err := ptGetProxy(slices.Contains(ptClientInfo.MethodNames, "snowflake"))
if err != nil {
golog.Fatal(err)
} else if ptClientProxy != nil {
......@@ -85,6 +87,10 @@ func clientSetup() (launched bool, listeners []net.Listener) {
continue
}
f.OnEvent(func(e base.TransportEvent) {
pt.Log(pt.LogSeverityNotice, e.String())
})
ln, err := net.Listen("tcp", socksAddr)
if err != nil {
_ = pt.CmethodError(name, err.Error())
......@@ -155,6 +161,17 @@ func clientHandler(f base.ClientFactory, conn net.Conn, proxyURI *url.URL) {
return
}
dialFn = dialer.Dial
// The snowflake library takes care of configuring the proxy, so rather than
// relying on dialfn, we need to add the proxy URL to the Snowflake args
if name == "snowflake" {
config, ok := args.(sf.ClientConfig)
if !ok {
log.Errorf("Error adding snowflake proxy URL to args")
return
}
config.CommunicationProxy = proxyURI
}
}
remote, err := f.Dial("tcp", socksReq.Target, dialFn, args)
if err != nil {
......@@ -181,6 +198,7 @@ func serverSetup() (launched bool, listeners []net.Listener) {
if err != nil {
golog.Fatal(err)
}
pt.ReportVersion("lyrebird", lyrebirdVersion)
for _, bindaddr := range ptServerInfo.Bindaddrs {
name := bindaddr.MethodName
......@@ -267,41 +285,29 @@ func serverHandler(f base.ServerFactory, conn net.Conn, info *pt.ServerInfo) {
}
func copyLoop(a net.Conn, b net.Conn) error {
firstErr := func(errors ...error) error {
for _, err := range errors {
if err != nil {
return err
}
}
return nil
}
// Note: b is always the pt connection. a is the SOCKS/ORPort connection.
errChan := make(chan error, 2)
var wg sync.WaitGroup
wg.Add(2)
errChan := make(chan error, 1)
go func() {
defer wg.Done()
defer b.Close()
defer a.Close()
_, err := io.Copy(b, a)
errChan <- err
}()
go func() {
defer wg.Done()
defer a.Close()
defer b.Close()
_, err := io.Copy(a, b)
errChan <- err
}()
_, err := io.Copy(a, b)
// Wait for both upstream and downstream to close. Since one side
// terminating closes the other, the second error in the channel will be
// something like EINVAL (though io.Copy() will swallow EOF), so only the
// first error is returned.
wg.Wait()
if len(errChan) > 0 {
return <-errChan
}
return nil
}
func getVersion() string {
return fmt.Sprintf("lyrebird-%s", lyrebirdVersion)
return firstErr(<-errChan, err, a.Close(), b.Close())
}
func main() {
......@@ -317,7 +323,7 @@ func main() {
flag.Parse()
if *showVer {
fmt.Printf("%s\n", getVersion())
fmt.Printf("lyrebird %s\n", lyrebirdVersion)
os.Exit(0)
}
if err := log.SetLogLevel(*logLevelStr); err != nil {
......@@ -342,7 +348,7 @@ func main() {
os.Exit(-1)
}
log.Noticef("%s - launched", getVersion())
log.Noticef("%s - launched", lyrebirdVersion)
// Do the managed pluggable transport protocol configuration.
if isClient {
......
......@@ -70,11 +70,6 @@ func (s *httpProxy) Dial(network, addr string) (net.Conn, error) {
}
conn := new(httpConn)
conn.httpConn = httputil.NewClientConn(c, nil) // nolint: staticcheck
conn.remoteAddr, err = net.ResolveTCPAddr(network, addr)
if err != nil {
conn.httpConn.Close()
return nil, err
}
// HACK HACK HACK HACK. http.ReadRequest also does this.
reqURL, err := url.Parse("http://" + addr)
......@@ -112,7 +107,6 @@ func (s *httpProxy) Dial(network, addr string) (net.Conn, error) {
}
type httpConn struct {
remoteAddr *net.TCPAddr
httpConn *httputil.ClientConn // nolint: staticcheck
hijackedConn net.Conn
staleReader *bufio.Reader
......@@ -141,7 +135,7 @@ func (c *httpConn) LocalAddr() net.Addr {
}
func (c *httpConn) RemoteAddr() net.Addr {
return c.remoteAddr
return &net.UnixAddr{Net: "unknown_HTTPProxy"}
}
func (c *httpConn) SetDeadline(t time.Time) error {
......
......@@ -150,7 +150,7 @@ func socks4ErrorToString(code byte) string {
case socks4Rejected:
return "request rejected or failed"
case socks4RejectedIdentdFailed:
return "request rejected becasue SOCKS server cannot connect to identd on the client"
return "request rejected because SOCKS server cannot connect to identd on the client"
case socks4RejectedIdentdMismatch:
return "request rejected because the client program and identd report different user-ids"
default:
......
......@@ -35,7 +35,8 @@ import (
"os"
"strconv"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/proxy"
)
// This file contains things that probably should be in goptlib but are not
......@@ -71,7 +72,7 @@ func ptIsClient() (bool, error) {
return false, errors.New("not launched as a managed transport")
}
func ptGetProxy() (*url.URL, error) {
func ptGetProxy(isSnowflake bool) (*url.URL, error) {
specString := os.Getenv("TOR_PT_PROXY")
if specString == "" {
return nil, nil
......@@ -95,6 +96,22 @@ func ptGetProxy() (*url.URL, error) {
return nil, ptProxyError("proxy URI has a fragment defined")
}
// Snowflake has extra restrictions on which proxy types are supported.
// Perform the necessary checks if snowflake is one of the configured
// transports.
if isSnowflake {
if err := proxy.CheckProxyProtocolSupport(spec); err != nil {
return nil, pt.ProxyError("proxy is not supported:" + err.Error())
} else {
client := proxy.NewSocks5UDPClient(spec)
conn, err := client.ListenPacket("udp", nil)
if err != nil {
return nil, pt.ProxyError("proxy test failure:" + err.Error())
}
conn.Close()
}
}
switch spec.Scheme {
case "http":
// The most forgiving of proxies.
......
package utlsutil
import (
"fmt"
utls "github.com/refraction-networking/utls"
"strings"
)
var (
// This should be kept in sync with what is available in utls.
clientHelloIDMap = map[string]*utls.ClientHelloID{
"hellogolang": nil, // Don't bother with utls.
"hellorandomized": &utls.HelloRandomized,
"hellorandomizedalpn": &utls.HelloRandomizedALPN,
"hellorandomizednoalpn": &utls.HelloRandomizedNoALPN,
"hellofirefox_auto": &utls.HelloFirefox_Auto,
"hellofirefox_55": &utls.HelloFirefox_55,
"hellofirefox_56": &utls.HelloFirefox_56,
"hellofirefox_63": &utls.HelloFirefox_63,
"hellofirefox_65": &utls.HelloFirefox_65,
"hellofirefox_99": &utls.HelloFirefox_99,
"hellofirefox_102": &utls.HelloFirefox_102,
"hellofirefox_105": &utls.HelloFirefox_105,
"hellochrome_auto": &utls.HelloChrome_Auto,
"hellochrome_58": &utls.HelloChrome_58,
"hellochrome_62": &utls.HelloChrome_62,
"hellochrome_70": &utls.HelloChrome_70,
"hellochrome_72": &utls.HelloChrome_72,
"hellochrome_83": &utls.HelloChrome_83,
"hellochrome_87": &utls.HelloChrome_87,
"hellochrome_96": &utls.HelloChrome_96,
"hellochrome_100": &utls.HelloChrome_100,
"hellochrome_102": &utls.HelloChrome_102,
"helloios_auto": &utls.HelloIOS_Auto,
"helloios_11_1": &utls.HelloIOS_11_1,
"helloios_12_1": &utls.HelloIOS_12_1,
"helloios_13": &utls.HelloIOS_13,
"helloios_14": &utls.HelloIOS_14,
"helloandroid_11": &utls.HelloAndroid_11_OkHttp,
"helloedge_auto": &utls.HelloEdge_Auto,
"helloedge_85": &utls.HelloEdge_85,
"helloedge_106": &utls.HelloEdge_106,
"hellosafari_auto": &utls.HelloSafari_Auto,
"hellosafari_16_0": &utls.HelloSafari_16_0,
"hello360_auto": &utls.Hello360_Auto,
"hello360_7_5": &utls.Hello360_7_5,
"hello360_11_0": &utls.Hello360_11_0,
"helloqq_auto": &utls.HelloQQ_Auto,
"helloqq_11_1": &utls.HelloQQ_11_1,
}
defaultClientHello = &utls.HelloChrome_Auto
)
func ParseClientHelloID(s string) (*utls.ClientHelloID, error) {
s = strings.ToLower(s)
switch s {
case "none":
return nil, nil
case "":
return defaultClientHello, nil
default:
if ret := clientHelloIDMap[s]; ret != nil {
return ret, nil
}
}
return nil, fmt.Errorf("invalid ClientHelloID: '%v'", s)
}
......@@ -3,20 +3,80 @@ module gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird
require (
filippo.io/edwards25519 v1.1.0
github.com/dchest/siphash v1.2.3
github.com/refraction-networking/utls v1.6.3
github.com/refraction-networking/utls v1.6.7
gitlab.com/yawning/edwards25519-extra v0.0.0-20231005122941-2149dcafc266
gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib v1.5.0
golang.org/x/crypto v0.19.0
golang.org/x/net v0.21.0
gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib v1.6.0
gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2 v2.10.1
gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/webtunnel v0.0.2
golang.org/x/crypto v0.36.0
golang.org/x/net v0.37.0
)
require (
github.com/andybalholm/brotli v1.0.6 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/quic-go/quic-go v0.40.1 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/aws/aws-sdk-go-v2 v1.32.8 // indirect
github.com/aws/aws-sdk-go-v2/config v1.28.10 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.51 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.23 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.27 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.27 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.8 // indirect
github.com/aws/aws-sdk-go-v2/service/sqs v1.37.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.9 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.8 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.6 // indirect
github.com/aws/smithy-go v1.22.1 // indirect
github.com/cloudflare/circl v1.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
github.com/klauspost/reedsolomon v1.12.4 // indirect
github.com/miekg/dns v1.1.62 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pion/datachannel v1.5.10 // indirect
github.com/pion/dtls/v2 v2.2.12 // indirect
github.com/pion/dtls/v3 v3.0.4 // indirect
github.com/pion/ice/v2 v2.3.37 // indirect
github.com/pion/interceptor v0.1.37 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/mdns v0.0.12 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.15 // indirect
github.com/pion/rtp v1.8.10 // indirect
github.com/pion/sctp v1.8.35 // indirect
github.com/pion/sdp/v3 v3.0.10 // indirect
github.com/pion/srtp/v2 v2.0.20 // indirect
github.com/pion/stun v0.6.1 // indirect
github.com/pion/stun/v3 v3.0.0 // indirect
github.com/pion/transport/v2 v2.2.10 // indirect
github.com/pion/transport/v3 v3.0.7 // indirect
github.com/pion/turn/v2 v2.1.6 // indirect
github.com/pion/webrtc/v3 v3.3.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/realclientip/realclientip-go v1.0.0 // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/templexxx/cpu v0.1.1 // indirect
github.com/templexxx/xorsimd v0.4.3 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/txthinking/runnergroup v0.0.0-20241229123329-7b873ad00768 // indirect
github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301 // indirect
github.com/wlynxg/anet v0.0.5 // indirect
github.com/xtaci/kcp-go/v5 v5.6.18 // indirect
github.com/xtaci/smux v1.5.33 // indirect
gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/ptutil v0.0.0-20240710081135-6c4d8ed41027 // indirect
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.23.0 // indirect
golang.org/x/tools v0.29.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
go 1.20
go 1.23.0
toolchain go1.23.7
This diff is collapsed.
......@@ -15,7 +15,7 @@
// Package x25519ell2 implements obfuscated X25519 ECDH, via the Elligator2
// mapping.
package x25519ell2 // import "gitlab.com/yawning/obfs4.git/internal/x25519ell2"
package x25519ell2 // import "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/internal/x25519ell2"
import (
"encoding/binary"
......
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"constraints": {
"go": "1.20"
"go": "1.21"
},
"postUpdateOptions": ["gomodTidy", "gomodUpdateImportPaths"],
"osvVulnerabilityAlerts": true
......
......@@ -32,7 +32,7 @@ package base // import "gitlab.torproject.org/tpo/anti-censorship/pluggable-tran
import (
"net"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
)
type DialFunc func(string, string) (net.Conn, error)
......@@ -54,6 +54,11 @@ type ClientFactory interface {
// (eg: handshaking) to get the connection to the point where it is
// ready to relay data.
Dial(network, address string, dialFn DialFunc, args interface{}) (net.Conn, error)
// OnEvent sets a callback that can be called by transports when notable
// events in the connection happen. This is especially useful for logging
// and UX purposes.
OnEvent(f func(TransportEvent))
}
// ServerFactory is the interface that defines the factory for creating
......@@ -88,3 +93,7 @@ type Transport interface {
// protocol. This can fail if the provided arguments are invalid.
ServerFactory(stateDir string, args *pt.Args) (ServerFactory, error)
}
type TransportEvent interface {
String() string
}
......@@ -36,7 +36,7 @@ import (
"fmt"
"net"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/transports/base"
)
......@@ -85,6 +85,9 @@ func (cf *meekClientFactory) Dial(network, addr string, dialFn base.DialFunc, ar
return newMeekConn(network, addr, dialFn, ca)
}
// Not yet implemented
func (cf *meekClientFactory) OnEvent(f func(base.TransportEvent)) {}
var (
_ base.ClientFactory = (*meekClientFactory)(nil)
_ base.Transport = (*Transport)(nil)
......
package meeklite
import (
"crypto/x509"
"log"
)
// https://crt.sh/?id=9314791
const LetsEncryptRootCert = `-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----`
// GetRootCAs is a workaround for older versions of Android that do not trust
// Let's Encrypt's ISRG Root X1. This manually adds the ISRG root to the device's
// existing cert pool.
func GetRootCAs() *x509.CertPool {
rootCerts, err := x509.SystemCertPool()
if err != nil {
rootCerts = x509.NewCertPool()
}
if ok := rootCerts.AppendCertsFromPEM([]byte(LetsEncryptRootCert)); !ok {
log.Println("Error appending Let's Encrypt root certificate to cert poool")
return nil
}
return rootCerts
}
......@@ -34,6 +34,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/utlsutil"
"io"
"io/ioutil"
"net"
......@@ -111,7 +112,7 @@ func newClientArgs(args *pt.Args) (ca *meekClientArgs, err error) {
// Parse the (optional) utls argument.
utlsOpt, _ := args.Get(utlsArg)
if ca.utls, err = parseClientHelloID(utlsOpt); err != nil {
if ca.utls, err = utlsutil.ParseClientHelloID(utlsOpt); err != nil {
return nil, err
}
......
......@@ -35,49 +35,6 @@ import (
var (
errProtocolNegotiated = errors.New("meek_lite: protocol negotiated")
// This should be kept in sync with what is available in utls.
clientHelloIDMap = map[string]*utls.ClientHelloID{
"hellogolang": nil, // Don't bother with utls.
"hellorandomized": &utls.HelloRandomized,
"hellorandomizedalpn": &utls.HelloRandomizedALPN,
"hellorandomizednoalpn": &utls.HelloRandomizedNoALPN,
"hellofirefox_auto": &utls.HelloFirefox_Auto,
"hellofirefox_55": &utls.HelloFirefox_55,
"hellofirefox_56": &utls.HelloFirefox_56,
"hellofirefox_63": &utls.HelloFirefox_63,
"hellofirefox_65": &utls.HelloFirefox_65,
"hellofirefox_99": &utls.HelloFirefox_99,
"hellofirefox_102": &utls.HelloFirefox_102,
"hellofirefox_105": &utls.HelloFirefox_105,
"hellochrome_auto": &utls.HelloChrome_Auto,
"hellochrome_58": &utls.HelloChrome_58,
"hellochrome_62": &utls.HelloChrome_62,
"hellochrome_70": &utls.HelloChrome_70,
"hellochrome_72": &utls.HelloChrome_72,
"hellochrome_83": &utls.HelloChrome_83,
"hellochrome_87": &utls.HelloChrome_87,
"hellochrome_96": &utls.HelloChrome_96,
"hellochrome_100": &utls.HelloChrome_100,
"hellochrome_102": &utls.HelloChrome_102,
"helloios_auto": &utls.HelloIOS_Auto,
"helloios_11_1": &utls.HelloIOS_11_1,
"helloios_12_1": &utls.HelloIOS_12_1,
"helloios_13": &utls.HelloIOS_13,
"helloios_14": &utls.HelloIOS_14,
"helloandroid_11": &utls.HelloAndroid_11_OkHttp,
"helloedge_auto": &utls.HelloEdge_Auto,
"helloedge_85": &utls.HelloEdge_85,
"helloedge_106": &utls.HelloEdge_106,
"hellosafari_auto": &utls.HelloSafari_Auto,
"hellosafari_16_0": &utls.HelloSafari_16_0,
"hello360_auto": &utls.Hello360_Auto,
"hello360_7_5": &utls.Hello360_7_5,
"hello360_11_0": &utls.Hello360_11_0,
"helloqq_auto": &utls.HelloQQ_Auto,
"helloqq_11_1": &utls.HelloQQ_11_1,
}
defaultClientHello = &utls.HelloChrome_Auto
)
type roundTripper struct {
......@@ -158,6 +115,7 @@ func (rt *roundTripper) dialTLS(network, addr string) (net.Conn, error) {
// a good optimization and is a relatively common server feature,
// neither Firefox nor Chromium appear to use such optimizations.
DynamicRecordSizingDisabled: true,
RootCAs: GetRootCAs(),
}, *rt.clientHelloID)
if err = conn.Handshake(); err != nil {
......@@ -208,21 +166,6 @@ func newRoundTripper(dialFn base.DialFunc, clientHelloID *utls.ClientHelloID) ht
}
}
func parseClientHelloID(s string) (*utls.ClientHelloID, error) {
s = strings.ToLower(s)
switch s {
case "none":
return nil, nil
case "":
return defaultClientHello, nil
default:
if ret := clientHelloIDMap[s]; ret != nil {
return ret, nil
}
}
return nil, fmt.Errorf("invalid ClientHelloID: '%v'", s)
}
func newHTTPTransport(dialFn, dialTLSFn base.DialFunc) *http.Transport {
base := (http.DefaultTransport).(*http.Transport)
......
......@@ -40,7 +40,7 @@ import (
"net"
"time"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/csrand"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/transports/base"
)
......@@ -121,6 +121,9 @@ func (cf *obfs2ClientFactory) Dial(network, addr string, dialFn base.DialFunc, a
return conn, nil
}
// Not yet implemented
func (cf *obfs2ClientFactory) OnEvent(f func(base.TransportEvent)) {}
type obfs2ServerFactory struct {
transport base.Transport
}
......
......@@ -40,7 +40,7 @@ import (
"net"
"time"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/csrand"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/uniformdh"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/transports/base"
......@@ -105,6 +105,9 @@ func (cf *obfs3ClientFactory) Dial(network, addr string, dialFn base.DialFunc, a
return conn, nil
}
// Not yet implemented
func (cf *obfs3ClientFactory) OnEvent(f func(base.TransportEvent)) {}
type obfs3ServerFactory struct {
transport base.Transport
}
......
......@@ -42,7 +42,7 @@ import (
"syscall"
"time"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/drbg"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/ntor"
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/probdist"
......@@ -223,6 +223,9 @@ func (cf *obfs4ClientFactory) Dial(network, addr string, dialFn base.DialFunc, a
return conn, nil
}
// Not yet implemented
func (cf *obfs4ClientFactory) OnEvent(f func(base.TransportEvent)) {}
type obfs4ServerFactory struct {
transport base.Transport
args *pt.Args
......