├── build.sh ├── doc ├── genKey.sh ├── goproxy.png └── proxy.png ├── gomitmproxy-ca-cert.pem ├── gomitmproxy-ca-pk.pem ├── readme.md └── src ├── main └── main.go └── vendor ├── color └── tcolor.go ├── config └── config.go ├── mitm ├── cache.go ├── dump.go ├── gen_key.go ├── gomitmproxy.go ├── listener.go └── mitm.go └── mylog ├── my_log.go ├── my_log_test.go └── test.log /build.sh: -------------------------------------------------------------------------------- 1 | os=$1 2 | arch=$2 3 | 4 | export GOPATH=`pwd` 5 | GOOS=$os GOARCH=$arch go build -o bin/gomitmproxy$os$arch src/main/*.go 6 | -------------------------------------------------------------------------------- /doc/genKey.sh: -------------------------------------------------------------------------------- 1 | openssl genrsa -out gomitmproxy-ca-pk.pem 2048 2 | openssl req -new -x509 -days 36500 -key gomitmproxy-ca-pk.pem -out gomitmproxy-ca-cert.pem -------------------------------------------------------------------------------- /doc/goproxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zboya/gomitmproxy/6030c05a53151b7a77fd4e204528b1a3d53196ef/doc/goproxy.png -------------------------------------------------------------------------------- /doc/proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zboya/gomitmproxy/6030c05a53151b7a77fd4e204528b1a3d53196ef/doc/proxy.png -------------------------------------------------------------------------------- /gomitmproxy-ca-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDFjCCAf4CCQCGwNBaM3AUxTANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJj 3 | bjEUMBIGA1UECgwLZ29taXRtcHJveHkxDjAMBgNVBAsMBXByb3h5MRcwFQYDVQQD 4 | DA5nb21pdG1wcm94eTEuMjAgFw0xODAzMjkwNzMxNTJaGA8yMTE4MDMwNTA3MzE1 5 | MlowTDELMAkGA1UEBhMCY24xFDASBgNVBAoMC2dvbWl0bXByb3h5MQ4wDAYDVQQL 6 | DAVwcm94eTEXMBUGA1UEAwwOZ29taXRtcHJveHkxLjIwggEiMA0GCSqGSIb3DQEB 7 | AQUAA4IBDwAwggEKAoIBAQDamLQMN7B77J5hQNZTXQ7IohPJQx6nbq3PteQ+2+Ia 8 | d4Mllczxe8855BpLW1kTsgPTk/1tZcw05//megxDncLyUUIiQh3MUc25XOTuNe3Z 9 | RgYUNemt+n7MVxoq9DLbk4nWnpBJEYHBokaAZfOejo4rzdjZEWQCZRFocPuFTvOw 10 | 6slPUZY1urp4fzvlQY5qOcatk+DkuB+FI4REsuSTu0kbRyVHoS5xiVRJPI6X0fZB 11 | dRLqhJujrNqzYnyARMAzcRIV04FyDNY+2hxD3ViRL+XcMa/ksymloApqprAzvgxR 12 | w5v8ob7GwTlxyJS4lxY8GptYPvxcXHF8bbyUCTLD+/OfAgMBAAEwDQYJKoZIhvcN 13 | AQELBQADggEBAE3PSKbLIJTSX0E98nsguKspAzfExBwUbQSe8RIxDjOFmIiqqgPa 14 | wW4P1LEdQtKWMIUcCubNj7RnpOo/2t1+rqSSnRUUQ8WpzBQ85WnpaR2pXdgkl1OA 15 | LVYMgJU1cUHYD++ljVLnSDq7rOPe5TmVeycYejfkdXVP+WFsM5g8QEFYoQz6a16u 16 | e75rM3JQu8sGNox5iktmcmnGkaYXr6XcbNEy1m0b5jXbmI2k4ffciE2Qs66nV/kT 17 | 3tg7fTN7Ptlu0pbqbpFgjd/cyFNKyq7yDbIyI0Y5Vpz44ZrkMQpjzN6wAiR5va2q 18 | jg839LQ9Qcd7Qd01Jgyg2tyvoBFqzgx0puM= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /gomitmproxy-ca-pk.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA2pi0DDewe+yeYUDWU10OyKITyUMep26tz7XkPtviGneDJZXM 3 | 8XvPOeQaS1tZE7ID05P9bWXMNOf/5noMQ53C8lFCIkIdzFHNuVzk7jXt2UYGFDXp 4 | rfp+zFcaKvQy25OJ1p6QSRGBwaJGgGXzno6OK83Y2RFkAmURaHD7hU7zsOrJT1GW 5 | Nbq6eH875UGOajnGrZPg5LgfhSOERLLkk7tJG0clR6EucYlUSTyOl9H2QXUS6oSb 6 | o6zas2J8gETAM3ESFdOBcgzWPtocQ91YkS/l3DGv5LMppaAKaqawM74MUcOb/KG+ 7 | xsE5cciUuJcWPBqbWD78XFxxfG28lAkyw/vznwIDAQABAoIBAQCKdxntd0UianK0 8 | deaNLbAUpJ3V6d87/Z65qKTosE2bqEJ5h1cnS96q8/M38qgNEsDbv61TI51jkeWF 9 | 759fIUqARbqXirvnVZXzqYUV4zFDZNiq6q+X1cmF1FKuDLs+XUl9mjkZH67Koej4 10 | ohvcPr6NvrlyXlK0NaL+PjsEaUtxr0tx0e7c3k5W99MRL3G2O6uIkoUpRuV7YjTj 11 | 2Kod8jUgGnXhNPFaJ2f186bZDMHLuSzhXlv2N3WZL0ixTZuvEbjK4xRD4sP+GhvH 12 | BB2tzF7qjYNuKA02InWWxPpzIeLw/EQHaYMt2lud/y2vqlI6Pk4Vn/EsGFeALiwT 13 | Sc8fYXXRAoGBAPS22NcbS4jFidcZTPsXcmxwxTyqQ/6fQ07+7a4CLrghzFNoWuGf 14 | LIGpjYlA4zRQ51sIZU5Ksket43JmJj+4NkfmZE/dNhovh3eJXxd4hq37SxCmXqpm 15 | WY9c9FWAimnAhwWG2QqbhXTAIMC+fOUr6ZNZWHnZ5RM9Ru5g4xcOucxXAoGBAOSt 16 | gQyD/uDCRQMomfMdBVePRlPKZCbnEvcBsTiGm3b3q1cAejoORI/kJ8kRUyvuQOn4 17 | 7nvyM4Z7AqtaQfE2H2RM/54r+rS6eVcsvSnBeBiD0tVEJG/2/zgxOEUad8iDGFVX 18 | XcTRHAAjoW3NGO2aDUySAHLIwgAlJ5S16MC13YX5AoGBAO62twwOyj4fRHkZayi9 19 | FJeH4j9tcGqffY8/yyclZeGkxqbOc2kIVugdN74eGATervD0Xa5j20lk7SyZTNJ3 20 | piu5KT1m8vHUT3dh/+rrXaW2LuGNCWd78/2PlaEahOroLk5L3skkMKlVCh47M6Zy 21 | kaV1UIN89KMx8VF0HdJOQRx9AoGAbRe8xdy+njjvtXcMIqgIoWHvmg+mwcxhBsee 22 | 5SmKRzIWYnYO2V1vJfohZNHIDOAnxbcFBspf/Fr4xghUBx/bz/zPwYSXoNqJAqaM 23 | Q7xRb9iLn0RX4bZCwWrxvj3HQTgRRr1cNYXQxtw4qeo7Zzaj+5B3eEsAChOvk0lJ 24 | FY5tdPkCgYBFcHm+ilGQEoSKn0kT2I15KJvTdD0z7iZR5LEtz/LUPFjTaSKZZjZF 25 | mG9pOV58zM93YqRCssEKzW/0bqcmXGDzpwU5VqvTyURSU++/8srd3R99uUl47Kn/ 26 | mKrGsyv1LTwFVzPOYEKz96HWRFQQ4NAVWw8whYN4OR3UXpxHzRQuiA== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # gomitmproxy 2 | 3 | gomitmproxy是想用golang语言实现的[mitmproxy](https://mitmproxy.org/),主要实现http代理,目前实现了http代理和https抓包功能,差距甚远,加油。 4 | 5 | 6 | ## 可以用来干嘛? 7 | 8 | * http代理 9 | * http和https抓包 10 | * 科学上网 11 | 12 | ## 将来要实现的功能 13 | 14 | * 修改http(s)请求 15 | * 重复请求 16 | * 同时监听多端口 17 | * 支持socks5、websocket等协议 18 | * 界面支持终端和网页两种形式 19 | 20 | ## 安装使用 21 | 22 | ```bash 23 | git clone https://github.com/sheepbao/gomitmproxy.git 24 | cd gomitmproxy 25 | ./build.sh 26 | ``` 27 | 28 | ## 例子 29 | 30 | * http代理 31 | 32 | ```bash 33 | gomitmproxy 34 | ``` 35 | 不带任何参数,表示http代理,默认端口8080,更改端口用 -port 36 | 37 | * http抓包 38 | 39 | ```bash 40 | gomitmproxy -m 41 | ``` 42 | 43 | ![fetch http](https://raw.githubusercontent.com/sheepbao/gomitmproxy/master/doc/goproxy.png) 44 | 45 | 加 -m 参数,表示抓取http请求和响应 46 | 47 | * http代理科学上网 48 | 49 | 首先你得有个墙外的服务器,如阿里香港的服务器,为图中的Server,假设其ip地址为:22.222.222.222 50 | 51 | ```bash 52 | 在Server执行: 53 | gomitmproxy -port 8888 54 | ``` 55 | 56 | ```bash 57 | 在你自己电脑执行: 58 | gomitmproxy -port 8080 -raddr 22.222.222.222:8888 59 | ``` 60 | 然后浏览器设置代理,ip为localhost,端口为8080,即可实现科学上网 61 | 62 | ![proxy](https://raw.githubusercontent.com/sheepbao/gomitmproxy/master/doc/proxy.png) 63 | 64 | ## 最后 65 | 66 | 欢迎star和fork,一起学习交流。 67 | ## License 68 | 69 | The 3-clause BSD License 70 | - see LICENSE for more details 71 | -------------------------------------------------------------------------------- /src/main/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "config" 5 | "flag" 6 | "io" 7 | "mitm" 8 | "mylog" 9 | "os" 10 | "sync" 11 | ) 12 | 13 | func main() { 14 | var log io.WriteCloser 15 | var err error 16 | // cofig 17 | conf := new(config.Cfg) 18 | conf.Port = flag.String("port", "8080", "Listen port") 19 | conf.Raddr = flag.String("raddr", "", "Remote addr") 20 | conf.Log = flag.String("logFile", "", "log file path") 21 | conf.Monitor = flag.Bool("m", false, "monitor mode") 22 | conf.Tls = flag.Bool("tls", false, "tls connect") 23 | 24 | flag.Parse() 25 | 26 | // init log 27 | if *conf.Log != "" { 28 | log, err = os.Create(*conf.Log) 29 | if err != nil { 30 | mylog.Fatalln("fail to create log file " + err.Error()) 31 | } 32 | } else { 33 | log = os.Stderr 34 | } 35 | mylog.SetLog(log) 36 | 37 | // init tls config 38 | tlsConfig := config.NewTlsConfig("gomitmproxy-ca-pk.pem", "gomitmproxy-ca-cert.pem", "", "") 39 | // start mitm proxy 40 | wg := new(sync.WaitGroup) 41 | wg.Add(1) 42 | mitm.Gomitmproxy(conf, tlsConfig, wg) 43 | wg.Wait() 44 | } 45 | -------------------------------------------------------------------------------- /src/vendor/color/tcolor.go: -------------------------------------------------------------------------------- 1 | package color 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | ) 7 | 8 | const ( 9 | TextBlack = iota + 30 10 | TextRed 11 | TextGreen 12 | TextYellow 13 | TextBlue 14 | TextMagenta 15 | TextCyan 16 | TextWhite 17 | ) 18 | 19 | func Black(str string) string { 20 | return textColor(TextBlack, str) 21 | } 22 | 23 | func Red(str string) string { 24 | return textColor(TextRed, str) 25 | } 26 | 27 | func Green(str string) string { 28 | return textColor(TextGreen, str) 29 | } 30 | 31 | func Yellow(str string) string { 32 | return textColor(TextYellow, str) 33 | } 34 | 35 | func Blue(str string) string { 36 | return textColor(TextBlue, str) 37 | } 38 | 39 | func Magenta(str string) string { 40 | return textColor(TextMagenta, str) 41 | } 42 | 43 | func Cyan(str string) string { 44 | return textColor(TextCyan, str) 45 | } 46 | 47 | func White(str string) string { 48 | return textColor(TextWhite, str) 49 | } 50 | 51 | func textColor(color int, str string) string { 52 | if IsWindows() { 53 | return str 54 | } 55 | 56 | switch color { 57 | case TextBlack: 58 | return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextBlack, str) 59 | case TextRed: 60 | return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextRed, str) 61 | case TextGreen: 62 | return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextGreen, str) 63 | case TextYellow: 64 | return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextYellow, str) 65 | case TextBlue: 66 | return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextBlue, str) 67 | case TextMagenta: 68 | return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextMagenta, str) 69 | case TextCyan: 70 | return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextCyan, str) 71 | case TextWhite: 72 | return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextWhite, str) 73 | default: 74 | return str 75 | } 76 | } 77 | 78 | func IsWindows() bool { 79 | if runtime.GOOS == "windows" { 80 | return true 81 | } else { 82 | return false 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/vendor/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import "crypto/tls" 4 | 5 | type Cfg struct { 6 | Port *string 7 | Raddr *string 8 | Log *string 9 | Monitor *bool 10 | Tls *bool 11 | } 12 | 13 | type TlsConfig struct { 14 | PrivateKeyFile string 15 | CertFile string 16 | Organization string 17 | CommonName string 18 | ServerTLSConfig *tls.Config 19 | } 20 | 21 | func NewTlsConfig(pk, cert, org, cn string) *TlsConfig { 22 | return &TlsConfig{ 23 | PrivateKeyFile: pk, 24 | CertFile: cert, 25 | Organization: org, 26 | CommonName: cn, 27 | ServerTLSConfig: &tls.Config{ 28 | CipherSuites: []uint16{ 29 | tls.TLS_RSA_WITH_RC4_128_SHA, 30 | tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, 31 | tls.TLS_RSA_WITH_AES_128_CBC_SHA, 32 | tls.TLS_RSA_WITH_AES_256_CBC_SHA, 33 | tls.TLS_RSA_WITH_AES_128_CBC_SHA256, 34 | tls.TLS_RSA_WITH_AES_128_GCM_SHA256, 35 | tls.TLS_RSA_WITH_AES_256_GCM_SHA384, 36 | tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 37 | tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 38 | tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 39 | tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, 40 | tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 41 | tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 42 | tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 43 | tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 44 | tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 45 | tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 46 | tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 47 | tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 48 | tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 49 | tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 50 | tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 51 | tls.TLS_FALLBACK_SCSV, 52 | }, 53 | PreferServerCipherSuites: true, 54 | }, 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/vendor/mitm/cache.go: -------------------------------------------------------------------------------- 1 | // package cache implements a really primitive cache that associates expiring 2 | // values with string keys. This cache never clears itself out. 3 | package mitm 4 | 5 | import ( 6 | "sync" 7 | "time" 8 | ) 9 | 10 | // Cache is a cache for binary data 11 | type Cache struct { 12 | entries map[string]*entry 13 | mutex sync.RWMutex 14 | } 15 | 16 | // entry is an entry in a Cache 17 | type entry struct { 18 | data interface{} 19 | expiration time.Time 20 | } 21 | 22 | // NewCache creates a new Cache 23 | func NewCache() *Cache { 24 | return &Cache{entries: make(map[string]*entry)} 25 | } 26 | 27 | // Get returns the currently cached value for the given key, as long as it 28 | // hasn't expired. If the key was never set, or has expired, found will be 29 | // false. 30 | func (cache *Cache) Get(key string) (val interface{}, found bool) { 31 | cache.mutex.RLock() 32 | defer cache.mutex.RUnlock() 33 | entry := cache.entries[key] 34 | if entry == nil { 35 | return nil, false 36 | } else if entry.expiration.Before(time.Now()) { 37 | return nil, false 38 | } else { 39 | return entry.data, true 40 | } 41 | } 42 | 43 | // Set sets a value in the cache with an expiration of now + ttl. 44 | func (cache *Cache) Set(key string, data interface{}, ttl time.Duration) { 45 | cache.mutex.Lock() 46 | defer cache.mutex.Unlock() 47 | cache.entries[key] = &entry{data, time.Now().Add(ttl)} 48 | } 49 | -------------------------------------------------------------------------------- /src/vendor/mitm/dump.go: -------------------------------------------------------------------------------- 1 | package mitm 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "color" 7 | "compress/flate" 8 | "compress/gzip" 9 | "fmt" 10 | "io" 11 | "io/ioutil" 12 | "math" 13 | "mylog" 14 | "net/http" 15 | "strconv" 16 | ) 17 | 18 | func httpDump(reqDump []byte, resp *http.Response) { 19 | defer resp.Body.Close() 20 | var respStatusStr string 21 | respStatus := resp.StatusCode 22 | respStatusHeader := int(math.Floor(float64(respStatus / 100))) 23 | switch respStatusHeader { 24 | case 2: 25 | respStatusStr = color.Green("<--" + strconv.Itoa(respStatus)) 26 | case 3: 27 | respStatusStr = color.Yellow("<--" + strconv.Itoa(respStatus)) 28 | case 4: 29 | respStatusStr = color.Magenta("<--" + strconv.Itoa(respStatus)) 30 | case 5: 31 | respStatusStr = color.Red("<--" + strconv.Itoa(respStatus)) 32 | } 33 | 34 | fmt.Println(color.Green("Request:"), respStatusStr) 35 | req, _ := ParseReq(reqDump) 36 | fmt.Printf("%s %s %s\n", color.Blue(req.Method), req.Host+req.RequestURI, respStatusStr) 37 | fmt.Printf("%s %s\n", color.Blue("RemoteAddr:"), req.RemoteAddr) 38 | for headerName, headerContext := range req.Header { 39 | fmt.Printf("%s: %s\n", color.Blue(headerName), headerContext) 40 | } 41 | 42 | if req.Method == "POST" { 43 | fmt.Println(color.Green("POST Param:")) 44 | err := req.ParseForm() 45 | if err != nil { 46 | mylog.Println("parseForm error:", err) 47 | } else { 48 | for k, v := range req.Form { 49 | fmt.Printf("\t%s: %s\n", color.Blue(k), v) 50 | } 51 | } 52 | } 53 | fmt.Println(color.Green("Response:")) 54 | for headerName, headerContext := range resp.Header { 55 | fmt.Printf("%s: %s\n", color.Blue(headerName), headerContext) 56 | } 57 | 58 | respBody, err := ioutil.ReadAll(resp.Body) 59 | if err != nil { 60 | mylog.Println("func httpDump read resp body err:", err) 61 | } else { 62 | acceptEncode := resp.Header["Content-Encoding"] 63 | var respBodyBin bytes.Buffer 64 | w := bufio.NewWriter(&respBodyBin) 65 | w.Write(respBody) 66 | w.Flush() 67 | for _, compress := range acceptEncode { 68 | switch compress { 69 | case "gzip": 70 | r, err := gzip.NewReader(&respBodyBin) 71 | if err != nil { 72 | mylog.Println("gzip reader err:", err) 73 | } else { 74 | defer r.Close() 75 | respBody, _ = ioutil.ReadAll(r) 76 | } 77 | break 78 | case "deflate": 79 | r := flate.NewReader(&respBodyBin) 80 | defer r.Close() 81 | respBody, _ = ioutil.ReadAll(r) 82 | break 83 | } 84 | } 85 | fmt.Printf("%s\n", string(respBody)) 86 | } 87 | 88 | fmt.Printf("%s%s%s\n", color.Black("####################"), color.Cyan("END"), color.Black("####################")) 89 | } 90 | 91 | func ParseReq(b []byte) (*http.Request, error) { 92 | // func ReadRequest(b *bufio.Reader) (req *Request, err error) { return readRequest(b, deleteHostHeader) } 93 | fmt.Println(string(b)) 94 | fmt.Println("-----------------------") 95 | var buf io.ReadWriter 96 | buf = new(bytes.Buffer) 97 | buf.Write(b) 98 | bufr := bufio.NewReader(buf) 99 | return http.ReadRequest(bufr) 100 | } 101 | -------------------------------------------------------------------------------- /src/vendor/mitm/gen_key.go: -------------------------------------------------------------------------------- 1 | // Package keyman provides convenience APIs around Go's built-in crypto APIs. 2 | package mitm 3 | 4 | import ( 5 | "crypto/rand" 6 | "crypto/rsa" 7 | "crypto/x509" 8 | "crypto/x509/pkix" 9 | "encoding/pem" 10 | "fmt" 11 | "io/ioutil" 12 | "math/big" 13 | "mylog" 14 | "net" 15 | "os" 16 | "time" 17 | ) 18 | 19 | const ( 20 | PEM_HEADER_PRIVATE_KEY = "RSA PRIVATE KEY" 21 | PEM_HEADER_PUBLIC_KEY = "RSA PRIVATE KEY" 22 | PEM_HEADER_CERTIFICATE = "CERTIFICATE" 23 | ) 24 | 25 | var ( 26 | tenYearsFromToday = time.Now().AddDate(10, 0, 0) 27 | ) 28 | 29 | // PrivateKey is a convenience wrapper for rsa.PrivateKey 30 | type PrivateKey struct { 31 | rsaKey *rsa.PrivateKey 32 | } 33 | 34 | // Certificate is a convenience wrapper for x509.Certificate 35 | type Certificate struct { 36 | cert *x509.Certificate 37 | derBytes []byte 38 | } 39 | 40 | /******************************************************************************* 41 | * Private Key Functions 42 | ******************************************************************************/ 43 | 44 | // GeneratePK generates a PrivateKey with a specified size in bits. 45 | func GeneratePK(bits int) (key *PrivateKey, err error) { 46 | var rsaKey *rsa.PrivateKey 47 | rsaKey, err = rsa.GenerateKey(rand.Reader, bits) 48 | if err == nil { 49 | key = &PrivateKey{rsaKey: rsaKey} 50 | } 51 | return 52 | } 53 | 54 | // LoadPKFromFile loads a PEM-encoded PrivateKey from a file 55 | func LoadPKFromFile(filename string) (key *PrivateKey, err error) { 56 | privateKeyData, err := ioutil.ReadFile(filename) 57 | if err != nil { 58 | if os.IsNotExist(err) { 59 | return nil, err 60 | } 61 | return nil, fmt.Errorf("Unable to read private key file from file %s: %s", filename, err) 62 | } 63 | block, _ := pem.Decode(privateKeyData) 64 | if block == nil { 65 | return nil, fmt.Errorf("Unable to decode PEM encoded private key data: %s", err) 66 | } 67 | rsaKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) 68 | if err != nil { 69 | return nil, fmt.Errorf("Unable to decode X509 private key data: %s", err) 70 | } 71 | return &PrivateKey{rsaKey: rsaKey}, nil 72 | } 73 | 74 | // PEMEncoded encodes the PrivateKey in PEM 75 | func (key *PrivateKey) PEMEncoded() (pemBytes []byte) { 76 | return pem.EncodeToMemory(key.pemBlock()) 77 | } 78 | 79 | // WriteToFile writes the PEM-encoded PrivateKey to the given file 80 | func (key *PrivateKey) WriteToFile(filename string) (err error) { 81 | keyOut, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 82 | if err != nil { 83 | return fmt.Errorf("Failed to open %s for writing: %s", filename, err) 84 | } 85 | if err := pem.Encode(keyOut, key.pemBlock()); err != nil { 86 | return fmt.Errorf("Unable to PEM encode private key: %s", err) 87 | } 88 | if err := keyOut.Close(); err != nil { 89 | mylog.Printf("Unable to close file: %v", err) 90 | } 91 | return 92 | } 93 | 94 | func (key *PrivateKey) pemBlock() *pem.Block { 95 | return &pem.Block{Type: PEM_HEADER_PRIVATE_KEY, Bytes: x509.MarshalPKCS1PrivateKey(key.rsaKey)} 96 | } 97 | 98 | /******************************************************************************* 99 | * Certificate Functions 100 | ******************************************************************************/ 101 | 102 | /* 103 | Certificate() generates a certificate for the Public Key of the given PrivateKey 104 | based on the given template and signed by the given issuer. If issuer is nil, 105 | the generated certificate is self-signed. 106 | */ 107 | func (key *PrivateKey) Certificate(template *x509.Certificate, issuer *Certificate) (*Certificate, error) { 108 | return key.CertificateForKey(template, issuer, &key.rsaKey.PublicKey) 109 | } 110 | 111 | /* 112 | CertificateForKey() generates a certificate for the given Public Key based on 113 | the given template and signed by the given issuer. If issuer is nil, the 114 | generated certificate is self-signed. 115 | */ 116 | func (key *PrivateKey) CertificateForKey(template *x509.Certificate, issuer *Certificate, publicKey interface{}) (*Certificate, error) { 117 | var issuerCert *x509.Certificate 118 | if issuer == nil { 119 | // Note - for self-signed certificates, we include the host's external IP address 120 | issuerCert = template 121 | } else { 122 | issuerCert = issuer.cert 123 | } 124 | derBytes, err := x509.CreateCertificate( 125 | rand.Reader, // secure entropy 126 | template, // the template for the new cert 127 | issuerCert, // cert that's signing this cert 128 | publicKey, // public key 129 | key.rsaKey, // private key 130 | ) 131 | if err != nil { 132 | return nil, err 133 | } 134 | return bytesToCert(derBytes) 135 | } 136 | 137 | // TLSCertificateFor generates a certificate useful for TLS use based on the 138 | // given parameters. These certs are usable for key encipherment and digital 139 | // signatures. 140 | // 141 | // organization: the org name for the cert. 142 | // name: used as the common name for the cert. If name is an IP 143 | // address, it is also added as an IP SAN. 144 | // validUntil: time at which certificate expires 145 | // isCA: whether or not this cert is a CA 146 | // issuer: the certificate which is issuing the new cert. If nil, the 147 | // new cert will be a self-signed CA certificate. 148 | // 149 | func (key *PrivateKey) TLSCertificateFor( 150 | organization string, 151 | name string, 152 | validUntil time.Time, 153 | isCA bool, 154 | issuer *Certificate) (cert *Certificate, err error) { 155 | 156 | template := &x509.Certificate{ 157 | SerialNumber: new(big.Int).SetInt64(int64(time.Now().UnixNano())), 158 | Subject: pkix.Name{ 159 | Organization: []string{organization}, 160 | CommonName: name, 161 | }, 162 | NotBefore: time.Now().AddDate(0, -1, 0), 163 | NotAfter: validUntil, 164 | 165 | BasicConstraintsValid: true, 166 | KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 167 | } 168 | 169 | // If name is an ip address, add it as an IP SAN 170 | ip := net.ParseIP(name) 171 | if ip != nil { 172 | template.IPAddresses = []net.IP{ip} 173 | } 174 | 175 | isSelfSigned := issuer == nil 176 | if isSelfSigned { 177 | template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth} 178 | } 179 | 180 | // If it's a CA, add certificate signing 181 | if isCA { 182 | template.KeyUsage = template.KeyUsage | x509.KeyUsageCertSign 183 | template.IsCA = true 184 | } 185 | 186 | cert, err = key.Certificate(template, issuer) 187 | return 188 | } 189 | 190 | // LoadCertificateFromFile loads a Certificate from a PEM-encoded file 191 | func LoadCertificateFromFile(filename string) (*Certificate, error) { 192 | certificateData, err := ioutil.ReadFile(filename) 193 | if err != nil { 194 | if os.IsNotExist(err) { 195 | return nil, err 196 | } 197 | return nil, fmt.Errorf("Unable to read certificate file from disk: %s", err) 198 | } 199 | return LoadCertificateFromPEMBytes(certificateData) 200 | } 201 | 202 | // LoadCertificateFromPEMBytes loads a Certificate from a byte array in PEM 203 | // format 204 | func LoadCertificateFromPEMBytes(pemBytes []byte) (*Certificate, error) { 205 | block, _ := pem.Decode(pemBytes) 206 | if block == nil { 207 | return nil, fmt.Errorf("Unable to decode PEM encoded certificate") 208 | } 209 | return bytesToCert(block.Bytes) 210 | } 211 | 212 | // LoadCertificateFromX509 loads a Certificate from an x509.Certificate 213 | func LoadCertificateFromX509(cert *x509.Certificate) (*Certificate, error) { 214 | pemBytes := pem.EncodeToMemory(&pem.Block{ 215 | Type: "CERTIFICATE", 216 | Headers: nil, 217 | Bytes: cert.Raw, 218 | }) 219 | return LoadCertificateFromPEMBytes(pemBytes) 220 | } 221 | 222 | // X509 returns the x509 certificate underlying this Certificate 223 | func (cert *Certificate) X509() *x509.Certificate { 224 | return cert.cert 225 | } 226 | 227 | // PEMEncoded encodes the Certificate in PEM 228 | func (cert *Certificate) PEMEncoded() (pemBytes []byte) { 229 | return pem.EncodeToMemory(cert.pemBlock()) 230 | } 231 | 232 | // WriteToFile writes the PEM-encoded Certificate to a file. 233 | func (cert *Certificate) WriteToFile(filename string) (err error) { 234 | certOut, err := os.Create(filename) 235 | if err != nil { 236 | return fmt.Errorf("Failed to open %s for writing: %s", filename, err) 237 | } 238 | defer func() { 239 | if err := certOut.Close(); err != nil { 240 | mylog.Printf("Unable to close file: %v", err) 241 | } 242 | }() 243 | return pem.Encode(certOut, cert.pemBlock()) 244 | } 245 | 246 | func (cert *Certificate) WriteToTempFile() (name string, err error) { 247 | // Create a temp file containing the certificate 248 | tempFile, err := ioutil.TempFile("", "tempCert") 249 | if err != nil { 250 | return "", fmt.Errorf("Unable to create temp file: %s", err) 251 | } 252 | name = tempFile.Name() 253 | err = cert.WriteToFile(name) 254 | if err != nil { 255 | return "", fmt.Errorf("Unable to save certificate to temp file: %s", err) 256 | } 257 | return 258 | } 259 | 260 | // WriteToDERFile writes the DER-encoded Certificate to a file. 261 | func (cert *Certificate) WriteToDERFile(filename string) (err error) { 262 | certOut, err := os.Create(filename) 263 | if err != nil { 264 | return fmt.Errorf("Failed to open %s for writing: %s", filename, err) 265 | } 266 | defer func() { 267 | if err := certOut.Close(); err != nil { 268 | mylog.Printf("Unable to close file: %v", err) 269 | } 270 | }() 271 | _, err = certOut.Write(cert.derBytes) 272 | return err 273 | } 274 | 275 | // PoolContainingCert creates a pool containing this cert. 276 | func (cert *Certificate) PoolContainingCert() *x509.CertPool { 277 | pool := x509.NewCertPool() 278 | pool.AddCert(cert.cert) 279 | return pool 280 | } 281 | 282 | // PoolContainingCerts constructs a CertPool containing all of the given certs 283 | // (PEM encoded). 284 | func PoolContainingCerts(certs ...string) (*x509.CertPool, error) { 285 | pool := x509.NewCertPool() 286 | for _, cert := range certs { 287 | c, err := LoadCertificateFromPEMBytes([]byte(cert)) 288 | if err != nil { 289 | return nil, err 290 | } 291 | pool.AddCert(c.cert) 292 | } 293 | return pool, nil 294 | } 295 | 296 | func (cert *Certificate) ExpiresBefore(time time.Time) bool { 297 | return cert.cert.NotAfter.Before(time) 298 | } 299 | 300 | func bytesToCert(derBytes []byte) (*Certificate, error) { 301 | cert, err := x509.ParseCertificate(derBytes) 302 | if err != nil { 303 | return nil, err 304 | } 305 | return &Certificate{cert, derBytes}, nil 306 | } 307 | 308 | func (cert *Certificate) pemBlock() *pem.Block { 309 | return &pem.Block{Type: PEM_HEADER_CERTIFICATE, Bytes: cert.derBytes} 310 | } 311 | -------------------------------------------------------------------------------- /src/vendor/mitm/gomitmproxy.go: -------------------------------------------------------------------------------- 1 | // This example shows a proxy server that uses go-mitm to man-in-the-middle 2 | // HTTPS connections opened with CONNECT requests 3 | 4 | package mitm 5 | 6 | import ( 7 | "config" 8 | "mylog" 9 | "net/http" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | func Gomitmproxy(conf *config.Cfg, tlsConfig *config.TlsConfig, wg *sync.WaitGroup) { 15 | handler, err := InitConfig(conf, tlsConfig) 16 | if err != nil { 17 | mylog.Fatalf("InitConfig error: %s", err) 18 | } 19 | 20 | server := &http.Server{ 21 | Addr: ":" + *conf.Port, 22 | Handler: handler, 23 | ReadTimeout: 1 * time.Hour, 24 | WriteTimeout: 1 * time.Hour, 25 | } 26 | 27 | go func() { 28 | mylog.Printf("Gomitmproxy Listening On: %s", *conf.Port) 29 | if *conf.Tls { 30 | mylog.Println("Listen And Serve HTTP TLS") 31 | err = server.ListenAndServeTLS("gomitmproxy-ca-cert.pem", "gomitmproxy-ca-pk.pem") 32 | } else { 33 | mylog.Println("Listen And Serve HTTP") 34 | err = server.ListenAndServe() 35 | } 36 | if err != nil { 37 | mylog.Fatalf("Unable To Start HTTP proxy: %s", err) 38 | } 39 | 40 | wg.Done() 41 | mylog.Printf("Gomitmproxy Stop!!!!") 42 | }() 43 | 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /src/vendor/mitm/listener.go: -------------------------------------------------------------------------------- 1 | package mitm 2 | 3 | import ( 4 | "io" 5 | "net" 6 | ) 7 | 8 | type mitmListener struct { 9 | conn net.Conn 10 | } 11 | 12 | func (listener *mitmListener) Accept() (net.Conn, error) { 13 | if listener.conn != nil { 14 | conn := listener.conn 15 | listener.conn = nil 16 | return conn, nil 17 | } else { 18 | return nil, io.EOF 19 | } 20 | } 21 | 22 | func (listener *mitmListener) Close() error { 23 | return nil 24 | } 25 | 26 | func (listener *mitmListener) Addr() net.Addr { 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /src/vendor/mitm/mitm.go: -------------------------------------------------------------------------------- 1 | package mitm 2 | 3 | import ( 4 | "bufio" 5 | "config" 6 | "crypto/tls" 7 | "errors" 8 | "fmt" 9 | "io" 10 | "log" 11 | "mylog" 12 | "net" 13 | "net/http" 14 | "net/http/httputil" 15 | "net/url" 16 | "regexp" 17 | "strings" 18 | "sync" 19 | "time" 20 | ) 21 | 22 | const ( 23 | Version = "1.1" 24 | ONE_DAY = 24 * time.Hour 25 | TWO_WEEKS = ONE_DAY * 14 26 | ONE_MONTH = 1 27 | ONE_YEAR = 1 28 | ) 29 | 30 | type HandlerWrapper struct { 31 | MyConfig *config.Cfg 32 | tlsConfig *config.TlsConfig 33 | wrapped http.Handler 34 | pk *PrivateKey 35 | pkPem []byte 36 | issuingCert *Certificate 37 | issuingCertPem []byte 38 | serverTLSConfig *tls.Config 39 | dynamicCerts *Cache 40 | certMutex sync.Mutex 41 | https bool 42 | } 43 | 44 | func (hw *HandlerWrapper) GenerateCertForClient() (err error) { 45 | if hw.tlsConfig.Organization == "" { 46 | hw.tlsConfig.Organization = "gomitmproxy" + Version 47 | } 48 | if hw.tlsConfig.CommonName == "" { 49 | hw.tlsConfig.CommonName = "gomitmproxy" 50 | } 51 | if hw.pk, err = LoadPKFromFile(hw.tlsConfig.PrivateKeyFile); err != nil { 52 | hw.pk, err = GeneratePK(2048) 53 | if err != nil { 54 | return fmt.Errorf("Unable to generate private key: %s", err) 55 | } 56 | hw.pk.WriteToFile(hw.tlsConfig.PrivateKeyFile) 57 | } 58 | hw.pkPem = hw.pk.PEMEncoded() 59 | hw.issuingCert, err = LoadCertificateFromFile(hw.tlsConfig.CertFile) 60 | if err != nil || hw.issuingCert.ExpiresBefore(time.Now().AddDate(0, ONE_MONTH, 0)) { 61 | hw.issuingCert, err = hw.pk.TLSCertificateFor( 62 | hw.tlsConfig.Organization, 63 | hw.tlsConfig.CommonName, 64 | time.Now().AddDate(ONE_YEAR, 0, 0), 65 | true, 66 | nil) 67 | if err != nil { 68 | return fmt.Errorf("Unable to generate self-signed issuing certificate: %s", err) 69 | } 70 | hw.issuingCert.WriteToFile(hw.tlsConfig.CertFile) 71 | } 72 | hw.issuingCertPem = hw.issuingCert.PEMEncoded() 73 | return 74 | } 75 | 76 | func (hw *HandlerWrapper) FakeCertForName(name string) (cert *tls.Certificate, err error) { 77 | kpCandidateIf, found := hw.dynamicCerts.Get(name) 78 | if found { 79 | return kpCandidateIf.(*tls.Certificate), nil 80 | } 81 | 82 | hw.certMutex.Lock() 83 | defer hw.certMutex.Unlock() 84 | kpCandidateIf, found = hw.dynamicCerts.Get(name) 85 | if found { 86 | return kpCandidateIf.(*tls.Certificate), nil 87 | } 88 | 89 | //create certificate 90 | certTTL := TWO_WEEKS 91 | generatedCert, err := hw.pk.TLSCertificateFor( 92 | hw.tlsConfig.Organization, 93 | name, 94 | time.Now().Add(certTTL), 95 | false, 96 | hw.issuingCert) 97 | if err != nil { 98 | return nil, fmt.Errorf("Unable to issue certificate: %s", err) 99 | } 100 | keyPair, err := tls.X509KeyPair(generatedCert.PEMEncoded(), hw.pkPem) 101 | if err != nil { 102 | return nil, fmt.Errorf("Unable to parse keypair for tls: %s", err) 103 | } 104 | 105 | cacheTTL := certTTL - ONE_DAY 106 | hw.dynamicCerts.Set(name, &keyPair, cacheTTL) 107 | return &keyPair, nil 108 | } 109 | 110 | func (hw *HandlerWrapper) DumpHTTPAndHTTPs(resp http.ResponseWriter, req *http.Request) { 111 | mylog.Println("DumpHTTPAndHTTPs") 112 | req.Header.Del("Proxy-Connection") 113 | req.Header.Set("Connection", "Keep-Alive") 114 | var reqDump []byte 115 | var err error 116 | ch := make(chan bool) 117 | // handle connection 118 | go func() { 119 | reqDump, err = httputil.DumpRequestOut(req, true) 120 | ch <- true 121 | }() 122 | if err != nil { 123 | mylog.Println("DumpRequest error ", err) 124 | } 125 | connIn, _, err := resp.(http.Hijacker).Hijack() 126 | if err != nil { 127 | mylog.Println("hijack error:", err) 128 | } 129 | defer connIn.Close() 130 | 131 | var respOut *http.Response 132 | host := req.Host 133 | 134 | matched, _ := regexp.MatchString(":[0-9]+$", host) 135 | 136 | if !hw.https { 137 | if !matched { 138 | host += ":80" 139 | } 140 | 141 | connOut, err := net.DialTimeout("tcp", host, time.Second*30) 142 | if err != nil { 143 | mylog.Println("dial to", host, "error:", err) 144 | return 145 | } 146 | 147 | if err = req.Write(connOut); err != nil { 148 | mylog.Println("send to server error", err) 149 | return 150 | } 151 | 152 | respOut, err = http.ReadResponse(bufio.NewReader(connOut), req) 153 | if err != nil && err != io.EOF { 154 | mylog.Println("read response error:", err) 155 | } 156 | 157 | } else { 158 | if !matched { 159 | host += ":443" 160 | } 161 | 162 | connOut, err := tls.Dial("tcp", host, hw.tlsConfig.ServerTLSConfig) 163 | if err != nil { 164 | 165 | } 166 | if err = req.Write(connOut); err != nil { 167 | mylog.Println("tls dial to", host, "error:", err) 168 | return 169 | } 170 | if err = req.Write(connOut); err != nil { 171 | mylog.Println("send to server error", err) 172 | return 173 | } 174 | 175 | respOut, err = http.ReadResponse(bufio.NewReader(connOut), req) 176 | if err != nil && err != io.EOF { 177 | mylog.Println("read response error:", err) 178 | } 179 | 180 | } 181 | 182 | if respOut == nil { 183 | log.Println("respOut is nil") 184 | return 185 | } 186 | 187 | respDump, err := httputil.DumpResponse(respOut, true) 188 | if err != nil { 189 | mylog.Println("respDump error:", err) 190 | } 191 | 192 | _, err = connIn.Write(respDump) 193 | if err != nil { 194 | mylog.Println("connIn write error:", err) 195 | } 196 | 197 | if *hw.MyConfig.Monitor { 198 | <-ch 199 | go httpDump(reqDump, respOut) 200 | } else { 201 | <-ch 202 | } 203 | } 204 | 205 | func (hw *HandlerWrapper) ServeHTTP(resp http.ResponseWriter, req *http.Request) { 206 | raddr := *hw.MyConfig.Raddr 207 | if len(raddr) != 0 { 208 | hw.Forward(resp, req, raddr) 209 | } else { 210 | if req.Method == "CONNECT" { 211 | hw.https = true 212 | hw.InterceptHTTPs(resp, req) 213 | } else { 214 | hw.https = false 215 | hw.DumpHTTPAndHTTPs(resp, req) 216 | } 217 | } 218 | } 219 | 220 | func (hw *HandlerWrapper) InterceptHTTPs(resp http.ResponseWriter, req *http.Request) { 221 | mylog.Println("InterceptHTTPs") 222 | addr := req.Host 223 | host := strings.Split(addr, ":")[0] 224 | 225 | cert, err := hw.FakeCertForName(host) 226 | if err != nil { 227 | msg := fmt.Sprintf("Could not get mitm cert for name: %s\nerror: %s", host, err) 228 | respBadGateway(resp, msg) 229 | return 230 | } 231 | 232 | // handle connection 233 | connIn, _, err := resp.(http.Hijacker).Hijack() 234 | if err != nil { 235 | msg := fmt.Sprintf("Unable to access underlying connection from client: %s", err) 236 | respBadGateway(resp, msg) 237 | return 238 | } 239 | tlsConfig := copyTlsConfig(hw.tlsConfig.ServerTLSConfig) 240 | tlsConfig.Certificates = []tls.Certificate{*cert} 241 | tlsConnIn := tls.Server(connIn, tlsConfig) 242 | listener := &mitmListener{tlsConnIn} 243 | handler := http.HandlerFunc(func(resp2 http.ResponseWriter, req2 *http.Request) { 244 | req2.URL.Scheme = "https" 245 | req2.URL.Host = req2.Host 246 | hw.DumpHTTPAndHTTPs(resp2, req2) 247 | 248 | }) 249 | 250 | go func() { 251 | err = http.Serve(listener, handler) 252 | if err != nil && err != io.EOF { 253 | mylog.Printf("Error serving mitm'ed connection: %s", err) 254 | } 255 | }() 256 | 257 | connIn.Write([]byte("HTTP/1.1 200 OK\r\n\r\n")) 258 | } 259 | 260 | func (hw *HandlerWrapper) Forward(resp http.ResponseWriter, req *http.Request, raddr string) { 261 | connIn, _, err := resp.(http.Hijacker).Hijack() 262 | connOut, err := net.Dial("tcp", raddr) 263 | if err != nil { 264 | mylog.Println("dial tcp error", err) 265 | } 266 | 267 | err = connectProxyServer(connOut, raddr) 268 | if err != nil { 269 | mylog.Println("connectProxyServer error:", err) 270 | } 271 | 272 | if req.Method == "CONNECT" { 273 | b := []byte("HTTP/1.1 200 Connection Established\r\n" + 274 | "Proxy-Agent: gomitmproxy/" + Version + "\r\n" + 275 | "Content-Length: 0" + "\r\n\r\n") 276 | _, err := connIn.Write(b) 277 | if err != nil { 278 | mylog.Println("Write Connect err:", err) 279 | return 280 | } 281 | } else { 282 | req.Header.Del("Proxy-Connection") 283 | req.Header.Set("Connection", "Keep-Alive") 284 | if err = req.Write(connOut); err != nil { 285 | mylog.Println("send to server err", err) 286 | return 287 | } 288 | } 289 | err = Transport(connIn, connOut) 290 | if err != nil { 291 | mylog.Println("trans error ", err) 292 | } 293 | } 294 | 295 | func InitConfig(conf *config.Cfg, tlsConfig *config.TlsConfig) (*HandlerWrapper, error) { 296 | hw := &HandlerWrapper{ 297 | MyConfig: conf, 298 | tlsConfig: tlsConfig, 299 | dynamicCerts: NewCache(), 300 | } 301 | err := hw.GenerateCertForClient() 302 | if err != nil { 303 | return nil, err 304 | } 305 | return hw, nil 306 | } 307 | 308 | func copyTlsConfig(template *tls.Config) *tls.Config { 309 | tlsConfig := &tls.Config{} 310 | if template != nil { 311 | *tlsConfig = *template 312 | } 313 | return tlsConfig 314 | } 315 | 316 | func copyHTTPRequest(template *http.Request) *http.Request { 317 | req := &http.Request{} 318 | if template != nil { 319 | *req = *template 320 | } 321 | return req 322 | } 323 | 324 | func respBadGateway(resp http.ResponseWriter, msg string) { 325 | log.Println(msg) 326 | resp.WriteHeader(502) 327 | resp.Write([]byte(msg)) 328 | } 329 | 330 | //两个io口的连接 331 | func Transport(conn1, conn2 net.Conn) (err error) { 332 | rChan := make(chan error, 1) 333 | wChan := make(chan error, 1) 334 | 335 | go MyCopy(conn1, conn2, wChan) 336 | go MyCopy(conn2, conn1, rChan) 337 | 338 | select { 339 | case err = <-wChan: 340 | case err = <-rChan: 341 | } 342 | 343 | return 344 | } 345 | 346 | func MyCopy(src io.Reader, dst io.Writer, ch chan<- error) { 347 | _, err := io.Copy(dst, src) 348 | ch <- err 349 | } 350 | 351 | func connectProxyServer(conn net.Conn, addr string) error { 352 | req := &http.Request{ 353 | Method: "CONNECT", 354 | URL: &url.URL{Host: addr}, 355 | Host: addr, 356 | ProtoMajor: 1, 357 | ProtoMinor: 1, 358 | Header: make(http.Header), 359 | } 360 | req.Header.Set("Proxy-Connection", "keep-alive") 361 | 362 | if err := req.Write(conn); err != nil { 363 | return err 364 | } 365 | 366 | resp, err := http.ReadResponse(bufio.NewReader(conn), req) 367 | if err != nil { 368 | return err 369 | } 370 | if resp.StatusCode != http.StatusOK { 371 | return errors.New(resp.Status) 372 | } 373 | return nil 374 | } 375 | 376 | /*func ReadNotDrain(r *http.Request) (content []byte, err error) { 377 | content, err = ioutil.ReadAll(r.Body) 378 | r.Body = io.ReadCloser(bytes.NewBuffer(content)) 379 | return 380 | } 381 | 382 | func ParsePostValues(req *http.Request) (url.Values, error) { 383 | c, err := ReadNotDrain(req) 384 | if err != nil { 385 | return nil, err 386 | } 387 | values, err := url.ParseQuery(string(c)) 388 | if err != nil { 389 | return nil, err 390 | } 391 | return values, nil 392 | } 393 | */ 394 | -------------------------------------------------------------------------------- /src/vendor/mylog/my_log.go: -------------------------------------------------------------------------------- 1 | package mylog 2 | 3 | import "log" 4 | import "io" 5 | 6 | var logger *log.Logger 7 | 8 | func init() { 9 | log.SetFlags(log.LstdFlags | log.Lshortfile) 10 | } 11 | 12 | func SetLog(l io.WriteCloser) { 13 | logger = log.New(l, "[gomitmproxy]", log.LstdFlags) 14 | } 15 | 16 | func Fatalf(format string, v ...interface{}) { 17 | logger.Fatalf(format, v) 18 | } 19 | 20 | func Fatalln(v ...interface{}) { 21 | logger.Fatalln(v) 22 | } 23 | 24 | func Printf(format string, v ...interface{}) { 25 | logger.Printf(format, v) 26 | } 27 | 28 | func Println(v ...interface{}) { 29 | logger.Println(v) 30 | } 31 | 32 | func Panicln(v ...interface{}) { 33 | logger.Panicln(v) 34 | } 35 | -------------------------------------------------------------------------------- /src/vendor/mylog/my_log_test.go: -------------------------------------------------------------------------------- 1 | package mylog 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "testing" 7 | ) 8 | 9 | func TestMyLog(t *testing.T) { 10 | logFile, err := os.Create("test.log") 11 | if err != nil { 12 | log.Fatalln("fail to create log file!") 13 | } 14 | logger := log.New(logFile, "[gomitmproxy]", log.LstdFlags|log.Llongfile) 15 | SetLog(logger) 16 | Println("log test") 17 | } 18 | -------------------------------------------------------------------------------- /src/vendor/mylog/test.log: -------------------------------------------------------------------------------- 1 | [gomitmproxy]2017/04/03 00:00:25 /Users/bao/program/go/gowork/gomitmproxy/src/vendor/mylog/my_log.go:20: [log test] 2 | --------------------------------------------------------------------------------