mirror of
https://git.phreedom.club/localhost_frssoft/compy.git
synced 2024-11-23 16:41:30 +00:00
add http2 support
Add http2 using the go-1.6 net/http built-in support. net/http's http2 doesn't support hijacking, so instead of hijacking the inital CONNECT tcp connection, tunnel proxied requests/responses over the reader and writer streams of the CONNECT request.
This commit is contained in:
parent
6dae9bda0c
commit
a4a691b7b8
74
proxy/mitmconn.go
Normal file
74
proxy/mitmconn.go
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mitmConn struct {
|
||||||
|
w FlushWriter
|
||||||
|
r io.Reader
|
||||||
|
remoteAddr addr
|
||||||
|
closed chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlushWriter interface {
|
||||||
|
io.Writer
|
||||||
|
http.Flusher
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMitmConn(w FlushWriter, r io.Reader, remoteAddr string) *mitmConn {
|
||||||
|
return &mitmConn{
|
||||||
|
w: w,
|
||||||
|
r: r,
|
||||||
|
remoteAddr: addr(remoteAddr),
|
||||||
|
closed: make(chan struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mitmConn) Read(b []byte) (int, error) {
|
||||||
|
return c.r.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mitmConn) Write(b []byte) (int, error) {
|
||||||
|
n, err := c.w.Write(b)
|
||||||
|
c.w.Flush()
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mitmConn) Close() error {
|
||||||
|
close(c.closed)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mitmConn) RemoteAddr() net.Addr {
|
||||||
|
return c.remoteAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mitmConn) LocalAddr() net.Addr {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mitmConn) SetDeadline(t time.Time) error {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mitmConn) SetReadDeadline(t time.Time) error {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mitmConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
type addr string
|
||||||
|
|
||||||
|
func (a addr) String() string {
|
||||||
|
return string(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a addr) Network() string {
|
||||||
|
return "tcp"
|
||||||
|
}
|
|
@ -53,7 +53,7 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func (p *Proxy) handle(w http.ResponseWriter, r *http.Request) error {
|
func (p *Proxy) handle(w http.ResponseWriter, r *http.Request) error {
|
||||||
if r.Method == "CONNECT" {
|
if r.Method == "CONNECT" {
|
||||||
return p.handleConnect(w, r.Host)
|
return p.handleConnect(w, r)
|
||||||
}
|
}
|
||||||
resp, err := forward(r)
|
resp, err := forward(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -88,24 +88,19 @@ func (p *Proxy) proxyResponse(w *ResponseWriter, r *ResponseReader) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Proxy) handleConnect(w http.ResponseWriter, host string) error {
|
func (p *Proxy) handleConnect(w http.ResponseWriter, r *http.Request) error {
|
||||||
if p.ml == nil {
|
if p.ml == nil {
|
||||||
return fmt.Errorf("CONNECT received but mitm is not enabled")
|
return fmt.Errorf("CONNECT received but mitm is not enabled")
|
||||||
}
|
}
|
||||||
h, ok := w.(http.Hijacker)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("connection cannot be hijacked")
|
|
||||||
}
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
conn, _, err := h.Hijack()
|
fw := w.(FlushWriter)
|
||||||
|
fw.Flush()
|
||||||
|
conn := newMitmConn(fw, r.Body, r.RemoteAddr)
|
||||||
|
sconn, err := p.ml.Serve(conn, r.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sconn, err := p.ml.Serve(conn, host)
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
sconn.Close() // TODO: reuse this connection for https requests
|
sconn.Close() // TODO: reuse this connection for https requests
|
||||||
|
<-conn.closed
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue