Tls verification_mode, custom validation options?

https://www.elastic.co/guide/en/beats/filebeat/current/configuration-ssl.html#_literal_verification_mode_literal

As I understand it, if verification_mode is set to full, then the beats client will error if the hostname of the server doesn't match the CN or SAN on the certificate presented by the logstash server.

So if I connect to 127.0.0.1:10002 I get an error from the beat like the following:

Failed to connect to backoff(async(tcp://127.0.0.1:10002)): x509: cannot validate certificate for 127.0.0.1 because it doesn't contain any IP SANs

I interpret this to mean that the client refuses to connect because verification is set to full and I am connecting to 127.0.0.1 and 127.0.0.1 is not listed as CN or SAN on server certificate?

The docs warn that if I do verification_mode=none then I am open to MITM attacks. There are only the two options.

rsyslog client lets me set $ActionSendStreamDriverPermittedPeer syslog-server and then it validates that the server certificate is signed by the configured CA and that the CN/SAN in the server certificate matches syslog-server. I can connect by any ip or hostname I want and it doesn't impact whether the server certificate validates.

It would be great if there was a similar option for beats: way to do server certificate verification without tying that verification to the hostname/ip used to connect. For web browsers, hostname/ip makes sense. In a server-to-server environment people may have many different hostname/ip/service-discovery approaches. The important things for client verification in my opinion are:

  • server certificate is signed by a recognized CA (in my case, my private ca)
  • optionally server can be further verified by matching against CN/SAN in server certificate...which shouldn't be required to match the hostname/ip of the server (unless there is some good reason for that I am missing)

Question 1: If I am specifying my own CA via ssl.certificate_authorities...I would assume there is at least some level of verification happening...the server cert needs to be signed by the CA configured on the client? Right? If so, I can just turn verification to none and not worry about MITM.

Question 2: Did I miss something, other ideas?

Currently one full and none is supported by Beats. There is some github enhancement request you can follow or discuss.

Right. I guess my point/question was about the type of verification that is done.... checking against hostname/CN/SAN vs checking for specific certificate, specific CA or specific CN/SAN in the certificate .

I am not sure how many ELK setups are using certificates signed by commercial CAs and run under public hostnames...I'm also not sure how many companies would pay for commercial signing of certificates for use on private hostnames inside their infrastructure.

Of course with our own private CA we can also generate per-host certificates in order to provide implicit verification based on the hostname...but then we need to make sure all our clients connect using the same hostname all the time (never the IP for instance).

Feels like this forces a tighter coupling between beats and how service discovery and infrastructure provisioning is done. ie if you deploy/move ELK server to a different host you also need to re-generate and re-deploy server certificates every time.

I'm not arguing that nobody would want this to work the current way...just pointing out that there are other types of verification... for instance as a client I can say: I only want to trust server certificates that are signed by CA X...AND I only want to trust servers that have CN or SAN that matches "logstash-server" for instance.

With rsyslog over TLS, this works because the $ActionSendStreamDriverPermittedPeer lets us specify trusted server names (ie CN/SAN on server cert) separately from the connection parameters.

I'll check out the github enhancement request. Currently as a work-around I have disabled verification (none) and just rely on CA verification since I am using a private CA.

It seems I misunderstood what ssl.verification_mode: none does. Seems that turning off verification ignores all SSL settings including the configured ssl.certificate_authorities so we can't even rely on CA verification?