-
Notifications
You must be signed in to change notification settings - Fork 47
/
plaintext.go
77 lines (69 loc) · 1.9 KB
/
plaintext.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package main
import (
"context"
"crypto/x509"
"errors"
"net"
tls "github.com/refraction-networking/utls"
)
type PlaintextDialer struct {
fixedAddress string
tlsServerName string
next ContextDialer
caPool *x509.CertPool
hideSNI bool
}
func NewPlaintextDialer(address, tlsServerName string, caPool *x509.CertPool, hideSNI bool, next ContextDialer) *PlaintextDialer {
return &PlaintextDialer{
fixedAddress: address,
tlsServerName: tlsServerName,
next: next,
caPool: caPool,
hideSNI: hideSNI,
}
}
func (d *PlaintextDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
switch network {
case "tcp", "tcp4", "tcp6":
default:
return nil, errors.New("bad network specified for DialContext: only tcp is supported")
}
conn, err := d.next.DialContext(ctx, "tcp", d.fixedAddress)
if err != nil {
return nil, err
}
if d.tlsServerName != "" {
// Custom cert verification logic:
// DO NOT send SNI extension of TLS ClientHello
// DO peer certificate verification against specified servername
sni := d.tlsServerName
if d.hideSNI {
sni = ""
}
tlsConn := tls.UClient(conn, &tls.Config{
ServerName: sni,
InsecureSkipVerify: true,
VerifyConnection: func(cs tls.ConnectionState) error {
opts := x509.VerifyOptions{
DNSName: d.tlsServerName,
Intermediates: x509.NewCertPool(),
Roots: d.caPool,
}
for _, cert := range cs.PeerCertificates[1:] {
opts.Intermediates.AddCert(cert)
}
_, err := cs.PeerCertificates[0].Verify(opts)
return err
},
}, tls.HelloAndroid_11_OkHttp)
if err := tlsConn.HandshakeContext(ctx); err != nil {
conn.Close()
return nil, err
}
return tlsConn, nil
}
return conn, nil
}
func (d *PlaintextDialer) Dial(network, address string) (net.Conn, error) {
return d.DialContext(context.Background(), network, address)
}