Skip to content

Commit

Permalink
rewrote HTTP proxy, and much better logging
Browse files Browse the repository at this point in the history
  • Loading branch information
mosajjal committed Oct 17, 2022
1 parent e0969a4 commit 0b527a9
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 13 deletions.
122 changes: 122 additions & 0 deletions httpproxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package main

import (
"io"
"net/http"
"time"

log "github.com/sirupsen/logrus"
)

var verbose = false

var passthruRequestHeaderKeys = [...]string{
"Accept",
"Accept-Encoding",
"Accept-Language",
"Cache-Control",
"Cookie",
"Referer",
"User-Agent",
}

var passthruResponseHeaderKeys = [...]string{
"Content-Encoding",
"Content-Language",
"Content-Type",
"Cache-Control", // TODO: Is this valid in a response?
"Date",
"Etag",
"Expires",
"Last-Modified",
"Location",
"Server",
"Vary",
}

func runHTTP() {
handler := http.DefaultServeMux

handler.HandleFunc("/", handle80)

s := &http.Server{
Addr: ":80",
Handler: handler,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}

s.ListenAndServe()
}

func handle80(w http.ResponseWriter, r *http.Request) {
log.Infof("[HTTP] REQ: %v %v%v\n", r.Method, r.Host, r.URL)

// Construct filtered header to send to origin server
hh := http.Header{}
for _, hk := range passthruRequestHeaderKeys {
if hv, ok := r.Header[hk]; ok {
hh[hk] = hv
}
}

// Construct request to send to origin server
rr := http.Request{
Method: r.Method,
URL: r.URL,
Header: hh,
Body: r.Body,
// TODO: Is this correct for a 0 value?
// Perhaps a 0 may need to be reinterpreted as -1?
ContentLength: r.ContentLength,
Close: r.Close,
}
rr.URL.Scheme = "http"
rr.URL.Host = r.Host

// check to see if this host is listed to be processed, otherwise RESET
if !c.AllDomains && inDomainList(r.Host+".") {
http.Error(w, "Could not reach origin server", 403)
log.Warnf("[HTTP] a client requested connection to %s, but it's not allowed as per configuration.. sending 403", r.Host)
return
}

// Forward request to origin server
resp, err := http.DefaultTransport.RoundTrip(&rr)
if err != nil {
// TODO: Passthru more error information
http.Error(w, "Could not reach origin server", 500)
log.Warnf("%s", err)
return
}
defer resp.Body.Close()

if verbose {
log.Infof("[HTTP] RES: %v %+v\n", resp.Status, resp.Header)
} else {
log.Infof("[HTTP] RES: %v\n", resp.Status)
}

// Transfer filtered header from origin server -> client
respH := w.Header()
for _, hk := range passthruResponseHeaderKeys {
if hv, ok := resp.Header[hk]; ok {
respH[hk] = hv
}
}
w.WriteHeader(resp.StatusCode)

// Transfer response from origin server -> client
if resp.ContentLength > 0 {
// (Ignore I/O errors, since there's nothing we can do)
io.CopyN(w, resp.Body, resp.ContentLength)
} else if resp.Close { // TODO: Is this condition right?
// Copy until EOF or some other error occurs
for {
if _, err := io.Copy(w, resp.Body); err != nil {
break
}
}
}
}
18 changes: 5 additions & 13 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ type runConfig struct {

var c runConfig

func handle80(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "https://"+r.Host+r.RequestURI, http.StatusFound)
}
// func handle80(w http.ResponseWriter, r *http.Request) {
// http.Redirect(w, r, "https://"+r.Host+r.RequestURI, http.StatusFound)
// }

func pipe(conn1 net.Conn, conn2 net.Conn) {
chan1 := getChannel(conn1)
Expand Down Expand Up @@ -156,7 +156,7 @@ func handle443(conn net.Conn) error {
return err
}
// check SNI against domainlist for an extra layer of security
if !c.AllDomains && inDomainList(sni) {
if !c.AllDomains && inDomainList(sni+".") {
log.Warnf("[TCP] a client requested connection to %s, but it's not allowed as per configuration.. resetting TCP", sni)
conn.Close()
return nil
Expand All @@ -167,7 +167,7 @@ func handle443(conn net.Conn) error {
return err
}
// TODO: handle timeout and context here
log.Infof("[TCP] connecting to %s (%s)", rAddr, sni)
log.Infof("[TLS] connecting to %s (%s)", rAddr, sni)
target, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: rAddr, Port: 443})
if err != nil {
log.Println("could not connect to target", err)
Expand Down Expand Up @@ -209,14 +209,6 @@ func handleError(err error) {
}
}

func runHTTP() {
http.HandleFunc("/", handle80)
server := http.Server{
Addr: ":80",
}
server.ListenAndServe()
}

func runHTTPS() {
l, err := net.Listen("tcp", c.BindIP+":443")

Expand Down

0 comments on commit 0b527a9

Please sign in to comment.