diff --git a/gomitmproxy.go b/gomitmproxy.go new file mode 100644 index 0000000..7641918 --- /dev/null +++ b/gomitmproxy.go @@ -0,0 +1,88 @@ +// This example shows a proxy server that uses go-mitm to man-in-the-middle +// HTTPS connections opened with CONNECT requests + +package main + +import ( + "flag" + "log" + "net/http" + "os" + "sync" + "time" +) + +const ( + Version = "1.1" +) + +var ( + wg sync.WaitGroup +) + +var logFile *os.File +var logger *log.Logger + +func main() { + var conf Cfg + + conf.Port = flag.String("port", "8080", "Listen port") + conf.Raddr = flag.String("raddr", "", "Remote addr") + conf.Log = flag.String("log", "./error.log", "log file path") + conf.Monitor = flag.Bool("m", false, "monitor mode") + conf.Tls = flag.Bool("tls", false, "tls connect") + help := flag.Bool("h", false, "help") + flag.Parse() + + if *help { + flag.PrintDefaults() + } + var err error + logFile, err = os.Create(*conf.Log) + if err != nil { + log.Fatalln("fail to create log file!") + } + + logger = log.New(logFile, "[gomitmproxy]", log.LstdFlags|log.Llongfile) + + wg.Add(1) + gomitmproxy(&conf) + wg.Wait() +} + +func gomitmproxy(conf *Cfg) { + tlsConfig := NewTlsConfig("gomitmproxy-ca-pk.pem", "gomitmproxy-ca-cert.pem", "", "") + + handler, err := InitConfig(conf, tlsConfig) + if err != nil { + logger.Fatalf("InitConfig error: %s", err) + } + + server := &http.Server{ + Addr: ":" + *conf.Port, + Handler: handler, + ReadTimeout: 1 * time.Hour, + WriteTimeout: 1 * time.Hour, + } + + go func() { + log.Printf("proxy listening port:%s", *conf.Port) + + if *conf.Tls { + log.Println("ListenAndServeTLS") + err = server.ListenAndServeTLS("gomitmproxy-ca-cert.pem", "gomitmproxy-ca-pk.pem") + } else { + log.Println("ListenAndServe") + err = server.ListenAndServe() + } + if err != nil { + logger.Fatalf("Unable to start HTTP proxy: %s", err) + } + + wg.Done() + + log.Printf("gomitmproxy stop!!!!") + }() + + return +} diff --git a/src/vendor/mitm/dump.go b/src/vendor/mitm/dump.go index e19536f..6887eff 100644 --- a/src/vendor/mitm/dump.go +++ b/src/vendor/mitm/dump.go @@ -7,6 +7,7 @@ import ( "compress/flate" "compress/gzip" "fmt" + "io" "io/ioutil" "math" "mylog" @@ -14,7 +15,7 @@ import ( "strconv" ) -func httpDump(req *http.Request, resp *http.Response) { +func httpDump(reqDump []byte, resp *http.Response) { defer resp.Body.Close() var respStatusStr string respStatus := resp.StatusCode @@ -29,18 +30,25 @@ func httpDump(req *http.Request, resp *http.Response) { case 5: respStatusStr = color.Red("<--" + strconv.Itoa(respStatus)) } - fmt.Println(color.Green("Request:")) - fmt.Printf("%s %s %s\n", color.Blue(req.Method), req.RequestURI, respStatusStr) + + 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("URLEncoded form")) - for k, v := range req.Form { - fmt.Printf("%s: %s\n", color.Blue(k), v) + 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 { @@ -79,3 +87,14 @@ func httpDump(req *http.Request, resp *http.Response) { 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) +} diff --git a/src/vendor/mitm/mitm.go b/src/vendor/mitm/mitm.go index c82805a..c65be51 100644 --- a/src/vendor/mitm/mitm.go +++ b/src/vendor/mitm/mitm.go @@ -110,13 +110,17 @@ func (hw *HandlerWrapper) FakeCertForName(name string) (cert *tls.Certificate, e func (hw *HandlerWrapper) DumpHTTPAndHTTPs(resp http.ResponseWriter, req *http.Request) { req.Header.Del("Proxy-Connection") req.Header.Set("Connection", "Keep-Alive") - reqTmp := copyHTTPRequest(req) - err := reqTmp.ParseForm() - + 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("parseForm error:", err) + mylog.Println("DumpRequest error ", err) } - // handle connection connIn, _, err := resp.(http.Hijacker).Hijack() if err != nil { mylog.Println("hijack error:", err) @@ -155,9 +159,8 @@ func (hw *HandlerWrapper) DumpHTTPAndHTTPs(resp http.ResponseWriter, req *http.R } connOut, err := tls.Dial("tcp", host, hw.tlsConfig.ServerTLSConfig) - if err != nil { - mylog.Panicln("tls dial to", host, "error:", err) + mylog.Println("tls dial to", host, "error:", err) return } if err = req.Write(connOut); err != nil { @@ -188,7 +191,10 @@ func (hw *HandlerWrapper) DumpHTTPAndHTTPs(resp http.ResponseWriter, req *http.R } if *hw.MyConfig.Monitor { - go httpDump(reqTmp, respOut) + <-ch + go httpDump(reqDump, respOut) + } else { + <-ch } } @@ -361,3 +367,22 @@ func connectProxyServer(conn net.Conn, addr string) error { } 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 +} +*/