disable SNI check for tls behind NLB - go

Trying to set up a TLS connection through a NLB appliance in AWS. The connection is good through there(telnet, curl with --insecure). In my Go code, I need to be able to ignore the NLB SNI in the cert verify logic, but I want to keep all other checks. Setting InsecureVerify false is a no go. I know I can set a custom VerifyPeerCertificates in the tls.Config, but how do i go about just ignoring my 1 NLB SNI?
My cert is coming across as:
original url(1) for endpoint (on actual cert)
original url(2) for endpoint (on actual cert)
mnlb-elb.us-east-1.amazonaws.com (added to check, this needs to be ignored)
func customVerify(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
return nil
}
tr := &http.Transport{
TLSClientConfig: &tls.Config{
VerifyPeerCertificate: customVerify
}
}

Related

Are MITM possible when using IP

If I'm making TLS requests to an API server that I'm referencing by IP, are the kinds of MITM attacks that certificate validation prevents still possible?
Background info if it clarifies the question: I'm making TLS requests to a REST API with a static IP that has no domain name associated with it. To make this work in Go, I have to set the InsecureSkipVerify: true, at the Transport layer of my HTTP Client. Does this make my requests less secure?
I would assume it does but I don't really know why.
As #James noted the IP is an irrelevant component of a TLS handshake.
While the standard procedure is:
dial hostname/port
DNS lookup hostname to get IP
TLS handshake w/ IP
reveals hostnames certificate identity
verify cert name matches hostname
Using InsecureSkipVerify: true skips the last step - and is generally only used during development/testing.
You can however use a different name, in this last step, for the certificate identity to match: leveraging the ServerName field in tls.Config:
tc = &tls.Config{
ServerName: "myhostname", // certificate identity
RootCAs: rootca,
// InsecureSkipVerify: true // <- avoid using this
}
d := tls.Dialer{
Config: tc
}
conn, err := d.Dial("tcp", "127.0.0.1:8080")
Here we are dialing an IP address, performing a TLS handshake, but instead of the default behavior of comparing the host cert with 127.0.0.1, it will instead verify it matches myhostname.

Go: Send websocket requests to a proxy port

I have an Envoy proxy instance configured to proxy http and websocket requests. Note that this is not a CONNECT proxy. I want my websocket client to create a websocket request as if it was sending it to the original destination and then deliver the payload to the proxy's listener instead.
What's the recommended way to connect to the local proxy? I believe this is dependent on the specific Go websocket package being used. I can see packages that allow overriding the http.Client used, but the destination address is determined using the websocket URL specified. The only alternative I have is to send the request to ws://proxy_ip:proxy_port/path directly, and specify the destination using some custom HTTP header that the proxy is configured to use for routing. I am not a big fan of this approach.
I want to dial an address different from that in the request
Use Gorilla's Dialer.NetDialContext to dial an address different from the request:
d := websocket.Dialer{
NetDialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
return net.DialContext(ctx, network, "proxy_ip:proxy_port")
},
}
c, r, err := d.Dial("ws://example.com/path", nil)
if err != nil {
// handle error
}

Why is tls.Client failing with message:first record does not look like a TLS handshake

I'm trying to run the buildlet at https://github.com/golang/build/tree/master/cmd/coordinator
There is a locally hosted server connection that keeps failing to connect giving the error:
first record does not look like a TLS handshake
The piece of code that fails is from build/cmd/buildlet/reverse.go and it is:
tcpConn.SetDeadline(time.Now().Add(30 * time.Second))
config := &tls.Config{
ServerName: serverName,
InsecureSkipVerify: devMode,
}
conn := tls.Client(tcpConn, config)
if err := conn.Handshake(); err != nil {
return nil, fmt.Errorf("failed to handshake with coordinator: %v", err)
}
I've gathered that the connection should be established while ignoring TLS issues because the server is at localhost
I can't seem to figure out how to fix this issue.
Instructions on recreating my problem are at the above link. The only change I recommend is using
go run . -mode=dev -listen-http=localhost:8119
for the first command
InsecureSkipVerify just means that TLS certificate validation constraints are relaxed (to a point where your connection is insecure and prone to MITM attacks)
From the documentation:
If InsecureSkipVerify is true, crypto/tls accepts any certificate presented by the server and any host name in that certificate.
You still need to have a connection that uses TLS at the other end. The error that you're getting means that the other side of the connect doesn't speak TLS.
If you don't want to use TLS in devMode, then you should use the tcpConn directly while in dev mode, without wrapping it with a *tls.Conn. *tls.Conn implements net.Conn so after the handshake there shouldn't be any difference in how you use the connection, whether it has TLS or not.

Golang x509 cannot validate certificate

Good day!
I have difficulties with requests in Go. Locally service works fine, but in the server I have this error:
"Post "https://x.x.x.x:xxxx/": x509: cannot validate certificate for x.x.x.x because it doesn't contain any IP SANs
Solutions like using dns is not suite, only ip address with port, since it is an internal service.
Also, tried out:
TLSConfig: &tls.Config{
InsecureSkipVerify: true
}
Updated! Tried out with NodeJS, works fine, so I think problem with Go's tls configs
Please, hint me how can eliminate this error?

How does Golang's LDAP client library work with certificates?

I'm trying to connect to G Suite's LDAPS server with Golang's LDAP library.
However, in the example, I don't really understand two things.
It seems like it connects via non-encrypted LDAP first? Then it upgrades? Is that true, if so, can't I just start out by connecting encrypted?
Google supplies a .cer & .key file to connect to their ldap server. I don't see where it use these files. I do see in their docs that a lot of LDAP clients require the files to be combined into a .p12. Is that necessary for Go?
If the person that answers this could supply an example, that would really help. Thank you.
StartTLS, as you've noted, allows one to upgrade a connection to use a TLS later on in the connections lifecycle.
If you want to connect via TLS immediately, then use the well known ldaps port 636 (instead of 389) - and use DialTLS:
// l, err := ldap.Dial("tcp", "ldap.example.com:389"))
var tlsConf *tls.Config
ldaps, err := ldap.DialTLS("tcp", "gsuite.google.com:636", tlsConf)
You may also use DialURL which infers TLS or non-TLS by the schema e.g.
conn, err := ldap.DialURL("ldap://ldap.example.com") // non-TLS on default port 389
conn, err := ldap.DialURL("ldaps://ldap.example.com") // TLS on default port 636
conn, err := ldap.DialURL("ldaps://myserver.com:1234") // TLS on custom port 1234
// Note: there is no way to add a custom tls.Config with this method
So if using, DialTLS: since you are using a Google service, it's trust cert should already be in your keychain, so a simple tls.Config should suffice:
tlsConf = &tls.Config{ServerName:"gsuite.google.com"} // <- ensure this matches the hostname provided by the server
If you want to get things up an running for testing:
// DONT EVER USE THIS IN PRODUCTION...
tlsConf = &tls.Config{InsecureSkipVerify: true} // DO NOT USE EVER
To add a client cert for client-side authentication:
// Load cer & key files into a pair of []byte
cert, err := tls.X509KeyPair(cer, key)
if err != nil {
log.Fatal(err)
}
tlsCong := &tls.Config{Certificates: []tls.Certificate{cert}}

Resources