Below is my simple static "SSL Proxy" that listens on port 8000, and connects to another machine 10.3.0.124:443, and the proxy logs traffic both ways on screen.
To generate key.pem and cert.pem, you can use openssl, or use go team's simple program included in go package: http://golang.org/src/pkg/crypto/tls/generate_cert.go
package main import ( "io" "log" "net" "fmt" "os" "crypto/tls" "crypto/rand" ) func checkError(err error) { if err != nil { fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) os.Exit(1) } } /* slower, by we can print/log everything */ func myrawcopy(dst,src net.Conn) (written int64, err error) { buf := make([]byte, 32*1024) for { nr, er := src.Read(buf) if nr > 0 { fmt.Printf("%s",string(buf[0:nr])); nw, ew := dst.Write(buf[0:nr]) if nw > 0 { written += int64(nw) } if ew != nil { err = ew break } if nr != nw { err = io.ErrShortWrite break } } if er == io.EOF { break } if er != nil { err = er break } } return written, err } func myiocopy(dst net.Conn, src net.Conn){ myrawcopy(dst, src) //io.Copy(dst,src); dst.Close(); src.Close(); } func handleclient(c net.Conn){ config := tls.Config{InsecureSkipVerify: true} conn, err := tls.Dial("tcp", "10.3.0.124:443", &config) checkError(err) go myiocopy(conn,c) //io.Copy(c, conn) myrawcopy(c, conn) c.Close() conn.Close(); } func main() { cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem") if err != nil { log.Fatalf("server: loadkeys: %s", err) } config := tls.Config{Certificates: []tls.Certificate{cert}} config.Rand = rand.Reader service := "0.0.0.0:8000" listener, err := tls.Listen("tcp", service, &config) if err != nil { log.Fatalf("server: listen: %s", err) } log.Printf("server: listening on %s for https, connects to https://10.3.0.124:443",service) for { conn, err := listener.Accept() if err != nil { log.Printf("server: accept: %s", err) break } defer conn.Close() log.Printf("server: accepted from %s", conn.RemoteAddr()) go handleclient(conn) } }
Why are you initializing config.Rand? The default is fine.
ReplyDeleteActually it is the same, by default it's using rand.Rand, but that's an implementation detail: http://golang.org/src/pkg/crypto/tls/common.go Line 277
DeleteHello, I stumbled up on your blog while tryign to find solution of my question at http://stackoverflow.com/questions/21562269/golang-how-to-specify-certificate-in-tls-config-for-http-client can you help me to find out as how can I achieve what I am looking for?
ReplyDeletedmwm2 has this patch:
ReplyDeleteI've got the Windows client connecting through your proxy, which is
useful. It actually receives the certificate MD5 *from* the server,
which is kind of pointless, and requires the following hack (replace
cert hashes as appropriate, of course):
@@ -18,12 +20,15 @@ func checkError(err error) {
}
/* slower, by we can print/log everything */
-func myrawcopy(dst,src net.Conn) (written int64, err error) {
+func myrawcopy(dst,src net.Conn, direction string) (written int64, err error) {
buf := make([]byte, 32*1024)
+ realcert := []byte("cert_md5=90ab8294b0c3fe0b84af563bb4adf37c")
+ mycert := []byte("cert_md5=be9ac5a0dac73483037315ac51b81beb")
for {
nr, er := src.Read(buf)
if nr > 0 {
- fmt.Printf("%s",string(buf[0:nr]));
+ buf := bytes.Replace(buf, realcert, mycert, 1)
+ fmt.Printf("Packet %s:\n%s",direction, hex.Dump(buf[0:nr]));
nw, ew := dst.Write(buf[0:nr])
if nw > 0 {
written += int64(nw)
You might want to remove 'defer conn.Close()' in the main function. It will cause memory leak.
ReplyDeleteHi All,
ReplyDeleteCan someone help explaining how can we use proxy IP & port for below code.
tls.Dial("tcp", "10.3.0.124:443", &config)
Assume that I want to connect to 10.3.0.124 on port 443 but my network has proxy in IE setting.
Thanks in Advance.