mirror of
https://github.com/dstotijn/hetty
synced 2024-11-10 06:04:19 +00:00
Initial commit
This commit is contained in:
parent
26ec9f72e5
commit
c48562e873
5 changed files with 93 additions and 45 deletions
2
go.mod
2
go.mod
|
@ -1,5 +1,3 @@
|
|||
module github.com/dstotijn/gurp
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/google/martian v2.1.0+incompatible
|
||||
|
|
2
go.sum
2
go.sum
|
@ -1,2 +0,0 @@
|
|||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
50
main.go
50
main.go
|
@ -2,53 +2,21 @@ package main
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"github.com/google/martian"
|
||||
"github.com/google/martian/mitm"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func main() {
|
||||
p := martian.NewProxy()
|
||||
defer p.Close()
|
||||
proxy := NewProxy()
|
||||
|
||||
tlsc, err := tls.LoadX509KeyPair("/Users/dstotijn/.ssh/gurp_cert.pem", "/Users/dstotijn/.ssh/gurp_key.pem")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
priv := tlsc.PrivateKey
|
||||
|
||||
x509c, err := x509.ParseCertificate(tlsc.Certificate[0])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
s := &http.Server{
|
||||
Addr: ":8080",
|
||||
Handler: proxy,
|
||||
TLSNextProto: map[string]func(*http.Server, *tls.Conn, http.Handler){}, // Disable HTTP/2
|
||||
}
|
||||
|
||||
mc, err := mitm.NewConfig(x509c, priv)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
err := s.ListenAndServe()
|
||||
if err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("HTTP server closed: %v", err)
|
||||
}
|
||||
mc.SetValidity(time.Hour)
|
||||
mc.SetOrganization("Gurp, Inc.")
|
||||
|
||||
p.SetMITM(mc)
|
||||
|
||||
l, err := net.Listen("tcp", ":8080")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := p.Serve(l); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}()
|
||||
|
||||
sigc := make(chan os.Signal, 1)
|
||||
signal.Notify(sigc, os.Interrupt, os.Kill)
|
||||
<-sigc
|
||||
}
|
||||
|
|
3
modd.conf
Normal file
3
modd.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
**/*.go {
|
||||
daemon +sigterm: go run .
|
||||
}
|
81
proxy.go
Normal file
81
proxy.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
)
|
||||
|
||||
// Proxy is used to forward HTTP requests.
|
||||
type Proxy struct {
|
||||
rp httputil.ReverseProxy
|
||||
}
|
||||
|
||||
// NewProxy returns a new Proxy.
|
||||
func NewProxy() *Proxy {
|
||||
return &Proxy{
|
||||
rp: httputil.ReverseProxy{
|
||||
Director: func(r *http.Request) {
|
||||
log.Printf("Director handled URL: %v", r.URL)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("ServeHTTP: Received request (host: %v, url: %v", r.Host, r.URL)
|
||||
|
||||
if r.Method == http.MethodConnect {
|
||||
p.handleConnect(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
p.rp.ServeHTTP(w, r)
|
||||
log.Printf("ServeHTTP: Finished (host: %v, url: %v", r.Host, r.URL)
|
||||
}
|
||||
|
||||
func (p *Proxy) handleConnect(w http.ResponseWriter, r *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
log.Printf("handleConnect: ResponseWriter is not a http.Hijacker (type: %T)", w)
|
||||
writeError(w, r, http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
|
||||
// destConn is the TCP connection to the destination web server of the
|
||||
// proxied HTTP request.
|
||||
destConn, err := net.Dial("tcp", r.Host)
|
||||
if err != nil {
|
||||
log.Printf("handleConnect: Connect to destination host failed: %v", err)
|
||||
writeError(w, r, http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
defer destConn.Close()
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
||||
// clientConn is the TCP connection to the client.
|
||||
clientConn, _, err := hj.Hijack()
|
||||
if err != nil {
|
||||
log.Printf("handleConnect: Hijack failed: %v", err)
|
||||
writeError(w, r, http.StatusServiceUnavailable)
|
||||
return
|
||||
}
|
||||
defer clientConn.Close()
|
||||
|
||||
errc := make(chan error, 1)
|
||||
go tunnelData(destConn, clientConn, errc)
|
||||
go tunnelData(clientConn, destConn, errc)
|
||||
<-errc
|
||||
}
|
||||
|
||||
func tunnelData(dst, src io.ReadWriter, errc chan<- error) {
|
||||
_, err := io.Copy(dst, src)
|
||||
errc <- err
|
||||
}
|
||||
|
||||
func writeError(w http.ResponseWriter, r *http.Request, code int) {
|
||||
http.Error(w, http.StatusText(code), code)
|
||||
}
|
Loading…
Reference in a new issue