gomitmproxy icon indicating copy to clipboard operation
gomitmproxy copied to clipboard

routines:CONNECT_CR_SRVR_HELLO:wrong version number

Open domyway opened this issue 5 years ago • 4 comments

HTTP proxy OnRequest change the body . but get error info :

routines:CONNECT_CR_SRVR_HELLO:wrong version number

if I dont change anything, all fine.
need some help thanks.

domyway avatar Aug 21 '20 08:08 domyway

Could you please show your code?

ameshkov avatar Aug 21 '20 08:08 ameshkov

func main() {
	proxy := gomitmproxy.NewProxy(gomitmproxy.Config{
		// TLSConfig: tlsConfig,
		ListenAddr: &net.TCPAddr{
			IP:   net.IPv4(0, 0, 0, 0),
			Port: 8080,
		},
		OnRequest: func(session *gomitmproxy.Session) (request *http.Request, response *http.Response) {
			req := session.Request()

			log.Printf("onRequest: %s %s", req.Method, req.URL.String())

			body := strings.NewReader("<html><body><h1>Replaced response</h1></body></html>")
			res := proxyutil.NewResponse(http.StatusOK, body, req)
			log.Printf("onRequest: %s %s %+v", req.Method, req.URL.String(), res)

			if req.URL.Host == "www.google.com:443" {
				body := strings.NewReader("<html><body><h1>Replaced response</h1></body></html>")
				res := proxyutil.NewResponse(http.StatusOK, body, req)
				res.Header.Set("Content-Type", "text/html")

				// Use session props to pass the information about request being blocked
				// session.SetProp("blocked", true)
				return nil, res
			}

			return nil, nil
		},
		OnResponse: func(session *gomitmproxy.Session) *http.Response {
			log.Printf("onResponse: %s", session.Request().URL.String())

			if _, ok := session.GetProp("blocked"); ok {
				log.Printf("onResponse: was blocked")
			}

			res := session.Response()
			req := session.Request()

			if strings.Index(res.Header.Get("Content-Type"), "text/html") != 0 {
				// Do nothing with non-HTML responses
				return nil
			}

			b, err := proxyutil.ReadDecompressedBody(res)
			// Close the original body
			_ = res.Body.Close()
			if err != nil {
				return proxyutil.NewErrorResponse(req, err)
			}

			// Use latin1 before modifying the body
			// Using this 1-byte encoding will let us preserve all original characters
			// regardless of what exactly is the encoding
			body, err := proxyutil.DecodeLatin1(bytes.NewReader(b))
			if err != nil {
				return proxyutil.NewErrorResponse(session.Request(), err)
			}

			// Modifying the original body
			modifiedBody, err := proxyutil.EncodeLatin1(body + "<!-- EDITED -->")
			if err != nil {
				return proxyutil.NewErrorResponse(session.Request(), err)
			}

			res.Body = ioutil.NopCloser(bytes.NewReader(modifiedBody))
			res.Header.Del("Content-Encoding")
			// res.ContentLength = int64(len(modifiedBody))
			log.Printf("onResponse: %+v", res)
			return res
		},
	})
	err := proxy.Start()
	if err != nil {
		log.Fatal(err)
	}

	signalChannel := make(chan os.Signal, 1)
	signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM)
	<-signalChannel

	// Clean up
	proxy.Close()
}


export https_proxy=127.0.0.1:8080
export http_proxy=127.0.0.1:8080

curl -v https://www.google.com   
                                                                                                                                                                                              ````
* Uses proxy env variable https_proxy == 'http://127.0.0.1:8080'
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to www.google.com:443
> CONNECT www.google.com:443 HTTP/1.1
> Host: www.google.com:443
> User-Agent: curl/7.64.1
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 OK
< Connection: close
< Content-Type: text/html
<
* Proxy replied 200 to CONNECT request
* CONNECT phase completed!
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* error:1400410B:SSL routines:CONNECT_CR_SRVR_HELLO:wrong version number
* Closing connection 0
curl: (35) error:1400410B:SSL routines:CONNECT_CR_SRVR_HELLO:wrong version number

domyway avatar Aug 21 '20 08:08 domyway

CONNECT www.google.com:443 HTTP/1.1

curl sends a CONNECT method request to your app, then it sends TLS handshake data, but receives

body := strings.NewReader("<html><body><h1>Replaced response</h1></body></html>")

back. HTML data is not a valid TLS server handshake data!

szolin avatar Aug 21 '20 11:08 szolin

how can i do to change the https response body ?

I trace the code if I dont change the body, then app goes to handleConnect(session *Session) finally

session.res = proxyutil.NewResponse(http.StatusOK, nil, session.req)

then

err = p.writeResponse(session)

It looks like the same thing what the OnRequest Func do

body := strings.NewReader("<html><body><h1>Replaced response</h1></body></html>")
res := proxyutil.NewResponse(http.StatusOK, body, req)

// then go here
p.writeResponse(session)

domyway avatar Aug 21 '20 15:08 domyway