Skip to content

Instantly share code, notes, and snippets.

@ego008
Last active May 9, 2018 10:42
Show Gist options
  • Save ego008/bb403cc9bfb6736d1b6d9626dddf5c36 to your computer and use it in GitHub Desktop.
Save ego008/bb403cc9bfb6736d1b6d9626dddf5c36 to your computer and use it in GitHub Desktop.
Golang http/https proxy
package main
// ex $ curl --proxy http://127.0.0.1:12345 -L https://www.google.com
import (
"bytes"
"io"
"log"
"net"
"net/url"
"strconv"
"strings"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
l, err := net.Listen("tcp", ":12345")
if err != nil {
log.Panic(err)
}
defer l.Close()
for {
client, err := l.Accept()
if err != nil {
log.Panic(err)
}
go handleClientRequest(client)
}
}
func handleClientRequest(client net.Conn) {
if client == nil {
return
}
defer client.Close()
var b [1024]byte
n, err := client.Read(b[:])
if err != nil {
log.Println(err)
return
}
var method, host, address string
ni := bytes.IndexByte(b[:], '\n')
if ni != -1 {
// 避免url 过长崩溃
sl := strings.Split(string(b[:ni]), " ")
if len(sl) >= 2 {
method, host = sl[0], sl[1]
if _, err := strconv.Atoi(string(host[0])); err == nil {
// fixed https://github.com/golang/go/issues/19297
host = "//" + host
}
}
}
hostPortURL, err := url.Parse(host)
if err != nil {
log.Println(err)
return
}
if hostPortURL.Opaque == "443" { //https访问
address = hostPortURL.Scheme + ":443"
} else { //http访问
if strings.Index(hostPortURL.Host, ":") == -1 { //host不带端口, 默认80
address = hostPortURL.Host + ":80"
} else {
address = hostPortURL.Host
}
}
//获得了请求的host和port,就开始拨号吧
server, err := net.Dial("tcp", address)
if err != nil {
log.Println(err)
return
}
if method == "CONNECT" {
client.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
} else {
server.Write(b[:n])
}
//进行转发
go io.Copy(server, client)
io.Copy(client, server)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment