Skip to main content

TLS Check

Pull

Synopsis​

Director connects to one service from where it runs, asks it to start TLS where its protocol begins in the clear, makes the TLS handshake, and writes the result of every check itself as an ECS document: the TLS version and cipher agreed, the service's certificate, whether it verifies and the days it has left, and the state the service is in — up or down, since when, and after how many checks. After the handshake it sends no request and does not sign in. Nothing is installed on the service.

It is for the TLS services that are no web page, which an HTTP Check already asks: a mail server, LDAPS, a database listener, syslog over TLS, a VPN portal.

The TLS Check is one of six service check devices, each checking one service: a Website, an HTTP Check, a TCP Check, a DNS Check, an ICMP Check, and a TLS Check.

One device, one service. A device checks one service, so every service checked has a row of its own in the fleet list, and the device's connection state says whether that service is up.

The results are the device's own. Every check writes a result, up or down, with no dataset assigned. A TLS Check has no datasets: every result carries the service's certificate and the certificate of its chain that expires first. See Service Check Datasets.

The device dials the service and binds nothing, so service checks never collide on a port, and none blocks a listener on it. One Director owns each device.

note

The TLS Check device needs Director 2.3.1 or later. The other service check devices need 2.2.3.

Schema​

- id: <numeric>
name: <string>
description: <string>
type: tls_check
tags: <string[]>
status: <boolean>
properties:
address: <string>
protocol: <string>
port: <numeric>
tls:
insecure_skip_verify: <boolean>
ca_name: <string>
server_name: <string>
min_tls_version: <string>
max_tls_version: <string>
cert_name: <string>
key_name: <string>
passphrase: <string>
interval: <numeric>
timeout: <numeric>
pipelines: <pipeline[]>

Configuration​

The following fields are used to define the device:

Device​

FieldRequiredDefaultDescription
idY-Unique numeric identifier
nameY-Device name
descriptionN-Optional description
typeY-Must be tls_check
tagsN-Optional tags
statusNtrueEnable/disable the device

Target​

FieldRequiredDefaultDescription
addressY-A host name or an IP address, without a scheme, a port, or a path — not a wildcard. An IPv6 address as it is, or in one pair of brackets
protocolNtlsWhat the check says before its handshake. tls says nothing: the service starts in TLS (LDAPS, IMAPS, SMTPS, a database or a syslog listener). dtls says nothing either, and makes the DTLS 1.2 handshake over UDP — see DTLS. smtp, imap, pop3, ftp, ldap, and postgres make that protocol's request to start TLS — see The Request to Start TLS
portNthe protocol'sFrom 1 to 65535. Left out, it is 443 for tls, 25 for smtp, 143 for imap, 110 for pop3, 21 for ftp, 389 for ldap, and 5432 for postgres. Required for dtls, which has no port of its own (syslog over DTLS 6514, CoAP 5684, RADIUS 2083)

TLS​

FieldRequiredDefaultDescription
tls.insecure_skip_verifyNfalsetrue makes the handshake with any certificate. The service is then up, and the result still says whether the certificate verifies. Pin the CA instead where you can
tls.ca_nameN-A CA to verify the certificate against instead of the operating system's trust store: a path under the service root, or inline PEM
tls.server_nameNthe addressThe name the handshake sends, and the certificate is verified for
tls.min_tls_versionNtls1.2tls1.0 to tls1.3. With dtls, at most tls1.2
tls.max_tls_versionN-No cap. With dtls, at least tls1.2 when set
tls.cert_nameN-A client certificate presented to a service that asks for one, and to no other. Needs tls.key_name. See A Client Certificate
tls.key_nameN-Its private key. Needs tls.cert_name. Withheld from the API's device reads
tls.passphraseN-Decrypts an encrypted key (PKCS#8 or legacy PEM): plain text, ${ENV_VAR}, or $secret{...}. Withheld from the API's device reads
note

TLS material fields (cert_name, key_name, ca_name, client_ca_name) accept any of the following:

  • File name — resolved relative to the service root directory. Nested paths such as certs/prod/server.pem are supported.
  • Absolute path — honored only if it resolves inside the service root. Any path that escapes the root is refused.
  • Inline PEM content — used verbatim when the value contains -----BEGIN.
  • Environment variable — ${ENV_VAR}.
  • Vault reference — $secret{id=...} or $secret{store=...,ref=...}.

tls.status is not read: the check is a handshake.

Verification. The certificate is verified against the operating system's trust store, or tls.ca_name, for tls.server_name, and for the address when that is not set: a name by the names the certificate holds, an address by its addresses. So a service checked by address whose certificate names it by name needs tls.server_name.

A certificate that does not verify fails the check with Certificate error, and is still written: its dates, its names, and its days left. With tls.insecure_skip_verify the handshake is made with any certificate, the service is up, and the result says whether the certificate verifies (service_check.tls.certificate.verified) and why not (unverified), by the same trust store and for the same name.

Pipeline​

The device takes at most one pre-processing pipeline of its own: the device's pipeline picker in the console, pipelines: in a configuration file. Its results go through it, and through none when the device has none.

Datasets​

A TLS Check has no datasets: it writes its results directly. Every result carries the service's certificate under tls.server.x509.*, its days left, and the certificate of its chain that expires first (see Results and State), so the TLS Check Certificates dataset is retired; and Traceroute is a website's dataset alone. A dataset still assigned to the device is left out with a warning in the device's log — see Retired Datasets.

Advanced Configuration​

FieldRequiredDefaultDescription
intervalN60Seconds between checks: a result every interval. At least 10
timeoutN10Seconds the check may take whole — the name resolved, the connect, the request to start TLS, and the handshake — from 1 to 120

A configuration error — no address, a CA that cannot be read, an interval under its floor, a certificate without its key or a key without its certificate, a dtls check with no port or with versions that leave out TLS 1.2, material that cannot be read, a key the passphrase does not decrypt — stops the device with Configuration error. The message names the property, never its value. A number is read whole: a fraction, an infinity, or one no 32-bit integer holds is refused, never converted.

How a Check Works​

Every check dials a connection of its own: the Director resolves the host, connects, asks the service to start TLS where its protocol begins in the clear, and makes the handshake. Once the handshake is made, it sends no request and does not sign in: it ends the session with a close_notify and closes the connection, so a service that logs a connection dropped without one as an error has none to log at every check.

The Request to Start TLS​

protocolWhat the check doesThe yes it waits for
smtpReads the greeting (220), sends EHLO with the Director's host name, then STARTTLS220
imapReads the greeting (* OK), sends STARTTLSThe tagged OK
pop3Reads the greeting (+OK), sends STLS+OK
ftpReads the greeting (220), sends AUTH TLS234
ldapSends the StartTLS extended requestResult code 0
postgresSends SSLRequestS

A service that refuses the request, answers as another protocol's would, or goes on in the clear after its yes is down with error.type starttls, and the message quotes what it answered: the mail server refused STARTTLS: 502 5.5.1 Command not implemented. What a service may say before its handshake is bounded: a line of 2048 bytes, an answer of 64 lines.

Up and Down​

The check is up when the handshake was made and the certificate verifies, or when tls.insecure_skip_verify is set, and a TLS 1.3 service that asked for a client certificate did not refuse the session after it. Otherwise it is down, and error.type says why:

error.typeWhen
dnsThe address does not resolve
connectionThe connection failed. For dtls, also a host that reported the port unreachable (ICMP port unreachable)
timeoutThe check did not finish within timeout. For dtls, also a handshake no answer came to
starttlsThe service did not take the request to start TLS
certificateThe certificate does not verify
client_certificateThe service refused the check's client certificate, or the lack of one
handshakeThe handshake failed for another reason. For dtls, also a port that answered with what is no DTLS

A handshake that fails after the certificates still writes them. A service that refuses the check's client certificate, or the lack of one, has presented its own first, so the result has its certificate and days left.

Not included: DTLS 1.0 and 1.3, and a TLS 1.3 service's request for a client certificate after the handshake.

DTLS​

protocol: dtls makes the DTLS 1.2 handshake with the service's UDP port, and the result says what a TLS handshake's says, with tls.version_protocol dtls and network.transport udp. Its port is required, and its versions must let TLS 1.2 through.

  • A silent port is down with timeout when the timeout ends: a handshake that gets no answer is what a closed UDP port looks like, and a firewall that drops its datagrams looks the same.
  • A port the host reports closed (ICMP port unreachable) is down with connection at once. Windows reports none, so there it is a timeout.
  • A port that answers with what is no DTLS is down with handshake once the timeout ends.
  • Lost datagrams are sent again after 1, 2, and 4 seconds, within the timeout.

The certificate is verified as over TLS, and a client certificate is presented and refused within the handshake, as under TLS 1.2.

A Client Certificate​

With tls.cert_name and tls.key_name, the check presents the certificate to a service that asks for one, and to no other; without them it presents none. The certificate is read when the device starts, and one in a file again when the file changes.

A service that refuses the certificate, or the lack of one, is down with error.type client_certificate and the device's state is Authentication error, under TLS 1.2 and 1.3. The message ends with the alert the service sent: the service refused the check's client certificate: unknown certificate authority.

Under TLS 1.2 a service refuses the certificate within the handshake; under TLS 1.3 after it. So after a TLS 1.3 handshake whose service asked for a certificate, the check reads once for its verdict:

  • an alert, or a session the service ended unasked, is the session refused: the check is down;
  • a session ticket, or the service speaking first (an SMTPS or IMAPS greeting), is a yes, and the check is up at once;
  • silence through the wait is a service that waits for the client to speak first: the check is up.

The wait is a second, or twice as long as the handshake took when that is longer, within the timeout. Nothing is read after a TLS 1.2 handshake, or a TLS 1.3 one whose service did not ask for a certificate.

Results and State​

Every check writes one result, with event.dataset tls_check and definition id 12155, to the metric table:

  • destination.address, ip, port; network.transport (tcp, or udp for dtls), protocol (the device's protocol).
  • tls.established (false too for a session refused after a TLS 1.3 handshake), version, version_protocol (tls or dtls), cipher; tls.server.x509.* (the service's own certificate, verified or not) and tls.server.hash.sha256 (its fingerprint), as an HTTP Check's.
  • service_check.tls.protocol, server_name, and rtt.dns (the name's lookup), connect (none for dtls), starttls, tls_handshake, total (the parts the check finished).
  • service_check.tls.certificate.verified, certificate.unverified (why not), certificate.days_left, and certificate.chain.length, days_left, position, common_name, sha256, as an HTTP Check's: the certificate of the chain that expires first, and its days left.
  • service_check.tls.client_certificate.requested (true once the service asked for a client certificate; false after a handshake made without its asking; left out when the check ended before it could tell) and client_certificate.presented (whether the check presented tls.cert_name).

A check that failed before any certificate came has no tls and no certificate.

Every result carries the state the service is in, under state.*, and every service check writes the same fields. For the state's fields, how to alert on it, and the fields every record carries, see Results and State.

Connection States​

The device's connection state follows the service checked, and the fleet list shows it:

StateWhen
ConnectedThe service is up
Connection errorIt does not answer, or its name does not resolve
Certificate errorIts certificate does not verify
Authentication errorIt refused the check's client certificate, or required one the device does not name
ErrorIt did not take the request to start TLS, or its handshake failed for another reason than its certificate
Configuration errorA configuration that does not validate

The message says what the check ran into (db01.example.com:5432 is down: connect: connection refused), in words that stay the same while the failure does, so the state moves only when the service's does.

Console​

In the console, go to Fleet Management > Devices > TLS Check and click Add new device. The wizard's steps are:

  1. General settings, as on every device, with the device's pre-processing pipeline.
  2. Check settings: Address, Port, and Protocol — TLS, DTLS (over UDP), SMTP (STARTTLS), IMAP (STARTTLS), POP3 (STLS), FTP (AUTH TLS), LDAP (StartTLS), or PostgreSQL (SSLRequest). The port follows the protocol while it is still the protocol's own: choosing SMTP (STARTTLS) turns 443 into 25. A port you entered stays. DTLS has no port of its own: choosing it empties a port that was the protocol's. A DTLS check with no port is refused, as are versions that leave out TLS 1.2. Then the TLS settings: Skip certificate verification, CA certificate, Server name (Optional), and the minimum and maximum TLS version. The CA certificate stays while verification is skipped, since the result still says by it whether the certificate verifies. Then the Client certificate: Certificate (Optional), Private key (Optional), and Passphrase (Optional), on every protocol; the certificate and key go together. The review shows only whether one is set.
  3. Advanced settings: Interval and Timeout.
  4. Review and create.

There is no Data collection step: a TLS Check has no datasets.

With no Director or cluster at version 2.3.1 or later selected, the wizard shows TLS Check devices are unavailable on directors or clusters below version 2.3.1, and the device cannot be created.

Simulation​

The TLS Check is not simulated. What it writes is what its check finds, with the state the service is in, which one generic sample cannot stand in for.

Examples​

Mail Submission with STARTTLS​

Checking a mail submission port every five minutes over SMTP's STARTTLS. Every result carries the certificate it presents and the certificate of its chain that expires first...

devices:
- id: 512300185
name: mail-submission
type: tls_check
status: true
properties:
address: "mail.example.com"
protocol: smtp
port: 587
timeout: 10
interval: 300

LDAPS with a Private CA​

Checking an LDAPS service, which starts in TLS, against the organization's own CA. The port is the service's, since tls names none of its own but 443...

devices:
- id: 512300186
name: dc01-ldaps
type: tls_check
status: true
properties:
address: "dc01.corp.example.com"
protocol: tls
port: 636
tls:
ca_name: "corp-root-ca.pem"

Database Listener by Address​

Checking a PostgreSQL listener by its address on the protocol's own port, 5432. An address is verified against the addresses the certificate holds, so the name the certificate was issued for goes in server_name...

devices:
- id: 512300187
name: db01-postgres-tls
type: tls_check
status: true
properties:
address: "192.0.2.10"
protocol: postgres
tls:
server_name: "db01.example.com"

Syslog over DTLS with a Client Certificate​

Checking a syslog receiver over DTLS that takes only the senders whose certificate its authority issued, so the check presents the Director's. DTLS has no port of its own, so the port is named. The result's network.transport is udp, its tls.version_protocol dtls...

devices:
- id: 512300188
name: siem-syslog-dtls
type: tls_check
status: true
properties:
address: "siem.example.com"
protocol: dtls
port: 6514
tls:
ca_name: "corp-root-ca.pem"
cert_name: "certs/director.pem"
key_name: "certs/director.key"
passphrase: "${DIRECTOR_KEY_PASS}"