Created
September 11, 2023 18:55
-
-
Save howardjohn/94b8b0acc9014517826e8df422f94ab7 to your computer and use it in GitHub Desktop.
Trivial TLS proxy. Do not use, its neither tested nor secure.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/rand" | |
"crypto/rsa" | |
"crypto/tls" | |
"crypto/x509" | |
"encoding/pem" | |
"flag" | |
syscall "golang.org/x/sys/unix" | |
"io" | |
"log" | |
"math/big" | |
"net" | |
"os" | |
"os/signal" | |
"sync" | |
"time" | |
) | |
var ( | |
remote = flag.String("r", "127.0.0.1:8080", "remote addresses") | |
) | |
func main() { | |
flag.Parse() | |
go outbound() | |
go inbound() | |
WaitSignal() | |
} | |
func outbound() { | |
listener, err := net.Listen("tcp", "0.0.0.0:15001") | |
if err != nil { | |
panic(err) | |
} | |
for { | |
conn, err := listener.Accept() | |
if err != nil { | |
panic(err) | |
} | |
log.Println("accepted outbound connection") | |
go proxyConn(conn, *remote, true) | |
} | |
} | |
func inbound() { | |
listener, err := tls.Listen("tcp", "0.0.0.0:15006", generateTLSConfig()) | |
if err != nil { | |
panic(err) | |
} | |
for { | |
conn, err := listener.Accept() | |
if err != nil { | |
panic(err) | |
} | |
log.Println("accepted inbound connection") | |
_, port, _ := net.SplitHostPort(*remote) | |
go proxyConn(conn, "127.0.0.1:"+port, false) | |
} | |
} | |
func WaitSignal() { | |
sigs := make(chan os.Signal, 1) | |
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) | |
<-sigs | |
} | |
func proxyConn(incoming net.Conn, dstIP string, useTLS bool) { | |
var outgoing net.Conn | |
if useTLS { | |
c, err := tls.Dial("tcp", dstIP, generateTLSConfig()) | |
if err != nil { | |
panic(err) | |
} | |
outgoing = c | |
} else { | |
c, err := net.Dial("tcp", dstIP) | |
if err != nil { | |
panic(err) | |
} | |
outgoing = c | |
} | |
log.Println("connected to upstream ", outgoing.RemoteAddr().String()) | |
t0 := time.Now() | |
wg := sync.WaitGroup{} | |
wg.Add(1) | |
go func() { | |
n, err := io.Copy(incoming, outgoing) | |
log.Printf("upstream complete, wrote=%v, err=%v", n, err) | |
incoming.Close() | |
outgoing.Close() | |
wg.Done() | |
}() | |
n, err := io.Copy(outgoing, incoming) | |
log.Printf("downstream complete, wrote=%v, err=%v", n, err) | |
incoming.Close() | |
outgoing.Close() | |
wg.Wait() | |
log.Println("connection closed in ", time.Since(t0)) | |
} | |
func generateTLSConfig() *tls.Config { | |
key, err := rsa.GenerateKey(rand.Reader, 1024) | |
if err != nil { | |
panic(err) | |
} | |
template := x509.Certificate{SerialNumber: big.NewInt(1)} | |
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key) | |
if err != nil { | |
panic(err) | |
} | |
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}) | |
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) | |
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM) | |
if err != nil { | |
panic(err) | |
} | |
return &tls.Config{ | |
Certificates: []tls.Certificate{tlsCert}, | |
InsecureSkipVerify: true, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment