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

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}}

Related

Create SOCKS5 Proxy in go

I want to create a tor like clone in Go, where I have a local socks5 proxy server from which I get the request, encrypt it and send it via tcp to the network. To work with proxies in go I found the golang.org/x/net/proxy package. By searching how to create a server with it and getting the request data I only find something like this Creating a go socks5 client where people use it to only forward the traffic to another server.
Currently I have this implementation.
dialer, err := proxy.SOCKS5("tcp", "127.0.0.1:31415", nil, proxy.Direct)
if err != nil {
panic(err)
}
My question now is how I can get the data which the computer send via socks5 to this local proxy.

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.

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.

disable SNI check for tls behind NLB

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
}
}

Golang tcp-tls over socks5 proxy client

I create a dialer via
dialer := &net.Dialer{}
and a TLS dialer via
tlsDialer := &tls.Dialer{
NetDialer: dialer,
Config: &tls.Config{InsecureSkipVerify: true},
}
Then I create a socks5 proxy dialer by using
proxyDialer, err := proxy.SOCKS5("tcp", "127.0.0.1:1080", nil, proxy.Direct)
How can I connect remote server though the socks5 proxy?
In other way, how to nest three dialer in the order of net.Dialer->tls.Dialer->proxy.Dialer and finally using proxyDialer.Dial("tcp", "remote:port") to connect the server?
My Env:
OS: Windows 10 x64
Golang: 1.16 (no CGO)
Any help would be greatly appreciated :)
First time asking question in SOF, if I missed sth to say pls tell me :)
Thanks for #Steffen Ullrich
A Dialer is used to establish a connection - but there is only a single connection to establish. Create the connection using proxyDialer, then use tls.Client on the connection given by proxyDialer to "upgrade" it to a tls.Conn.
Just "upgrade" proxy connection to tls
proxyDialer, err := proxy.SOCKS5("tcp", "proxyserver:1080", nil, proxy.Direct)
conn, err = proxyDialer.Dial("tcp", "server:port")
conn = tls.Client(conn, &tls.Config{InsecureSkipVerify: true})

Resources