Compare commits

...

5 Commits

  1. 5
      build.sh
  2. 2
      doc/genKey.sh
  3. 0
      doc/goproxy.png
  4. 0
      doc/proxy.png
  5. 34
      gomitmproxy-ca-cert.pem
  6. 50
      gomitmproxy-ca-pk.pem
  7. 4
      readme.md
  8. 84
      src/color/tcolor.go
  9. 56
      src/config/config.go
  10. 74
      src/main.go
  11. 41
      src/main/main.go
  12. 74
      src/main/main.go.bak
  13. 48
      src/mitm/cache.go
  14. 100
      src/mitm/dump.go
  15. 310
      src/mitm/gen_key.go
  16. 45
      src/mitm/gomitmproxy.go
  17. 28
      src/mitm/listener.go
  18. 393
      src/mitm/mitm.go
  19. 34
      src/mylog/my_log.go
  20. 17
      src/mylog/my_log_test.go
  21. 1
      src/mylog/test.log
  22. 21
      src/vendor/config/config.go
  23. 5
      src/vendor/mitm/gomitmproxy.go
  24. 8
      src/vendor/mitm/mitm.go
  25. 4
      src/vendor/mylog/my_log.go

@ -1,2 +1,5 @@
os=$1
arch=$2
export GOPATH=`pwd` export GOPATH=`pwd`
go build -o bin/gomitmproxy src/main/*.go GOOS=$os GOARCH=$arch go build -o bin/gomitmproxy$os$arch src/main/*.go

@ -0,0 +1,2 @@
openssl genrsa -out gomitmproxy-ca-pk.pem 2048
openssl req -new -x509 -days 36500 -key gomitmproxy-ca-pk.pem -out gomitmproxy-ca-cert.pem

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIDIjCCAgqgAwIBAgIIFFyG4pw+r+kwDQYJKoZIhvcNAQELBQAwLzEXMBUGA1UE MIIDFjCCAf4CCQCGwNBaM3AUxTANBgkqhkiG9w0BAQsFADBMMQswCQYDVQQGEwJj
ChMOZ29taXRtcHJveHkxLjAxFDASBgNVBAMTC2dvbWl0bXByb3h5MB4XDTE2MDUy bjEUMBIGA1UECgwLZ29taXRtcHJveHkxDjAMBgNVBAsMBXByb3h5MRcwFQYDVQQD
OTEwMjQ0NloXDTE3MDYyOTEwMjQ0NlowLzEXMBUGA1UEChMOZ29taXRtcHJveHkx DA5nb21pdG1wcm94eTEuMjAgFw0xODAzMjkwNzMxNTJaGA8yMTE4MDMwNTA3MzE1
LjAxFDASBgNVBAMTC2dvbWl0bXByb3h5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MlowTDELMAkGA1UEBhMCY24xFDASBgNVBAoMC2dvbWl0bXByb3h5MQ4wDAYDVQQL
MIIBCgKCAQEA5i5e0Ioniij/zx4uP+pEwIfCPuqRHpmtxnylXtDJNS7Mibsl57cC DAVwcm94eTEXMBUGA1UEAwwOZ29taXRtcHJveHkxLjIwggEiMA0GCSqGSIb3DQEB
pKDymhGtehXKzt/7lv7Zh4PQyHUAPJQqTp6Q/bQRcnCEKoY0jSCDy7ZYxz+6YMth AQUAA4IBDwAwggEKAoIBAQDamLQMN7B77J5hQNZTXQ7IohPJQx6nbq3PteQ+2+Ia
JD9CG67jCio78hQDyYQc8RpUJ8FyH+HWE8xyPkixnGC9tZSG6bAtP2ORtn9AsKXX d4Mllczxe8855BpLW1kTsgPTk/1tZcw05//megxDncLyUUIiQh3MUc25XOTuNe3Z
8Hj9zWKrQqWFMbQvOp8SGVkqNsO/ZvIO3Rf5pBPlPTUTsjXMFFN2PipoMgZnF43C RgYUNemt+n7MVxoq9DLbk4nWnpBJEYHBokaAZfOejo4rzdjZEWQCZRFocPuFTvOw
eXt3de+PxFfs+nN2IIPbLTmRHW8qrworkJ0TBJWYMiT6mFOEiqlF92pzdLNDyR3e 6slPUZY1urp4fzvlQY5qOcatk+DkuB+FI4REsuSTu0kbRyVHoS5xiVRJPI6X0fZB
xednS3We07jZBAbvQGmy1eenZORXZsDuRQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC dRLqhJujrNqzYnyARMAzcRIV04FyDNY+2hxD3ViRL+XcMa/ksymloApqprAzvgxR
AqQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMB w5v8ob7GwTlxyJS4lxY8GptYPvxcXHF8bbyUCTLD+/OfAgMBAAEwDQYJKoZIhvcN
Af8wDQYJKoZIhvcNAQELBQADggEBAH1Gj0AtwzwbM0+NPrGsv2B0z/BLLDHu9MIN AQELBQADggEBAE3PSKbLIJTSX0E98nsguKspAzfExBwUbQSe8RIxDjOFmIiqqgPa
EhVIPgcGj9E9e3uP2uzxBBfFIeIk9w2GyuzqHqq/NTOJSf3CpL0RJYI9gS8qMg4x wW4P1LEdQtKWMIUcCubNj7RnpOo/2t1+rqSSnRUUQ8WpzBQ85WnpaR2pXdgkl1OA
wn5wkSPVb8cp36jS3rNvpNx6nuz+P+H+t1x4+KWk12GM2gz7g/YSmkXOtntQzpOW LVYMgJU1cUHYD++ljVLnSDq7rOPe5TmVeycYejfkdXVP+WFsM5g8QEFYoQz6a16u
Gl9ydNYWbd0ad5k+kQhBp2nsq1NByg3fwEd1jgvSnxKB+P76OK01pSxRczLpCp0F e75rM3JQu8sGNox5iktmcmnGkaYXr6XcbNEy1m0b5jXbmI2k4ffciE2Qs66nV/kT
+1gpD6ukiPIC1RZCUiHk4UeY8jmpBNgNW4OJmxgA+LFclB3hytkxN2qbnk5xfA33 3tg7fTN7Ptlu0pbqbpFgjd/cyFNKyq7yDbIyI0Y5Vpz44ZrkMQpjzN6wAiR5va2q
1JciXh8y0ZD1wXB7y14PAB1TB53Rgjvk38OrPpBf3nETxlqP5zQ= jg839LQ9Qcd7Qd01Jgyg2tyvoBFqzgx0puM=
-----END CERTIFICATE----- -----END CERTIFICATE-----

@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

@ -40,7 +40,7 @@ gomitmproxy
gomitmproxy -m gomitmproxy -m
``` ```
![fetch http](https://raw.githubusercontent.com/sheepbao/gomitmproxy/master/src/doc/goproxy.png) ![fetch http](https://raw.githubusercontent.com/sheepbao/gomitmproxy/master/doc/goproxy.png)
加 -m 参数,表示抓取http请求和响应 加 -m 参数,表示抓取http请求和响应
@ -59,7 +59,7 @@ gomitmproxy -m
``` ```
然后浏览器设置代理,ip为localhost,端口为8080,即可实现科学上网 然后浏览器设置代理,ip为localhost,端口为8080,即可实现科学上网
![proxy](https://raw.githubusercontent.com/sheepbao/gomitmproxy/master/src/doc/proxy.png) ![proxy](https://raw.githubusercontent.com/sheepbao/gomitmproxy/master/doc/proxy.png)
## 最后 ## 最后

@ -0,0 +1,84 @@
package color
import (
"fmt"
"runtime"
)
const (
TextBlack = iota + 30
TextRed
TextGreen
TextYellow
TextBlue
TextMagenta
TextCyan
TextWhite
)
func Black(str string) string {
return textColor(TextBlack, str)
}
func Red(str string) string {
return textColor(TextRed, str)
}
func Green(str string) string {
return textColor(TextGreen, str)
}
func Yellow(str string) string {
return textColor(TextYellow, str)
}
func Blue(str string) string {
return textColor(TextBlue, str)
}
func Magenta(str string) string {
return textColor(TextMagenta, str)
}
func Cyan(str string) string {
return textColor(TextCyan, str)
}
func White(str string) string {
return textColor(TextWhite, str)
}
func textColor(color int, str string) string {
if IsWindows() {
return str
}
switch color {
case TextBlack:
return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextBlack, str)
case TextRed:
return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextRed, str)
case TextGreen:
return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextGreen, str)
case TextYellow:
return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextYellow, str)
case TextBlue:
return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextBlue, str)
case TextMagenta:
return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextMagenta, str)
case TextCyan:
return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextCyan, str)
case TextWhite:
return fmt.Sprintf("\x1b[0;%dm%s\x1b[0m", TextWhite, str)
default:
return str
}
}
func IsWindows() bool {
if runtime.GOOS == "windows" {
return true
} else {
return false
}
}

@ -0,0 +1,56 @@
package config
import "crypto/tls"
type Cfg struct {
Port *string
Raddr *string
Log *string
Monitor *bool
Tls *bool
}
type TlsConfig struct {
PrivateKeyFile string
CertFile string
Organization string
CommonName string
ServerTLSConfig *tls.Config
}
func NewTlsConfig(pk, cert, org, cn string) *TlsConfig {
return &TlsConfig{
PrivateKeyFile: pk,
CertFile: cert,
Organization: org,
CommonName: cn,
ServerTLSConfig: &tls.Config{
CipherSuites: []uint16{
tls.TLS_RSA_WITH_RC4_128_SHA,
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_FALLBACK_SCSV,
},
PreferServerCipherSuites: true,
},
}
}

@ -0,0 +1,74 @@
package main
import (
"config"
"flag"
"io"
"io/ioutil"
"mitm"
"mylog"
"net/http"
"os"
"sync"
)
//func main() {
//
// println("Hello, Running Success!")
//}
func main() {
var log io.WriteCloser
var err error
// cofig
conf := new(conf.Cfg)
conf.Port = flag.String("port", "8080", "端口")
conf.Raddr = flag.String("raddr", "", "远程地址")
conf.Log = flag.String("logFile", "", "本地日志路径")
conf.Monitor = flag.Bool("m", false, "监听模式(捕获内容)")
conf.Tls = flag.Bool("tls", false, "是否启用tls连接")
//pool := flag.String("pool", "", "代理池地址,格式 ip:端口 ")
flag.Parse()
// init log
if *conf.Log != "" {
log, err = os.Create(*conf.Log)
if err != nil {
mylog.Fatalln("创建日志文件失败 " + err.Error())
}
} else {
log = os.Stderr
}
mylog.SetLog(log)
// add current node to remote pool
//go regToPool(*pool,*conf.Port,*conf.Tls)
// init tls config
tlsConfig := config.NewTlsConfig("gomitmproxy-ca-pk.pem", "gomitmproxy-ca-cert.pem", "", "")
// start mitm proxy
wg := new(sync.WaitGroup)
wg.Add(1)
mitm.Gomitmproxy(conf, tlsConfig, wg)
wg.Wait()
}
// 注册自己到代理池中心
func regToPool(pool string, port string, proto bool) {
mylog.Println("开始注册到代理池 ")
protoStr := "http"
if proto {
protoStr = "https"
}
pollURL := "http://" + pool + "/v2/add?port=" + port + "&proto=" + protoStr
mylog.Println("url: %s ", pollURL)
resp, err := http.Get(pollURL)
if err != nil {
mylog.Println("出现错误 ", err.Error())
}
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
mylog.Println("代理池返回结果:" + string(bodyBytes))
}

@ -1,41 +0,0 @@
package main
import (
"config"
"flag"
"io"
"mitm"
"mylog"
"os"
"sync"
)
func main() {
var log io.WriteCloser
var err error
// cofig
conf := new(config.Cfg)
conf.Port = flag.String("port", "8080", "Listen port")
conf.Raddr = flag.String("raddr", "", "Remote addr")
conf.Log = flag.String("logFile", "", "log file path")
conf.Monitor = flag.Bool("m", false, "monitor mode")
conf.Tls = flag.Bool("tls", false, "tls connect")
flag.Parse()
// init log
if *conf.Log != "" {
log, err = os.Create(*conf.Log)
if err != nil {
mylog.Fatalln("fail to create log file!")
}
} else {
log = os.Stderr
}
mylog.SetLog(log)
// start mitm proxy
wg := new(sync.WaitGroup)
wg.Add(1)
mitm.Gomitmproxy(conf, wg)
wg.Wait()
}

@ -0,0 +1,74 @@
package main
import (
"config"
"flag"
"io"
"io/ioutil"
"mitm"
"mylog"
"net/http"
"os"
"sync"
)
//func main() {
//
// println("Hello, Running Success!")
//}
func main() {
var log io.WriteCloser
var err error
// cofig
conf := new(conf.Cfg)
conf.Port = flag.String("port", "8080", "端口")
conf.Raddr = flag.String("raddr", "", "远程地址")
conf.Log = flag.String("logFile", "", "本地日志路径")
conf.Monitor = flag.Bool("m", false, "监听模式(捕获内容)")
conf.Tls = flag.Bool("tls", false, "是否启用tls连接")
//pool := flag.String("pool", "", "代理池地址,格式 ip:端口 ")
flag.Parse()
// init log
if *conf.Log != "" {
log, err = os.Create(*conf.Log)
if err != nil {
mylog.Fatalln("创建日志文件失败 " + err.Error())
}
} else {
log = os.Stderr
}
mylog.SetLog(log)
// add current node to remote pool
//go regToPool(*pool,*conf.Port,*conf.Tls)
// init tls config
tlsConfig := config.NewTlsConfig("gomitmproxy-ca-pk.pem", "gomitmproxy-ca-cert.pem", "", "")
// start mitm proxy
wg := new(sync.WaitGroup)
wg.Add(1)
mitm.Gomitmproxy(conf, tlsConfig, wg)
wg.Wait()
}
// 注册自己到代理池中心
func regToPool(pool string, port string, proto bool) {
mylog.Println("开始注册到代理池 ")
protoStr := "http"
if proto {
protoStr = "https"
}
pollURL := "http://" + pool + "/v2/add?port=" + port + "&proto=" + protoStr
mylog.Println("url: %s ", pollURL)
resp, err := http.Get(pollURL)
if err != nil {
mylog.Println("出现错误 ", err.Error())
}
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
mylog.Println("代理池返回结果:" + string(bodyBytes))
}

@ -0,0 +1,48 @@
// package cache implements a really primitive cache that associates expiring
// values with string keys. This cache never clears itself out.
package mitm
import (
"sync"
"time"
)
// Cache is a cache for binary data
type Cache struct {
entries map[string]*entry
mutex sync.RWMutex
}
// entry is an entry in a Cache
type entry struct {
data interface{}
expiration time.Time
}
// NewCache creates a new Cache
func NewCache() *Cache {
return &Cache{entries: make(map[string]*entry)}
}
// Get returns the currently cached value for the given key, as long as it
// hasn't expired. If the key was never set, or has expired, found will be
// false.
func (cache *Cache) Get(key string) (val interface{}, found bool) {
cache.mutex.RLock()
defer cache.mutex.RUnlock()
entry := cache.entries[key]
if entry == nil {
return nil, false
} else if entry.expiration.Before(time.Now()) {
return nil, false
} else {
return entry.data, true
}
}
// Set sets a value in the cache with an expiration of now + ttl.
func (cache *Cache) Set(key string, data interface{}, ttl time.Duration) {
cache.mutex.Lock()
defer cache.mutex.Unlock()
cache.entries[key] = &entry{data, time.Now().Add(ttl)}
}

@ -0,0 +1,100 @@
package mitm
import (
"bufio"
"bytes"
"color"
"compress/flate"
"compress/gzip"
"fmt"
"io"
"io/ioutil"
"math"
"mylog"
"net/http"
"strconv"
)
func httpDump(reqDump []byte, resp *http.Response) {
defer resp.Body.Close()
var respStatusStr string
respStatus := resp.StatusCode
respStatusHeader := int(math.Floor(float64(respStatus / 100)))
switch respStatusHeader {
case 2:
respStatusStr = color.Green("<--" + strconv.Itoa(respStatus))
case 3:
respStatusStr = color.Yellow("<--" + strconv.Itoa(respStatus))
case 4:
respStatusStr = color.Magenta("<--" + strconv.Itoa(respStatus))
case 5:
respStatusStr = color.Red("<--" + strconv.Itoa(respStatus))
}
fmt.Println(color.Green("Request:"), respStatusStr)
req, _ := ParseReq(reqDump)
fmt.Printf("%s %s %s\n", color.Blue(req.Method), req.Host+req.RequestURI, respStatusStr)
fmt.Printf("%s %s\n", color.Blue("RemoteAddr:"), req.RemoteAddr)
for headerName, headerContext := range req.Header {
fmt.Printf("%s: %s\n", color.Blue(headerName), headerContext)
}
if req.Method == "POST" {
fmt.Println(color.Green("POST Param:"))
err := req.ParseForm()
if err != nil {
mylog.Println("parseForm error:", err)
} else {
for k, v := range req.Form {
fmt.Printf("\t%s: %s\n", color.Blue(k), v)
}
}
}
fmt.Println(color.Green("Response:"))
for headerName, headerContext := range resp.Header {
fmt.Printf("%s: %s\n", color.Blue(headerName), headerContext)
}
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
mylog.Println("func httpDump read resp body err:", err)
} else {
acceptEncode := resp.Header["Content-Encoding"]
var respBodyBin bytes.Buffer
w := bufio.NewWriter(&respBodyBin)
w.Write(respBody)
w.Flush()
for _, compress := range acceptEncode {
switch compress {
case "gzip":
r, err := gzip.NewReader(&respBodyBin)
if err != nil {
mylog.Println("gzip reader err:", err)
} else {
defer r.Close()
respBody, _ = ioutil.ReadAll(r)
}
break
case "deflate":
r := flate.NewReader(&respBodyBin)
defer r.Close()
respBody, _ = ioutil.ReadAll(r)
break
}
}
fmt.Printf("%s\n", string(respBody))
}
fmt.Printf("%s%s%s\n", color.Black("####################"), color.Cyan("END"), color.Black("####################"))
}
func ParseReq(b []byte) (*http.Request, error) {
// func ReadRequest(b *bufio.Reader) (req *Request, err error) { return readRequest(b, deleteHostHeader) }
fmt.Println(string(b))
fmt.Println("-----------------------")
var buf io.ReadWriter
buf = new(bytes.Buffer)
buf.Write(b)
bufr := bufio.NewReader(buf)
return http.ReadRequest(bufr)
}

@ -0,0 +1,310 @@
// Package keyman provides convenience APIs around Go's built-in crypto APIs.
package mitm
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"io/ioutil"
"math/big"
"mylog"
"net"
"os"
"time"
)
const (
PEM_HEADER_PRIVATE_KEY = "RSA PRIVATE KEY"
PEM_HEADER_PUBLIC_KEY = "RSA PRIVATE KEY"
PEM_HEADER_CERTIFICATE = "CERTIFICATE"
)
var (
tenYearsFromToday = time.Now().AddDate(10, 0, 0)
)
// PrivateKey is a convenience wrapper for rsa.PrivateKey
type PrivateKey struct {
rsaKey *rsa.PrivateKey
}
// Certificate is a convenience wrapper for x509.Certificate
type Certificate struct {
cert *x509.Certificate
derBytes []byte
}
/*******************************************************************************
* Private Key Functions
******************************************************************************/
// GeneratePK generates a PrivateKey with a specified size in bits.
func GeneratePK(bits int) (key *PrivateKey, err error) {
var rsaKey *rsa.PrivateKey
rsaKey, err = rsa.GenerateKey(rand.Reader, bits)
if err == nil {
key = &PrivateKey{rsaKey: rsaKey}
}
return
}
// LoadPKFromFile loads a PEM-encoded PrivateKey from a file
func LoadPKFromFile(filename string) (key *PrivateKey, err error) {
privateKeyData, err := ioutil.ReadFile(filename)
if err != nil {
if os.IsNotExist(err) {
return nil, err
}
return nil, fmt.Errorf("Unable to read private key file from file %s: %s", filename, err)
}
block, _ := pem.Decode(privateKeyData)
if block == nil {
return nil, fmt.Errorf("Unable to decode PEM encoded private key data: %s", err)
}
rsaKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("Unable to decode X509 private key data: %s", err)
}
return &PrivateKey{rsaKey: rsaKey}, nil
}
// PEMEncoded encodes the PrivateKey in PEM
func (key *PrivateKey) PEMEncoded() (pemBytes []byte) {
return pem.EncodeToMemory(key.pemBlock())
}
// WriteToFile writes the PEM-encoded PrivateKey to the given file
func (key *PrivateKey) WriteToFile(filename string) (err error) {
keyOut, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return fmt.Errorf("Failed to open %s for writing: %s", filename, err)
}
if err := pem.Encode(keyOut, key.pemBlock()); err != nil {
return fmt.Errorf("Unable to PEM encode private key: %s", err)
}
if err := keyOut.Close(); err != nil {
mylog.Printf("Unable to close file: %v", err)
}
return
}
func (key *PrivateKey) pemBlock() *pem.Block {
return &pem.Block{Type: PEM_HEADER_PRIVATE_KEY, Bytes: x509.MarshalPKCS1PrivateKey(key.rsaKey)}
}
/*******************************************************************************
* Certificate Functions
******************************************************************************/
/*
Certificate() generates a certificate for the Public Key of the given PrivateKey
based on the given template and signed by the given issuer. If issuer is nil,
the generated certificate is self-signed.
*/
func (key *PrivateKey) Certificate(template *x509.Certificate, issuer *Certificate) (*Certificate, error) {
return key.CertificateForKey(template, issuer, &key.rsaKey.PublicKey)
}
/*
CertificateForKey() generates a certificate for the given Public Key based on
the given template and signed by the given issuer. If issuer is nil, the
generated certificate is self-signed.
*/
func (key *PrivateKey) CertificateForKey(template *x509.Certificate, issuer *Certificate, publicKey interface{}) (*Certificate, error) {
var issuerCert *x509.Certificate
if issuer == nil {
// Note - for self-signed certificates, we include the host's external IP address
issuerCert = template
} else {
issuerCert = issuer.cert
}
derBytes, err := x509.CreateCertificate(
rand.Reader, // secure entropy
template, // the template for the new cert
issuerCert, // cert that's signing this cert
publicKey, // public key
key.rsaKey, // private key
)
if err != nil {
return nil, err
}
return bytesToCert(derBytes)
}
// TLSCertificateFor generates a certificate useful for TLS use based on the
// given parameters. These certs are usable for key encipherment and digital
// signatures.
//
// organization: the org name for the cert.
// name: used as the common name for the cert. If name is an IP
// address, it is also added as an IP SAN.
// validUntil: time at which certificate expires
// isCA: whether or not this cert is a CA
// issuer: the certificate which is issuing the new cert. If nil, the
// new cert will be a self-signed CA certificate.
//
func (key *PrivateKey) TLSCertificateFor(
organization string,
name string,
validUntil time.Time,
isCA bool,
issuer *Certificate) (cert *Certificate, err error) {
template := &x509.Certificate{
SerialNumber: new(big.Int).SetInt64(int64(time.Now().UnixNano())),
Subject: pkix.Name{
Organization: []string{organization},
CommonName: name,
},
NotBefore: time.Now().AddDate(0, -1, 0),
NotAfter: validUntil,
BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
}
// If name is an ip address, add it as an IP SAN
ip := net.ParseIP(name)
if ip != nil {
template.IPAddresses = []net.IP{ip}
}
isSelfSigned := issuer == nil
if isSelfSigned {
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}
}
// If it's a CA, add certificate signing
if isCA {
template.KeyUsage = template.KeyUsage | x509.KeyUsageCertSign
template.IsCA = true
}
cert, err = key.Certificate(template, issuer)
return
}
// LoadCertificateFromFile loads a Certificate from a PEM-encoded file
func LoadCertificateFromFile(filename string) (*Certificate, error) {
certificateData, err := ioutil.ReadFile(filename)
if err != nil {
if os.IsNotExist(err) {
return nil, err
}
return nil, fmt.Errorf("Unable to read certificate file from disk: %s", err)
}
return LoadCertificateFromPEMBytes(certificateData)
}
// LoadCertificateFromPEMBytes loads a Certificate from a byte array in PEM
// format
func LoadCertificateFromPEMBytes(pemBytes []byte) (*Certificate, error) {
block, _ := pem.Decode(pemBytes)
if block == nil {
return nil, fmt.Errorf("Unable to decode PEM encoded certificate")
}
return bytesToCert(block.Bytes)
}
// LoadCertificateFromX509 loads a Certificate from an x509.Certificate
func LoadCertificateFromX509(cert *x509.Certificate) (*Certificate, error) {
pemBytes := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Headers: nil,
Bytes: cert.Raw,
})
return LoadCertificateFromPEMBytes(pemBytes)
}
// X509 returns the x509 certificate underlying this Certificate
func (cert *Certificate) X509() *x509.Certificate {
return cert.cert
}
// PEMEncoded encodes the Certificate in PEM
func (cert *Certificate) PEMEncoded() (pemBytes []byte) {
return pem.EncodeToMemory(cert.pemBlock())
}
// WriteToFile writes the PEM-encoded Certificate to a file.
func (cert *Certificate) WriteToFile(filename string) (err error) {
certOut, err := os.Create(filename)
if err != nil {
return fmt.Errorf("Failed to open %s for writing: %s", filename, err)
}
defer func() {
if err := certOut.Close(); err != nil {
mylog.Printf("Unable to close file: %v", err)
}
}()
return pem.Encode(certOut, cert.pemBlock())
}
func (cert *Certificate) WriteToTempFile() (name string, err error) {
// Create a temp file containing the certificate
tempFile, err := ioutil.TempFile("", "tempCert")
if err != nil {
return "", fmt.Errorf("Unable to create temp file: %s", err)
}
name = tempFile.Name()
err = cert.WriteToFile(name)
if err != nil {
return "", fmt.Errorf("Unable to save certificate to temp file: %s", err)
}
return
}
// WriteToDERFile writes the DER-encoded Certificate to a file.
func (cert *Certificate) WriteToDERFile(filename string) (err error) {
certOut, err := os.Create(filename)
if err != nil {
return fmt.Errorf("Failed to open %s for writing: %s", filename, err)
}
defer func() {
if err := certOut.Close(); err != nil {
mylog.Printf("Unable to close file: %v", err)
}
}()
_, err = certOut.Write(cert.derBytes)
return err
}
// PoolContainingCert creates a pool containing this cert.
func (cert *Certificate) PoolContainingCert() *x509.CertPool {
pool := x509.NewCertPool()
pool.AddCert(cert.cert)
return pool
}
// PoolContainingCerts constructs a CertPool containing all of the given certs
// (PEM encoded).
func PoolContainingCerts(certs ...string) (*x509.CertPool, error) {
pool := x509.NewCertPool()
for _, cert := range certs {
c, err := LoadCertificateFromPEMBytes([]byte(cert))
if err != nil {
return nil, err
}
pool.AddCert(c.cert)
}
return pool, nil
}
func (cert *Certificate) ExpiresBefore(time time.Time) bool {
return cert.cert.NotAfter.Before(time)
}
func bytesToCert(derBytes []byte) (*Certificate, error) {
cert, err := x509.ParseCertificate(derBytes)
if err != nil {
return nil, err
}
return &Certificate{cert, derBytes}, nil
}
func (cert *Certificate) pemBlock() *pem.Block {
return &pem.Block{Type: PEM_HEADER_CERTIFICATE, Bytes: cert.derBytes}
}

@ -0,0 +1,45 @@
// This example shows a proxy server that uses go-mitm to man-in-the-middle
// HTTPS connections opened with CONNECT requests
package mitm
import (
"config"
"mylog"
"net/http"
"sync"
"time"
)
func Gomitmproxy(conf *config.Cfg, tlsConfig *config.TlsConfig, wg *sync.WaitGroup) {
handler, err := InitConfig(conf, tlsConfig)
if err != nil {
mylog.Fatalf("InitConfig error: %s", err)
}
server := &http.Server{
Addr: ":" + *conf.Port,
Handler: handler,
ReadTimeout: 1 * time.Hour,
WriteTimeout: 1 * time.Hour,
}
go func() {
mylog.Printf("Gomitmproxy Listening On: %s", *conf.Port)
if *conf.Tls {
mylog.Println("Listen And Serve HTTP TLS")
err = server.ListenAndServeTLS("gomitmproxy-ca-cert.pem", "gomitmproxy-ca-pk.pem")
} else {
mylog.Println("Listen And Serve HTTP")
err = server.ListenAndServe()
}
if err != nil {
mylog.Fatalf("Unable To Start HTTP proxy: %s", err)
}
wg.Done()
mylog.Printf("Gomitmproxy Stop!!!!")
}()
return
}

@ -0,0 +1,28 @@
package mitm
import (
"io"
"net"
)
type mitmListener struct {
conn net.Conn
}
func (listener *mitmListener) Accept() (net.Conn, error) {
if listener.conn != nil {
conn := listener.conn
listener.conn = nil
return conn, nil
} else {
return nil, io.EOF
}
}
func (listener *mitmListener) Close() error {
return nil
}
func (listener *mitmListener) Addr() net.Addr {
return nil
}

@ -0,0 +1,393 @@
package mitm
import (
"bufio"
"config"
"crypto/tls"
"errors"
"fmt"
"io"
"log"
"mylog"
"net"
"net/http"
"net/http/httputil"
"net/url"
"regexp"
"strings"
"sync"
"time"
)
const (
Version = "1.1"
ONE_DAY = 24 * time.Hour
TWO_WEEKS = ONE_DAY * 14
ONE_MONTH = 1
ONE_YEAR = 1
)
type HandlerWrapper struct {
MyConfig *config.Cfg
tlsConfig *config.TlsConfig
wrapped http.Handler
pk *PrivateKey
pkPem []byte
issuingCert *Certificate
issuingCertPem []byte
serverTLSConfig *tls.Config
dynamicCerts *Cache
certMutex sync.Mutex
https bool
}
func (hw *HandlerWrapper) GenerateCertForClient() (err error) {
if hw.tlsConfig.Organization == "" {
hw.tlsConfig.Organization = "gomitmproxy" + Version
}
if hw.tlsConfig.CommonName == "" {
hw.tlsConfig.CommonName = "gomitmproxy"
}
if hw.pk, err = LoadPKFromFile(hw.tlsConfig.PrivateKeyFile); err != nil {
hw.pk, err = GeneratePK(2048)
if err != nil {
return fmt.Errorf("Unable to generate private key: %s", err)
}
hw.pk.WriteToFile(hw.tlsConfig.PrivateKeyFile)
}
hw.pkPem = hw.pk.PEMEncoded()
hw.issuingCert, err = LoadCertificateFromFile(hw.tlsConfig.CertFile)
if err != nil || hw.issuingCert.ExpiresBefore(time.Now().AddDate(0, ONE_MONTH, 0)) {
hw.issuingCert, err = hw.pk.TLSCertificateFor(
hw.tlsConfig.Organization,
hw.tlsConfig.CommonName,
time.Now().AddDate(ONE_YEAR, 0, 0),
true,
nil)
if err != nil {
return fmt.Errorf("Unable to generate self-signed issuing certificate: %s", err)
}
hw.issuingCert.WriteToFile(hw.tlsConfig.CertFile)
}
hw.issuingCertPem = hw.issuingCert.PEMEncoded()
return
}
func (hw *HandlerWrapper) FakeCertForName(name string) (cert *tls.Certificate, err error) {
kpCandidateIf, found := hw.dynamicCerts.Get(name)
if found {
return kpCandidateIf.(*tls.Certificate), nil
}
hw.certMutex.Lock()
defer hw.certMutex.Unlock()
kpCandidateIf, found = hw.dynamicCerts.Get(name)
if found {
return kpCandidateIf.(*tls.Certificate), nil
}
//create certificate
certTTL := TWO_WEEKS
generatedCert, err := hw.pk.TLSCertificateFor(
hw.tlsConfig.Organization,
name,
time.Now().Add(certTTL),
false,
hw.issuingCert)
if err != nil {
return nil, fmt.Errorf("Unable to issue certificate: %s", err)
}
keyPair, err := tls.X509KeyPair(generatedCert.PEMEncoded(), hw.pkPem)
if err != nil {
return nil, fmt.Errorf("Unable to parse keypair for tls: %s", err)
}
cacheTTL := certTTL - ONE_DAY
hw.dynamicCerts.Set(name, &keyPair, cacheTTL)
return &keyPair, nil
}
func (hw *HandlerWrapper) DumpHTTPAndHTTPs(resp http.ResponseWriter, req *http.Request) {
mylog.Println("DumpHTTPAndHTTPs")
req.Header.Del("Proxy-Connection")
req.Header.Set("Connection", "Keep-Alive")
var reqDump []byte
var err error
ch := make(chan bool)
// handle connection
go func() {
reqDump, err = httputil.DumpRequestOut(req, true)
ch <- true
}()
if err != nil {
mylog.Println("DumpRequest error ", err)
}
connIn, _, err := resp.(http.Hijacker).Hijack()
if err != nil {
mylog.Println("hijack error:", err)
}
defer connIn.Close()
var respOut *http.Response
host := req.Host
matched, _ := regexp.MatchString(":[0-9]+$", host)
if !hw.https {
if !matched {
host += ":80"
}
connOut, err := net.DialTimeout("tcp", host, time.Second*30)
if err != nil {
mylog.Println("dial to", host, "error:", err)
return
}
if err = req.Write(connOut); err != nil {
mylog.Println("send to server error", err)
return
}
respOut, err = http.ReadResponse(bufio.NewReader(connOut), req)
if err != nil && err != io.EOF {
mylog.Println("read response error:", err)
}
} else {
if !matched {
host += ":443"
}
connOut, err := tls.Dial("tcp", host, hw.tlsConfig.ServerTLSConfig)
if err != nil {
}
if err = req.Write(connOut); err != nil {
mylog.Println("tls dial to", host, "error:", err)
return
}
if err = req.Write(connOut); err != nil {
mylog.Println("send to server error", err)
return
}
respOut, err = http.ReadResponse(bufio.NewReader(connOut), req)
if err != nil && err != io.EOF {
mylog.Println("read response error:", err)
}
}
if respOut == nil {
log.Println("respOut is nil")
return
}
respDump, err := httputil.DumpResponse(respOut, true)
if err != nil {
mylog.Println("respDump error:", err)
}
_, err = connIn.Write(respDump)
if err != nil {
mylog.Println("connIn write error:", err)
}
if *hw.MyConfig.Monitor {
<-ch
go httpDump(reqDump, respOut)
} else {
<-ch
}
}
func (hw *HandlerWrapper) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
raddr := *hw.MyConfig.Raddr
if len(raddr) != 0 {
hw.Forward(resp, req, raddr)
} else {
if req.Method == "CONNECT" {
hw.https = true
hw.InterceptHTTPs(resp, req)
} else {
hw.https = false
hw.DumpHTTPAndHTTPs(resp, req)
}
}
}
func (hw *HandlerWrapper) InterceptHTTPs(resp http.ResponseWriter, req *http.Request) {
mylog.Println("InterceptHTTPs")
addr := req.Host
host := strings.Split(addr, ":")[0]
cert, err := hw.FakeCertForName(host)
if err != nil {
msg := fmt.Sprintf("Could not get mitm cert for name: %s\nerror: %s", host, err)
respBadGateway(resp, msg)
return
}
// handle connection
connIn, _, err := resp.(http.Hijacker).Hijack()
if err != nil {
msg := fmt.Sprintf("Unable to access underlying connection from client: %s", err)
respBadGateway(resp, msg)
return
}
tlsConfig := copyTlsConfig(hw.tlsConfig.ServerTLSConfig)
tlsConfig.Certificates = []tls.Certificate{*cert}
tlsConnIn := tls.Server(connIn, tlsConfig)
listener := &mitmListener{tlsConnIn}
handler := http.HandlerFunc(func(resp2 http.ResponseWriter, req2 *http.Request) {
req2.URL.Scheme = "https"
req2.URL.Host = req2.Host
hw.DumpHTTPAndHTTPs(resp2, req2)
})
go func() {
err = http.Serve(listener, handler)
if err != nil && err != io.EOF {
mylog.Printf("Error serving mitm'ed connection: %s", err)
}
}()
connIn.Write([]byte("HTTP/1.1 200 OK\r\n\r\n"))
}
func (hw *HandlerWrapper) Forward(resp http.ResponseWriter, req *http.Request, raddr string) {
connIn, _, err := resp.(http.Hijacker).Hijack()
connOut, err := net.Dial("tcp", raddr)
if err != nil {
mylog.Println("dial tcp error", err)
}
err = connectProxyServer(connOut, raddr)
if err != nil {
mylog.Println("connectProxyServer error:", err)
}
if req.Method == "CONNECT" {
b := []byte("HTTP/1.1 200 Connection Established\r\n" +
"Proxy-Agent: gomitmproxy/" + Version + "\r\n" +
"Content-Length: 0" + "\r\n\r\n")
_, err := connIn.Write(b)
if err != nil {
mylog.Println("Write Connect err:", err)
return
}
} else {
req.Header.Del("Proxy-Connection")
req.Header.Set("Connection", "Keep-Alive")
if err = req.Write(connOut); err != nil {
mylog.Println("send to server err", err)
return
}
}
err = Transport(connIn, connOut)
if err != nil {
mylog.Println("trans error ", err)
}
}
func InitConfig(conf *config.Cfg, tlsConfig *config.TlsConfig) (*HandlerWrapper, error) {
hw := &HandlerWrapper{
MyConfig: conf,
tlsConfig: tlsConfig,
dynamicCerts: NewCache(),
}
err := hw.GenerateCertForClient()
if err != nil {
return nil, err
}
return hw, nil
}
func copyTlsConfig(template *tls.Config) *tls.Config {
tlsConfig := &tls.Config{}
if template != nil {
*tlsConfig = *template
}
return tlsConfig
}
func copyHTTPRequest(template *http.Request) *http.Request {
req := &http.Request{}
if template != nil {
*req = *template
}
return req
}
func respBadGateway(resp http.ResponseWriter, msg string) {
log.Println(msg)
resp.WriteHeader(502)
resp.Write([]byte(msg))
}
//两个io口的连接
func Transport(conn1, conn2 net.Conn) (err error) {
rChan := make(chan error, 1)
wChan := make(chan error, 1)
go MyCopy(conn1, conn2, wChan)
go MyCopy(conn2, conn1, rChan)
select {
case err = <-wChan:
case err = <-rChan:
}
return
}
func MyCopy(src io.Reader, dst io.Writer, ch chan<- error) {
_, err := io.Copy(dst, src)
ch <- err
}
func connectProxyServer(conn net.Conn, addr string) error {
req := &http.Request{
Method: "CONNECT",
URL: &url.URL{Host: addr},
Host: addr,
ProtoMajor: 1,
ProtoMinor: 1,
Header: make(http.Header),
}
req.Header.Set("Proxy-Connection", "keep-alive")
if err := req.Write(conn); err != nil {
return err
}
resp, err := http.ReadResponse(bufio.NewReader(conn), req)
if err != nil {
return err
}
if resp.StatusCode != http.StatusOK {
return errors.New(resp.Status)
}
return nil
}
/*func ReadNotDrain(r *http.Request) (content []byte, err error) {
content, err = ioutil.ReadAll(r.Body)
r.Body = io.ReadCloser(bytes.NewBuffer(content))
return
}
func ParsePostValues(req *http.Request) (url.Values, error) {
c, err := ReadNotDrain(req)
if err != nil {
return nil, err
}
values, err := url.ParseQuery(string(c))
if err != nil {
return nil, err
}
return values, nil
}
*/

@ -0,0 +1,34 @@
package mylog
import "log"
import "io"
var logger *log.Logger
func init() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
}
func SetLog(l io.WriteCloser) {
logger = log.New(l, "[gomitmproxy]", log.LstdFlags)
}
func Fatalf(format string, v ...interface{}) {
logger.Fatalf(format, v)
}
func Fatalln(v ...interface{}) {
logger.Fatalln(v)
}
func Printf(format string, v ...interface{}) {
logger.Printf(format, v)
}
func Println(v ...interface{}) {
logger.Println(v)
}
func Panicln(v ...interface{}) {
logger.Panicln(v)
}

@ -0,0 +1,17 @@
package mylog
import (
"log"
"os"
"testing"
)
func TestMyLog(t *testing.T) {
logFile, err := os.Create("test.log")
if err != nil {
log.Fatalln("fail to create log file!")
}
logger := log.New(logFile, "[gomitmproxy]", log.LstdFlags|log.Llongfile)
SetLog(logger)
Println("log test")
}

@ -0,0 +1 @@
[gomitmproxy]2017/04/03 00:00:25 /Users/bao/program/go/gowork/gomitmproxy/src/vendor/mylog/my_log.go:20: [log test]

@ -26,16 +26,29 @@ func NewTlsConfig(pk, cert, org, cn string) *TlsConfig {
CommonName: cn, CommonName: cn,
ServerTLSConfig: &tls.Config{ ServerTLSConfig: &tls.Config{
CipherSuites: []uint16{ CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_RC4_128_SHA, tls.TLS_RSA_WITH_RC4_128_SHA,
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_RSA_WITH_AES_256_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
tls.TLS_FALLBACK_SCSV,
}, },
PreferServerCipherSuites: true, PreferServerCipherSuites: true,
}, },

@ -11,9 +11,7 @@ import (
"time" "time"
) )
func Gomitmproxy(conf *config.Cfg, wg *sync.WaitGroup) { func Gomitmproxy(conf *config.Cfg, tlsConfig *config.TlsConfig, wg *sync.WaitGroup) {
tlsConfig := config.NewTlsConfig("gomitmproxy-ca-pk.pem", "gomitmproxy-ca-cert.pem", "", "")
handler, err := InitConfig(conf, tlsConfig) handler, err := InitConfig(conf, tlsConfig)
if err != nil { if err != nil {
mylog.Fatalf("InitConfig error: %s", err) mylog.Fatalf("InitConfig error: %s", err)
@ -40,7 +38,6 @@ func Gomitmproxy(conf *config.Cfg, wg *sync.WaitGroup) {
} }
wg.Done() wg.Done()
mylog.Printf("Gomitmproxy Stop!!!!") mylog.Printf("Gomitmproxy Stop!!!!")
}() }()

@ -108,6 +108,7 @@ func (hw *HandlerWrapper) FakeCertForName(name string) (cert *tls.Certificate, e
} }
func (hw *HandlerWrapper) DumpHTTPAndHTTPs(resp http.ResponseWriter, req *http.Request) { func (hw *HandlerWrapper) DumpHTTPAndHTTPs(resp http.ResponseWriter, req *http.Request) {
mylog.Println("DumpHTTPAndHTTPs")
req.Header.Del("Proxy-Connection") req.Header.Del("Proxy-Connection")
req.Header.Set("Connection", "Keep-Alive") req.Header.Set("Connection", "Keep-Alive")
var reqDump []byte var reqDump []byte
@ -139,13 +140,11 @@ func (hw *HandlerWrapper) DumpHTTPAndHTTPs(resp http.ResponseWriter, req *http.R
connOut, err := net.DialTimeout("tcp", host, time.Second*30) connOut, err := net.DialTimeout("tcp", host, time.Second*30)
if err != nil { if err != nil {
mylog.Println("dial to", host, "error:", err) mylog.Println("dial to", host, "error:", err)
return return
} }
if err = req.Write(connOut); err != nil { if err = req.Write(connOut); err != nil {
mylog.Println("send to server error", err) mylog.Println("send to server error", err)
return return
} }
@ -204,7 +203,6 @@ func (hw *HandlerWrapper) DumpHTTPAndHTTPs(resp http.ResponseWriter, req *http.R
} }
func (hw *HandlerWrapper) ServeHTTP(resp http.ResponseWriter, req *http.Request) { func (hw *HandlerWrapper) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
raddr := *hw.MyConfig.Raddr raddr := *hw.MyConfig.Raddr
if len(raddr) != 0 { if len(raddr) != 0 {
hw.Forward(resp, req, raddr) hw.Forward(resp, req, raddr)
@ -220,6 +218,7 @@ func (hw *HandlerWrapper) ServeHTTP(resp http.ResponseWriter, req *http.Request)
} }
func (hw *HandlerWrapper) InterceptHTTPs(resp http.ResponseWriter, req *http.Request) { func (hw *HandlerWrapper) InterceptHTTPs(resp http.ResponseWriter, req *http.Request) {
mylog.Println("InterceptHTTPs")
addr := req.Host addr := req.Host
host := strings.Split(addr, ":")[0] host := strings.Split(addr, ":")[0]
@ -272,7 +271,8 @@ func (hw *HandlerWrapper) Forward(resp http.ResponseWriter, req *http.Request, r
if req.Method == "CONNECT" { if req.Method == "CONNECT" {
b := []byte("HTTP/1.1 200 Connection Established\r\n" + b := []byte("HTTP/1.1 200 Connection Established\r\n" +
"Proxy-Agent: gomitmproxy/" + Version + "\r\n\r\n") "Proxy-Agent: gomitmproxy/" + Version + "\r\n" +
"Content-Length: 0" + "\r\n\r\n")
_, err := connIn.Write(b) _, err := connIn.Write(b)
if err != nil { if err != nil {
mylog.Println("Write Connect err:", err) mylog.Println("Write Connect err:", err)

@ -5,6 +5,10 @@ import "io"
var logger *log.Logger var logger *log.Logger
func init() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
}
func SetLog(l io.WriteCloser) { func SetLog(l io.WriteCloser) {
logger = log.New(l, "[gomitmproxy]", log.LstdFlags) logger = log.New(l, "[gomitmproxy]", log.LstdFlags)
} }

Loading…
Cancel
Save