-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
143 lines (122 loc) · 3.77 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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main
import (
"crypto/tls"
"crypto/x509"
"flag"
"github.com/ffutop/mitmproxy/mitm"
"github.com/ffutop/mitmproxy/netproxy"
"gopkg.in/yaml.v3"
"io/ioutil"
"log"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
)
var pwd, _ = os.Getwd()
var home = os.Getenv("HOME")
var hostname, _ = os.Hostname()
var (
configFile string
config Config
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
var err error
flag.StringVar(&configFile, "config", "", "Specify custom path to `config.yaml`")
flag.StringVar(&config.Addr, "addr", "127.0.0.1:53960", "Specify a URI endpoint on which to listen")
flag.BoolVar(&config.DebugTLS, "debugTLS", false, "Enable debugging information")
flag.StringVar(&config.CertFile, "certFile", filepath.Join(home, ".mitm/ca-cert.pem"), "Path to a cert file for the root certificate authority")
flag.StringVar(&config.KeyFile, "keyFile", filepath.Join(home, ".mitm/ca-key.pem"), "Path to a key file for the root certificate authority")
flag.StringVar(&config.TlsKeyLogFile, "tlsKeyLogFile", filepath.Join(home, ".mitm/master-secret.log"), "Expose NSS Key Log for trace HTTPS traffic via Wireshark. works only DebugTLS is enabled")
flag.StringVar(&config.LogFile, "logFile", "", "If non-empty, use this log file")
flag.Parse()
parseConfig()
if config.LogFile != "" {
logFile, err := os.OpenFile(config.LogFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600)
if err != nil {
log.Fatalln(err)
}
log.SetOutput(logFile)
}
log.Println("final config: ", config)
// prior create $HOME/.mitm directory
if err = os.MkdirAll(filepath.Join(home, ".mitm"), 0755); err != nil {
log.Fatalln(err)
}
srv := &mitm.Proxy{}
if srv.RootCA, err = config.loadRootCA(); err != nil {
log.Fatalln(err)
}
if config.DebugTLS {
if srv.KeyLogWriter, err = os.OpenFile(config.TlsKeyLogFile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600); err != nil {
log.Fatalln(err)
}
}
if err := netproxy.SetupGlobalNetworkProxy(config.Addr); err != nil {
log.Fatalln(err)
}
go func() {
log.Println("proxy server started on", config.Addr)
if err = http.ListenAndServe(config.Addr, srv); err != nil {
log.Fatalln(err)
}
}()
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGHUP, os.Interrupt)
s := <-c
log.Println(s)
netproxy.ShutdownGlobalNetworkProxy()
}
// Note: struct fields must be public in order for unmarshal to
// correctly populate the data.
type Config struct {
Addr string `yaml:"addr"`
DebugTLS bool `yaml:"debugTLS"`
CertFile string `yaml:"certFile"`
KeyFile string `yaml:"keyFile"`
TlsKeyLogFile string `yaml:"tlsKeyLogFile"`
LogFile string `yaml:"logFile"`
}
func parseConfig() {
if configFile == "" {
return
}
bytes, err := ioutil.ReadFile(configFile)
if err != nil {
log.Fatalln(err)
}
if err = yaml.Unmarshal(bytes, &config); err != nil {
log.Fatalln(err)
}
}
func (config *Config) loadRootCA() (rootCA *tls.Certificate, err error) {
var certificate tls.Certificate
// direct load certificate from storage
certificate, err = tls.LoadX509KeyPair(config.CertFile, config.KeyFile)
if err != nil {
log.Println("RootCA not exist, auto generate")
// generate new RootCA key, cert
cert, key, err := mitm.GenerateRootCertificate(hostname)
if err != nil {
return nil, err
}
// persist to storage
if err := ioutil.WriteFile(config.CertFile, cert, 0600); err != nil {
return nil, err
}
if err := ioutil.WriteFile(config.KeyFile, key, 0600); err != nil {
return nil, err
}
// build RootCA
certificate, err = tls.X509KeyPair(cert, key)
if err != nil {
return nil, err
}
}
if certificate.Leaf, err = x509.ParseCertificate(certificate.Certificate[0]); err != nil {
return nil, err
}
return &certificate, nil
}