Skip to content

Instantly share code, notes, and snippets.

@asjustas
Forked from afdalwahyu/http_proxy.go
Created June 20, 2024 12:25
Show Gist options
  • Save asjustas/f3475fbfd4fb5a4daaeee1d544c8ec09 to your computer and use it in GitHub Desktop.
Save asjustas/f3475fbfd4fb5a4daaeee1d544c8ec09 to your computer and use it in GitHub Desktop.
golang http proxy server CONNECT method
package main
import (
"bufio"
"encoding/base64"
"flag"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"strings"
"time"
)
func transfer(destination io.WriteCloser, source io.ReadCloser) {
defer destination.Close()
defer source.Close()
io.Copy(destination, source)
}
func main() {
host := flag.String("host", ":80", "host proxy server")
auth := flag.String("auth", "", "authentication to for client to connect proxy, ex: username:password")
flag.Parse()
listener, err := net.Listen("tcp", *host)
if err != nil {
log.Fatal(err)
}
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
go func(c net.Conn) {
br := bufio.NewReader(c)
req, err := http.ReadRequest(br)
if err != nil {
log.Println("buffer: ", err)
return
}
if req.Method == http.MethodConnect {
if *auth != "" {
clientAuth := req.Header.Get("Proxy-Authorization")
if clientAuth == "" {
response := &http.Response{
StatusCode: http.StatusProxyAuthRequired,
ProtoMajor: 1,
ProtoMinor: 1,
}
response.Write(c)
c.Close()
return
}
serverAuth := "Basic " + base64.StdEncoding.EncodeToString([]byte(*auth))
if clientAuth != serverAuth {
response := &http.Response{
StatusCode: http.StatusUnauthorized,
ProtoMajor: 1,
ProtoMinor: 1,
}
response.Write(c)
c.Close()
return
}
}
response := &http.Response{
StatusCode: 200,
ProtoMajor: 1,
ProtoMinor: 1,
}
response.Write(c)
destConn, err := net.DialTimeout("tcp", req.URL.Host, 10*time.Second)
if err != nil {
response := &http.Response{
StatusCode: http.StatusRequestTimeout,
ProtoMajor: 1,
ProtoMinor: 1,
}
response.Write(c)
return
}
go transfer(destConn, c)
go transfer(c, destConn)
} else {
response := &http.Response{
StatusCode: http.StatusRequestTimeout,
ProtoMajor: 1,
ProtoMinor: 1,
Body: ioutil.NopCloser(strings.NewReader("hello world")),
}
response.Write(c)
c.Close()
return
}
}(conn)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment