Skip to content

Instantly share code, notes, and snippets.

@oxtoacart
Last active August 6, 2021 08:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save oxtoacart/5e78d25a7f9a9cda10cd to your computer and use it in GitHub Desktop.
Save oxtoacart/5e78d25a7f9a9cda10cd to your computer and use it in GitHub Desktop.
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