-
Notifications
You must be signed in to change notification settings - Fork 4
/
main.go
99 lines (84 loc) · 2.42 KB
/
main.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package main
import (
"bytes"
"crypto/tls"
"flag"
"fmt"
"io"
"log"
"net/http"
"os"
"strings"
"github.com/elazarl/goproxy" // github.com/saucesteals/goproxy
utls "github.com/refraction-networking/utls"
"github.com/saucesteals/utlsproxy/cert"
)
var (
flagKeyLogFile = flag.String("keylog", "", "TLS key log file")
flagAddr = flag.String("addr", ":8080", "Address to bind to")
flagHttp1Only = flag.Bool("http1", false, "Force HTTP/1.1 between client and proxy")
)
func main() {
flag.Parse()
ca, err := cert.GetCertificate()
if err != nil {
log.Panic(err)
}
proxyCAConfig := goproxy.TLSConfigFromCA(ca)
proxyTlsConfig := func(host string, ctx *goproxy.ProxyCtx) (*tls.Config, error) {
config, err := proxyCAConfig(host, ctx)
if err != nil {
return nil, err
}
config.NextProtos = []string{"h2", "http/1.1"}
if *flagHttp1Only {
config.NextProtos = []string{"http/1.1"}
}
return config, nil
}
proxy := goproxy.NewProxyHttpServer(tlsConfig())
proxy.CertStore = NewOptimizedCertStore()
proxy.OnRequest().HandleConnect(goproxy.FuncHttpsHandler(func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
return &goproxy.ConnectAction{
Action: goproxy.ConnectMitm,
TLSConfig: proxyTlsConfig,
}, host
}))
proxy.OnRequest().DoFunc(serveCertificate(ca))
addr := *flagAddr
log.Printf("Listening on %s", addr)
if err := http.ListenAndServe(addr, proxy); err != nil {
log.Panic(err)
}
}
func tlsConfig() *utls.Config {
var keyLogWriter io.Writer
if path := *flagKeyLogFile; path != "" {
w, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0600)
if err != nil {
log.Panic(err)
}
keyLogWriter = w
}
return &utls.Config{KeyLogWriter: keyLogWriter}
}
func serveCertificate(ca *tls.Certificate) func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
return func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
certServer := "utlsproxy.ws"
if r.URL.Host != certServer {
return r, &http.Response{
StatusCode: http.StatusNotFound,
Body: io.NopCloser(
strings.NewReader(fmt.Sprintf("<html><body>Not found. Did you mean <a href='http://%s'>%s</a> ?</body></html>", certServer, certServer)),
),
}
}
return r, &http.Response{
StatusCode: http.StatusOK,
Header: http.Header{
"content-type": {"application/x-x509-ca-cert"},
},
Body: io.NopCloser(bytes.NewReader(ca.Leaf.Raw)),
}
}
}