mirror of
https://github.com/boringproxy/boringproxy.git
synced 2024-07-04 11:22:57 -05:00
Also cleaned up things a bit by moving the ProxyTcp logic into a separate file and sharing it between the client and server.
109 lines
2.1 KiB
Go
109 lines
2.1 KiB
Go
package boringproxy
|
|
|
|
import (
|
|
//"errors"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/caddyserver/certmagic"
|
|
)
|
|
|
|
func ProxyTcp(conn net.Conn, addr string, port int, useTls bool, certConfig *certmagic.Config) error {
|
|
|
|
if useTls {
|
|
tlsConfig := &tls.Config{
|
|
GetCertificate: certConfig.GetCertificate,
|
|
}
|
|
|
|
tlsConfig.NextProtos = append([]string{"http/1.1", "h2", "acme-tls/1"}, tlsConfig.NextProtos...)
|
|
|
|
tlsConn := tls.Server(conn, tlsConfig)
|
|
|
|
tlsConn.Handshake()
|
|
if tlsConn.ConnectionState().NegotiatedProtocol == "acme-tls/1" {
|
|
tlsConn.Close()
|
|
return nil
|
|
}
|
|
|
|
go handleConnection(tlsConn, addr, port)
|
|
} else {
|
|
go handleConnection(conn, addr, port)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func handleConnection(conn net.Conn, upstreamAddr string, port int) {
|
|
|
|
defer conn.Close()
|
|
|
|
useTls := false
|
|
addr := upstreamAddr
|
|
|
|
if strings.HasPrefix(upstreamAddr, "https://") {
|
|
addr = upstreamAddr[len("https://"):]
|
|
useTls = true
|
|
}
|
|
|
|
var upstreamConn net.Conn
|
|
var err error
|
|
|
|
if useTls {
|
|
tlsConfig := &tls.Config{
|
|
InsecureSkipVerify: true,
|
|
}
|
|
upstreamConn, err = tls.Dial("tcp", fmt.Sprintf("%s:%d", addr, port), tlsConfig)
|
|
} else {
|
|
upstreamConn, err = net.Dial("tcp", fmt.Sprintf("%s:%d", addr, port))
|
|
}
|
|
|
|
if err != nil {
|
|
log.Print(err)
|
|
return
|
|
}
|
|
|
|
defer upstreamConn.Close()
|
|
|
|
var wg sync.WaitGroup
|
|
wg.Add(2)
|
|
|
|
// Copy request to upstream
|
|
go func() {
|
|
_, err := io.Copy(upstreamConn, conn)
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
}
|
|
|
|
if c, ok := upstreamConn.(*net.TCPConn); ok {
|
|
c.CloseWrite()
|
|
} else if c, ok := upstreamConn.(*tls.Conn); ok {
|
|
c.CloseWrite()
|
|
}
|
|
|
|
wg.Done()
|
|
}()
|
|
|
|
// Copy response to downstream
|
|
go func() {
|
|
_, err := io.Copy(conn, upstreamConn)
|
|
//conn.(*net.TCPConn).CloseWrite()
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
}
|
|
// TODO: I added this to fix a bug where the copy to
|
|
// upstreamConn was never closing, even though the copy to
|
|
// conn was. It seems related to persistent connections going
|
|
// idle and upstream closing the connection. I'm a bit worried
|
|
// this might not be thread safe.
|
|
conn.Close()
|
|
wg.Done()
|
|
}()
|
|
|
|
wg.Wait()
|
|
}
|