Code Monkey home page Code Monkey logo

gomitmproxy's Introduction

Code Coverage Go Report Card GolangCI Go Doc

gomitmproxy

This is a customizable HTTP proxy with TLS interception support. It was created as a part of AdGuard Home. However, it can be used for different purposes so we decided to make it a separate project.

Features

  • HTTP proxy
  • HTTP over TLS (HTTPS) proxy
  • Proxy authorization
  • TLS termination

How to use gomitmproxy

Simple HTTP proxy

package main

import (
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"

	"github.com/AdguardTeam/gomitmproxy"
)

func main() {
	proxy := gomitmproxy.NewProxy(gomitmproxy.Config{
		ListenAddr: &net.TCPAddr{
			IP:   net.IPv4(0, 0, 0, 0),
			Port: 8080,
		},
	})
	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()
}

Modifying requests and responses

You can modify requests and responses using OnRequest and OnResponse handlers.

The example below will block requests to example.net and add a short comment to the end of every HTML response.

proxy := gomitmproxy.NewProxy(gomitmproxy.Config{
    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())

        if req.URL.Host == "example.net" {
            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))
        return res
    },
})

Proxy authorization

If you want to protect your proxy with Basic authentication, set Username and Password fields in the proxy configuration.

proxy := gomitmproxy.NewProxy(gomitmproxy.Config{
    ListenAddr: &net.TCPAddr{
        IP:   net.IPv4(0, 0, 0, 0),
        Port: 8080,
    },
    Username: "user",
    Password: "pass",
})

HTTP over TLS (HTTPS) proxy

If you want to protect yourself from eavesdropping on your traffic to proxy, you can configure it to work over a TLS tunnel. This is really simple to do, just set a *tls.Config instance in your proxy configuration.

tlsConfig := &tls.Config{
    Certificates: []tls.Certificate{*proxyCert},
}
proxy := gomitmproxy.NewProxy(gomitmproxy.Config{
    ListenAddr: addr,
    TLSConfig:  tlsConfig,
})

TLS interception

If you want to do TLS termination, you first need to prepare a self-signed certificate that will be used as a certificates authority. Use the following openssl commands to do this.

openssl genrsa -out demo.key 2048
openssl req -new -x509 -key demo.key -out demo.crt -days 3650 -addext subjectAltName=DNS:<hostname>,IP:<ip>

Now you can use it to initialize MITMConfig:

tlsCert, err := tls.LoadX509KeyPair("demo.crt", "demo.key")
if err != nil {
    log.Fatal(err)
}
privateKey := tlsCert.PrivateKey.(*rsa.PrivateKey)

x509c, err := x509.ParseCertificate(tlsCert.Certificate[0])
if err != nil {
    log.Fatal(err)
}

mitmConfig, err := mitm.NewConfig(x509c, privateKey, nil)
if err != nil {
    log.Fatal(err)
}

mitmConfig.SetValidity(time.Hour * 24 * 7) // generate certs valid for 7 days
mitmConfig.SetOrganization("gomitmproxy")  // cert organization

Please note that you can set MITMExceptions to a list of hostnames, which will be excluded from TLS interception.

proxy := gomitmproxy.NewProxy(gomitmproxy.Config{
    ListenAddr: &net.TCPAddr{
        IP:   net.IPv4(0, 0, 0, 0),
        Port: 3333,
    },
    MITMConfig:     mitmConfig,
    MITMExceptions: []string{"example.com"},
})

If you configure the APIHost, you'll be able to download the CA certificate from http://[APIHost]/cert.crt when the proxy is configured.

// Navigate to http://gomitmproxy/cert.crt to download the CA certificate
proxy.APIHost = "gomitmproxy"

Custom certs storage

By default, gomitmproxy uses an in-memory map-based storage for the certificates, generated while doing TLS interception. It is often necessary to use a different kind of certificates storage. If this is your case, you can supply your own implementation of the CertsStorage interface.

// CustomCertsStorage - an example of a custom cert storage
type CustomCertsStorage struct {
	certsCache map[string]*tls.Certificate // cache with the generated certificates
}

// Get gets the certificate from the storage
func (c *CustomCertsStorage) Get(key string) (*tls.Certificate, bool) {
	v, ok := c.certsCache[key]
	return v, ok
}

// Set saves the certificate to the storage
func (c *CustomCertsStorage) Set(key string, cert *tls.Certificate) {
	c.certsCache[key] = cert
}

Then pass it to the NewConfig function.

mitmConfig, err := mitm.NewConfig(x509c, privateKey, &CustomCertsStorage{
    certsCache: map[string]*tls.Certificate{}},
)

Notable alternatives

  • martian - an awesome debugging proxy with TLS interception support.
  • goproxy - also supports TLS interception and requests.

TODO

  • Basic HTTP proxy without MITM
  • Proxy
    • Expose APIs for the library users
    • How-to doc
    • Travis configuration
    • Proxy-Authorization
    • WebSockets support (see this)
    • certsCache -- allow custom implementations
    • Support HTTP CONNECT over TLS
    • Test plain HTTP requests inside HTTP CONNECT
    • Test memory leaks
    • Editing response body in a callback
    • Handle unknown content-encoding values
    • Handle CONNECT to APIHost properly (without trying to actually connect anywhere)
    • Allow hijacking connections (!)
    • Multiple listeners
    • Unit tests
    • Check & fix TODOs
    • Allow specifying net.Dialer
    • Specify timeouts for http.Transport
  • MITM
    • Basic MITM
    • MITM exceptions
    • Handle invalid server certificates properly (not just reset connections)
    • Pass the most important tests on badssl.com/dashboard
    • Handle certificate authentication
    • Allow configuring minimum supported TLS version
    • OCSP check (see example)
    • (?) HPKP (see example)
    • (?) CT logs (see example)
    • (?) CRLSets (see example)

gomitmproxy's People

Contributors

ameshkov avatar gidobossftw5731 avatar szolin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gomitmproxy's Issues

tls first record does not look like a tls handshake

Hello,

I ran the examples/mitm/main.go file and there is the logs, nothing working:

2022/01/07 09:50:00 12480#300 [debug] id=100133: failed to read request: tls: first record does not look like a TLS handshake

2022/01/07 09:50:00 12480#299 [debug] id=100133: closing connection due to: tls: first record does not look like a TLS handshake

2022/01/07 09:50:00 12480#22 [debug] id=100134: accepted connection from 192.168.1.26:53754

2022/01/07 09:50:00 12480#308 [debug] id=100134: waiting for request

2022/01/07 09:50:00 12480#301 [debug] id=100134: failed to read request: tls: first record does not look like a TLS handshake

2022/01/07 09:50:00 12480#308 [debug] id=100134: closing connection due to: tls: first record does not look like a TLS handshake

2022/01/07 09:50:00 12480#22 [debug] id=100135: accepted connection from 192.168.1.26:53755

2022/01/07 09:50:00 12480#302 [debug] id=100135: waiting for request

2022/01/07 09:50:00 12480#303 [debug] id=100135: failed to read request: tls: first record does not look like a TLS handshake


if req.URL.Host is no hostname

Hi
my problem if req.URL.Host is no hostname
req.URL.Host is ip adress

if req.URL.Host == "google.ru" not work
how to use hostname in this code?

Feat request: Please allow us to have access to transport config

gomitmproxy.NewProxy starts out as follows:

// NewProxy creates a new instance of the Proxy
func NewProxy(config Config) *Proxy {
	proxy := &Proxy{
		Config: config,
		transport: &http.Transport{
			// This forces http.Transport to not upgrade requests to HTTP/2
			// TODO: Remove when HTTP/2 can be supported
			TLSNextProto:          make(map[string]func(string, *tls.Conn) http.RoundTripper),
			Proxy:                 http.ProxyFromEnvironment,
...

The Proxy: http.ProxyFromEnvironment is what affects me specifically. I am using an upstream proxy, and having to os.Setenv... to make it work is very inelegant:

os.Setenv("ALL_PROXY", upstreamProxy)
os.Setenv("HTTP_PROXY", upstreamProxy)
os.Setenv("HTTPS_PROXY", upstreamProxy)
fmt.Println("Upstream Proxy =", upstreamProxy)

Being able to pass this in, perhaps via the Config would be amazing. I would be happy to make a PR, please suggest if can be added to Config (maybe simple/non-breaking) or should be done some other way.

Thank you.

About Transparent Proxy

First of all, I am very grateful to the AdguardTeam team for giving so many excellent open source projects, from which I have learned a lot. Recently, I have been fascinated by the gomitmproxy project. The code of this project is very elegant, but I want to enter gomitmproxy through iptables traffic on Openwrt, but Encountered many setbacks.

So, I would like to ask you to help me, now I will describe the problem in detail:

First of all, there is no problem with HTTP proxying, it works fine. But I wanted to use a transparent proxy, so I replaced &net.TCPAddr with net.ResolveTCPAddr:

//addr := &net.TCPAddr{IP: listenIP, Port: options.ListenPort}
addr, err := net.ResolveTCPAddr("tcp", ":12345")

config.ProxyConfig = gomitmproxy.Config{
		ListenAddr: addr,

		MITMConfig:     mitmConfig,
		MITMExceptions: []string{"example.com"},
	}
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 10.20.1.1:12345
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to 10.20.1.1:12345

It seems that the code does not report an error, but when it is actually run, a huge problem occurs. First of all, if you access the content of port 80, there seems to be no big problem, and you can access it normally:

2022/04/07 08:12:41 9756#56 [debug] id=100004-1: handle request GET http://local.local.wooc.org/cart
2022/04/07 08:12:41 9756#56 [debug] urlfilter: id=100004-1: saving session
2022/04/07 08:12:41 9756#56 [debug] id=100004-1: request was overridden by: http://local.wooc.org/cart
2022/04/07 08:12:41 9756#56 [debug] id=100004-1: response was overridden by: 200 OK
2022/04/07 08:12:41 9756#56 [debug] id=100004: waiting for request
2022/04/07 08:12:42 9756#51 [debug] id=100005: accepted connection from 10.20.1.92:54267

But when accessing the link to 443, it cannot be accessed, and a bunch of garbled characters are prompted:

2022/04/07 08:12:42 9756#35 [debug] id=100005: failed to read request: malformed HTTP request "\x16\x03\x01\x02\x00\x01\x00\x01\xfc\x03\x03**\xa41\x92\x963K\x84\xb5\xe6f{>W\xb9\xcbVL\xe5\xc1[\xa2I\xeb#\x96xH\u0094\xe7 \xd2=\xa27\x1a\xb83\xa7?[\x83s(\xcfy\xeeʞ\xcfJ\x97`\xeb\x03\xb2;v\xfaJO\xf65\x006\xca\xca\x13\x01\x13\x02\x13\x03\xc0,\xc0+̩\xc00\xc0/̨\xc0$\xc0#\xc0"
2022/04/07 08:12:42 9756#61 [debug] id=100005: closing connection due to: malformed HTTP request "\x16\x03\x01\x02\x00\x01\x00\x01\xfc\x03\x03**\xa41\x92\x963K\x84\xb5\xe6f{>W\xb9\xcbVL\xe5\xc1[\xa2I\xeb#\x96xH\u0094\xe7 \xd2=\xa27\x1a\xb83\xa7?[\x83s(\xcfy\xeeʞ\xcfJ\x97`\xeb\x03\xb2;v\xfaJO\xf65\x006\xca\xca\x13\x01\x13\x02\x13\x03\xc0,\xc0+̩\xc00\xc0/̨\xc0$\xc0#\xc0"
2022/04/07 08:12:42 9756#51 [debug] id=100006: accepted connection from 10.20.1.92:54268

It should be a CONNECT request, but the above is not.

I have been troubled by this problem for a long time. I hope the official can help me when I see my post, and I will continue to support you with more and better products.

Segfault if client does not trust the proxy's SSL certificate

Greetings, and thanks for providing this library.

While getting set up with the examples, I managed to crash the proxy server because I did not pass the CA cert to curl.

$ curl -v -x https://user:[email protected]:3333/ https://www.google.com/
*   Trying 127.0.0.1:3333...
* Connected to 127.0.0.1 (127.0.0.1) port 3333 (#0)
* ALPN: offers http/1.1
* (304) (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (IN), TLS handshake, Server hello (2):
* (304) (IN), TLS handshake, Unknown (8):
* (304) (IN), TLS handshake, Certificate (11):
* SSL certificate problem: self signed certificate in certificate chain
* Closing connection 0
curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Resulted in the following segfault:

$ go run examples/mitm/main.go 
2023/10/20 11:56:57 55262#1 [debug] mitm: cache miss for 127.0.0.1
2023/10/20 11:56:57 55262#6 [info] start listening to [::]:3333
2023/10/20 11:56:59 55262#6 [debug] id=100001: accepted connection from 127.0.0.1:58335
2023/10/20 11:56:59 55262#9 [debug] id=100001: waiting for request
2023/10/20 11:56:59 55262#10 [debug] id=100001: failed to read request: remote error: tls: unknown certificate authority
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x40 pc=0x10468f04c]

goroutine 9 [running]:
github.com/AdguardTeam/gomitmproxy.(*Proxy).handleRequest(0x140001b2200, 0x1400006a940)
	/Users/steve/go/github.com/gomitmproxy/proxy.go:232 +0x3c
github.com/AdguardTeam/gomitmproxy.(*Proxy).handleLoop(0x140001b2200, 0x0?)
	/Users/steve/go/github.com/gomitmproxy/proxy.go:220 +0x70
github.com/AdguardTeam/gomitmproxy.(*Proxy).handleConnection(0x140001b2200, 0x1400006a940)
	/Users/steve/go/github.com/gomitmproxy/proxy.go:208 +0x10c
created by github.com/AdguardTeam/gomitmproxy.(*Proxy).serve
	/Users/steve/go/github.com/gomitmproxy/proxy.go:191 +0x34
exit status 2

The issue looks to be this line of code which is dereferencing the request prior to checking err.

I'll submit a PR to fix.

Make a guide on how to setup

I have no idea how to setup Go at all. Nor do I know how to setup this Go MITM proxy.

Can you please make a guide so I know how to set it up?

Redirect bug - failed to round trip: net/http: HTTP/1.x transport connection broken

Hello,

Thank you for open sourcing this excellent library!

I am starting to play with it and have noticed an issue with the sample code that suggests an issue in the library itself.

I have built the example and have it working perfectly for most sites (with a new CA I have generated and added to my trust store for TLS MitM), I have also removed the proxy authentication in the example.

I am testing it on Linux via chromium-browser --proxy-server="https://127.0.0.1:3333" so there's no iptables manipulation going on to add complexity.

The problem is that the proxy breaks on the login for ChatGPT https://chat.openai.com/auth/login

I am unsure if AdGuard itself is impacted, as I am not currently running it.

The log output from my proxy binary is as follows:

2024/03/04 11:51:07 7271#321 [debug] id=100022-1-1-2: handle request POST https://chat.openai.com/api/auth/signin/login-web?prompt=login
2024/03/04 11:51:07 7271#321 [error] id=100022-1-1-2: failed to round trip: net/http: HTTP/1.x transport connection broken: http: ContentLength=100 with Body length 0
2024/03/04 11:51:07 7271#321 [debug] id=100022-1-1-2: received response 502 Bad Gateway
2024/03/04 11:51:07 7271#321 [info] onResponse: https://chat.openai.com/api/auth/signin/login-web?prompt=login
2024/03/04 11:51:07 7271#321 [debug] id=100022-1-1-2: received close request
2024/03/04 11:51:07 7271#321 [debug] id=100022-1-1: closing connection due to: closing connection
2024/03/04 11:51:07 7271#321 [debug] id=100022: closing connection due to: closing connection

Based specifically on failed to round trip: net/http: HTTP/1.x transport connection broken: http: ContentLength=100 with Body length 0, what I believe is happening here is as follows:

  1. The ChatGPT front end loads successfully via the proxy
  2. You click login and a request is made to the login service - the front end is a React application so it is not making a full reload of the page (NOTE: Possibly other React applications may be impacted - I will update the issue if I find more)
  3. Because a new request has not been made, the body is now empty because the http.request body is a buffer and once it is read in the first call, the buffer becomes empty and there is no body content to send in redirect call.

@ameshkov if you could please advise I would greatly appreciate it, thank you!

may cause the connection to end prematurely

donec := make(chan bool, 2)

before entering the copyConnectTunnel logic, it should reset the ctx deadline, otherwise even if the remote server has been sending data back to the user, but the user side has not read any data(from browser or any other app), it will cause the connection to be interrupted abnormally(read deadline and return).

first record does not look like a TLS handshake

go version go1.14 darwin/amd64
mac

examples/mitm/main.go output error

2020/08/18 16:31:10 84778#1 [debug] mitm: cache miss for 127.0.0.1
2020/08/18 16:31:10 84778#35 [info] start listening to [::]:8080
2020/08/18 16:31:20 84778#35 [debug] id=100001: accepted connection from 127.0.0.1:60014
2020/08/18 16:31:20 84778#5 [debug] id=100001: waiting for request
2020/08/18 16:31:20 84778#6 [debug] id=100001: failed to read request: tls: first record does not look like a TLS handshake
2020/08/18 16:31:20 84778#5 [debug] id=100001: closing connection due to: tls: first record does not look like a TLS handshake

may cause connection hang

go copyConnectTunnel(session, remoteConn, session.ctx.conn, donec)

consider this case.

  1. user use mitm server to proxy ssh traffic(or any other unmitmable traffic)
  2. mitm server determined that dont need mitm and go into copy tunnel logic
  3. client begin sending handshake info but client crash abnomally

in this case,
client=>mitm connection will be close
but mitm => ssh server connection will be hang forever(ssh server still wait for reading handshake info, they dont know that client had already close the connection).

The latest progress on adding support for transparent proxy to Gomitmproxy

Hey, I stumbled upon a very interesting GO extension this afternoon, it seems to avoid a lot of code changes in Gomitmproxy and implement the function of adding a transparent proxy, I found that adding to Gomitmproxy this afternoon, there seems to be progress, and under the transparent proxy, there is no Before the failed to read request: malformed HTTP request appeared, this seems to be a good start, and I only changed a small range, but I still encountered some problems, which may need the author's help (there is a certificate verification problem , I debug test, but my ability is not enough, I hope the author can solve it).

I found a very interesting extension library, I believe the author must be very interested, https://github.com/inconshreveable/go-vhost, it can get the real hostname in the case of transparent proxy, including the one passed by the client Key information, which seems to be in line with Gomitmproxy's small changes to have the function of transparent proxy.

The only thing I changed is:
https://github.com/AdguardTeam/gomitmproxy/blob/master/proxy.go#L210

type dumbResponseWriter struct {
	net.Conn
}

func (dumb dumbResponseWriter) Header() http.Header {
	panic("Header() should not be called on this ResponseWriter")
}

func (dumb dumbResponseWriter) Write(buf []byte) (int, error) {
	if bytes.Equal(buf, []byte("HTTP/1.0 200 OK\r\n\r\n")) {
		return len(buf), nil // throw away the HTTP OK response from the faux CONNECT request
	}
	return dumb.Conn.Write(buf)
}

func (dumb dumbResponseWriter) WriteHeader(code int) {
	panic("WriteHeader() should not be called on this ResponseWriter")
}

func (dumb dumbResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	return dumb, bufio.NewReadWriter(bufio.NewReader(dumb), bufio.NewWriter(dumb)), nil
}

func (p *Proxy) connHijacker(w http.ResponseWriter) net.Conn {
	hij, ok := w.(http.Hijacker)
	if !ok {
		log.Error("httpserver does not support hijacking")
	}
	proxyClient, _, e := hij.Hijack()
	if e != nil {
		log.Error("Cannot hijack connection " + e.Error())
	}
	proxyClient.Write([]byte("HTTP/1.0 200 OK\r\n\r\n"))

	return proxyClient
}

// handleRequest reads an incoming request and processes it
func (p *Proxy) handleRequest(ctx *Context) error {
    tlsConn, err := vhost.TLS(ctx.conn)
    origReq := &http.Request{
        Method: "CONNECT",
        URL: &url.URL{
            Opaque: tlsConn.Host(),
            Host:   net.JoinHostPort(tlsConn.Host(), "443"),
        },
        Host:       tlsConn.Host(),
        Header:     make(http.Header),
        RemoteAddr: ctx.conn.RemoteAddr().String(),
    }
    hijackerConn := p.connHijacker(dumbResponseWriter{tlsConn})
    ctx.conn = hijackerConn
	
    //origReq, err := p.readRequest(ctx)

Then, pass the traffic to Gomitmproxy again via iptable:


sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to 10.20.1.1:12345
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to 10.20.1.1:12345

After execution, I found that, hey, failed to read request: malformed HTTP request did not appear, it seems to be good:
proxy.go.zip

2022/04/09 10:28:59 12416#6 [debug] id=100476: accepted connection from 10.20.1.92:51399
2022/04/09 10:29:00 12416#3207 [debug] id=100474-1: tunnel finished copying
2022/04/09 10:29:00 12416#3201 [debug] id=100474-1: closed CONNECT tunnel
2022/04/09 10:29:00 12416#3201 [debug] id=100474: closing connection due to: closing connection
2022/04/09 10:29:00 12416#3218 [debug] id=100476-1: handle request CONNECT http:init.push.apple.com
2022/04/09 10:29:00 12416#3218 [debug] id=100476-1: connecting to host: init.push.apple.com:443
2022/04/09 10:29:00 12416#3217 [debug] id=100475-1: tunnel finished copying
2022/04/09 10:29:00 12416#3218 [debug] id=100476-1: connecting to tcp://init.push.apple.com:443

Then, the browser cannot display the normal page and prompts:

safari cannot open the page because it could not establish a secure connection to the server

It seems that the problem appears in the certificate. Can the author reproduce it and help solve it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.