Last active
August 6, 2021 08:48
-
-
Save oxtoacart/5e78d25a7f9a9cda10cd to your computer and use it in GitHub Desktop.
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/tls" | |
"crypto/x509" | |
"fmt" | |
"io" | |
"log" | |
"net" | |
"net/http" | |
"os" | |
"time" | |
) | |
const ( | |
MASQUERADE_AS = "cdnjs.com" // the host to which we open a TLS connection | |
REAL_DEST = "geo.getiantem.org" // the host for which we make an HTTP request over the TLS connection | |
) | |
func main() { | |
client := &http.Client{ | |
Transport: &http.Transport{ | |
Dial: dialTLS, | |
}, | |
} | |
req, _ := http.NewRequest("GET", "http://"+REAL_DEST+"/lookup", nil) | |
req.Write(os.Stdout) | |
resp, err := client.Do(req) | |
log.Println("Made request") | |
if err != nil { | |
log.Fatalf("Unable to do GET: %s", err) | |
} | |
defer resp.Body.Close() | |
io.Copy(os.Stdout, resp.Body) | |
} | |
func dialTLS(network, addr string) (net.Conn, error) { | |
// Dial with net.Dial | |
conn, err := net.Dial("tcp", MASQUERADE_AS+":443") | |
if err != nil { | |
return nil, err | |
} | |
// Then wrap the connection with a tls Client. The combination of net.Dial | |
// + tls.Client allows us to avoid using a ServerName, unlike tls.Dial which | |
// automatically populates ServerName based on the dialed address. | |
tlsConn := tls.Client(conn, &tls.Config{ | |
// Need to set this so that the client handshake code doesn't complain | |
// about having neither a ServerName nor InsecureSkipVerify being true. | |
InsecureSkipVerify: true, | |
}) | |
err = tlsConn.Handshake() | |
if err != nil { | |
return nil, err | |
} | |
// Because we set InsecureSkipVerify, tls won't be verifying the server's | |
// cert for us, so we have to do it ourselves | |
err = verifyServerCerts(tlsConn) | |
if err != nil { | |
return nil, fmt.Errorf("Unable to verify server cert: %s", err) | |
} | |
return tlsConn, nil | |
} | |
func verifyServerCerts(conn *tls.Conn) error { | |
certs := conn.ConnectionState().PeerCertificates | |
opts := x509.VerifyOptions{ | |
Roots: nil, | |
CurrentTime: time.Now(), | |
DNSName: MASQUERADE_AS, | |
Intermediates: x509.NewCertPool(), | |
} | |
for i, cert := range certs { | |
if i == 0 { | |
continue | |
} | |
opts.Intermediates.AddCert(cert) | |
} | |
_, err := certs[0].Verify(opts) | |
return err | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment