My first thought was to use something like openssl s_client
but this only supports TCP not UDP and it seems there requires some special magic to get TLS over UDP working, how do I interface with that and get a dump of the certficate chain presented? (I specifically need the certificates, not information about them)

- 373
- 1
- 2
- 15
-
1\*facepalm*, there is a `-dtls1` flag I failed to notice. Not posting this as an answer since I still haven't figured out the dump-to-file part. – Shelvacu Jul 26 '15 at 09:33
3 Answers
Building on the mostly complete solution in this thread by Peter Šurda (see there for some explanation regarding the used openvpn
options), this should do the work to get the server certificates.
I assume you have a working OVPN configuration file in config.ovpn
and that you are authenticating the client with a username and a password (this can be omitted, depending on your setup).
Prepare working directory:
WD=/tmp/openvpn-cert
mkdir $WD
Prepare the script to extract the server certificates and some fake credentials file (we don't need to get past successful authentication):
echo -e '#!'"/bin/sh\ncp \$peer_cert $WD/server-cert-\$1.pem" >$WD/extract-cert.sh
chmod +x $WD/extract-cert.sh
echo -e "fakeusername\nfakepassword" >$WD/creds.dat
Try to connect with openvpn
:
openvpn --config config.ovpn --auth-user-pass $WD/creds.dat --tls-export-cert $WD \
--script-security 2 --tls-verify $WD/extract-cert.sh --log /dev/null
Now you should have the server certificate available in $WD/server-cert-0.pem
and can operate on it, e.g. get the notBefore and notAfter dates:
openssl x509 -in $WD/server-cert-0.pem -noout -dates
The other certificates in the chain will be available in $WD/server-cert-1.pem
etc. The number comes from the first argument passed to extract-cert.sh
, which is the certificate depth. See the --tls-verify
documentation in the Script Hooks section of the man page.

- 96
- 1
- 5
-
1For monitoring the OpenVPN server certificate expiration, instead of using `openssl` to get the expiration date you could use the following Nagios plugin https://github.com/matteocorti/check_ssl_cert with a command like `check_ssl_cert -H localhost -f /etc/openvpn/server/server.crt -w 15 -c 7`. – Jaime Hablutzel Dec 12 '20 at 17:59
-
2This doesn't seem to work if the certificate chain isn't actually accepted by OpenVPN (for example if you don't have the right CA cert for a server and you aren't sure which CA you actually need), because the script doesn't get run if the certificate fails other checks. – interfect Mar 20 '22 at 15:59
I happen to be running an OpenVPN server in TCP mode, and I can confirm that you cannot use openssl s_client
to get the certificate:
[me@risby 17]$ openssl s_client -connect openvpn.example.com:1194
CONNECTED(00000003)
140413456672632:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:184:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 205 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---
I can only presume that although OpenVPN uses SSL, it does so in a different way from a standard SSL/TLS connection. So I don't think this is the way to go.
I'd hoped to find an openvpn
client invocation that would dump the certficates, but thus far have not. I'm sorry not to have more for you, but I thought it worth writing an answer that might prevent you from wasting time.

- 79,770
- 20
- 184
- 232
-
See my comment on the original post; Openvpn uses DTLS for TLS over UDP. I was able to connect to (but not dump from) an openvpn server I was running. – Shelvacu Jul 26 '15 at 18:21
-
Having just tried it, I can't agree: it merely prints "`CONNECTED(00000003)`" (which is meaningless in a UDP context). `tcpdump` confirms that this message appears as soon as the first UDP packet is *sent* to the server - and no reply is received. I reiterate my view that `openssl s_client` can't help you. – MadHatter Jul 26 '15 at 19:09
I was facing the same problem and it can be resolved by using openvpn with particular arguments. The important ones are --tls-verify
and --tls-export-cert
. --tls-verify
needs to be followed by filename of a script you want to execute. The environment variable peer_cert
will contain a location of the dumped certificate chain. The --tls-export-cert
needs to be followed by a directory name where the certificate will be dumped. The certificate is auto-deleted once the tls-verify script finishes.
The only problem I found was that it requires you to already have the CA certificate. If you don't have it, the script won't execute and I haven't found a way to work around it.
Example in use:
openvpn --remote remote.host.to.check 1194 --dev tun --proto udp --ca tmp/openvpnca.cert --client --auth-user-pass tmp/noauth.txt --remote-cert-tls server --tls-verify tmp/tls-verify.sh --script-security 2 --tls-export-cert tmp/tlsverifies
tmp/noauth.txt
is a dummy file with two lines containing a fake username/password.
tmp/tlsverifies
is a directory where the chain file will be dumped.
tmp/tls-verify.sh
is a shell script that processes the peer_cert
environment variable

- 31
- 1
-
1
-
Also, all of your `tmp` directory references should be prefixed with `/`, and you need to `chmod 600 /tmp/noauth.txt` – Reinderien Aug 07 '19 at 14:43
-
-
@Reinderien `tls-verify.sh` should accept an environment variable `peer_cert` (which will contain the peer certificate) and process it. At least that's what I think based on the my original answer. I'm moving from openvpn to wireguard so I'm not spending time on this anymore. – Peter Šurda Jul 20 '21 at 13:03