I am trying to get the SSL/TLS certificate for one of our load balancers (Netscaler) using:

openssl s_client -showcerts -connect lb.example.com:443

But it won't show me the certificate:

CONNECTED(00000003)
write:errno=54

Using -servername lb.example.com doesn't help, and our sysadmin told me our load balancers don't use SNI anyway.

Edit: The server is on our intranet and doesn't accept connections from the public internet. This is the output of openssl with -debug:

CONNECTED(00000003)
write to 0x7fec7af0abf0 [0x7fec7b803a00] (130 bytes => 130 (0x82))
0000 - 80 80 01 03 01 00 57 00-00 00 20 00 00 39 00 00   ......W... ..9..
0010 - 38 00 00 35 00 00 16 00-00 13 00 00 0a 07 00 c0   8..5............
0020 - 00 00 33 00 00 32 00 00-2f 00 00 9a 00 00 99 00   ..3..2../.......
0030 - 00 96 03 00 80 00 00 05-00 00 04 01 00 80 00 00   ................
0040 - 15 00 00 12 00 00 09 06-00 40 00 00 14 00 00 11   .........@......
0050 - 00 00 08 00 00 06 04 00-80 00 00 03 02 00 80 00   ................
0060 - 00 ff a6 f7 27 1a a7 18-85 cf b2 03 22 fc 48 3d   ....'.......".H=
0070 - dd a9 2c b7 76 67 62 80-df 85 ed 48 35 c7 d4 87   ..,.vgb....H5...
0080 - 8d d3                                             ..
read from 0x7fec7af0abf0 [0x7fec7b809000] (7 bytes => -1 (0xFFFFFFFFFFFFFFFF))
write:errno=54

And this is the relevant output from curl -v https://lb.example.com/:

$ curl -vI https://lb.exmple.com/
*   Trying 1.2.3.4...
* Connected to lb.exmple.com (10.1.2.3) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_AES_256_CBC_SHA
* Server certificate: lb.example.com
* Server certificate: RapidSSL SHA256 CA - G2
* Server certificate: GeoTrust Primary Certification Authority - G3
> HEAD / HTTP/1.1
> Host: lb.exmple.com
> User-Agent: curl/7.43.0
> Accept: */*
>

Any suggestions as to how I can obtain the certificate using openssl s_client?

  • 2
    You are doing it the proper way. But based on the current information it is impossible to say what goes wrong: might be a firewall blocking the TLS handshake, might be a TLS protocol problem... . It might help if you either provide the (public) URL you are trying to use as target or add the full debug output (option -debug) to your question. – Steffen Ullrich Jul 25 '16 at 18:26
  • As @SteffenUllrich said it could be TLS. See openssl same error - possible solution here. – Zina Jul 25 '16 at 20:23
up vote 16 down vote accepted

After a while I figured it out: this particular load balancer was configured to use only TLSv1.2, which the version of openssl included in OS X (0.9.8) does not understand. I installed a newer version of openssl (>= 1.0.1) using homebrew so this works:

/usr/local/opt/openssl/bin/openssl s_client -showcerts -connect lb.example.com:443

I am trying to get the SSL/TLS certificate for one of our load balancers (Netscaler) using:

 openssl s_client -showcerts -connect lb.example.com:443

If its a modern configuration (some hand waiving on what that means), use:

openssl s_client -connect lb.example.com:443 -tls1 -servername lb.example.com | \
openssl x509 -text -noout

CONNECTED(00000003)
write to 0x7fec7af0abf0 [0x7fec7b803a00] (130 bytes => 130 (0x82))
0000 - 80 80 01 03 01 00 57 00-00 00 20 00 00 39 00 00
...

It looks like there's some extra preamble at byte 0 and 1. At byte 2, there should be a record type. At byte 3 and 4 there should be a version number. Bytes 5 and 6 should be a 16-bit length of the payload.

Here's a working example:

$ openssl s_client -connect www.googl.com:443 -tls1 -servername www.googl.com -debug
CONNECTED(00000005)
write to 0x7f7fe1c1fa30 [0x7f7fe2022000] (132 bytes => 132 (0x84))
0000 - 16 03 01 00 7f 01 00 00-7b 03 01 71 c0 12 35 98
...

From above, the record type is at position 0, and its value is 0x16. 0x16 is the Handshake type. The record layer version are the next two bytes at positions 2 and 3. Their values are 0x03 0x01. The length of the payload is 0x007f.

Also see RFC 5246, The Transport Layer Security (TLS) Protocol Version 1.2, page 18:

6.2.1.  Fragmentation

   The record layer fragments information blocks into TLSPlaintext
   records carrying data in chunks of 2^14 bytes or less.  Client
   message boundaries are not preserved in the record layer (i.e.,
   multiple client messages of the same ContentType MAY be coalesced
   into a single TLSPlaintext record, or a single message MAY be
   fragmented across several records).

      struct {
          uint8 major;
          uint8 minor;
      } ProtocolVersion;

      enum {
          change_cipher_spec(20), alert(21), handshake(22),
          application_data(23), (255)
      } ContentType;

      struct {
          ContentType type;
          ProtocolVersion version;
          uint16 length;
          opaque fragment[TLSPlaintext.length];
      } TLSPlaintext;

Your problem could be the old SSLv2 compatible record type. Or it could be a down level version of OpenSSL from, say 0.9.5 or 0.9.8. Its hard to say, and we probably need more information.

More information would include OS; OpenSSL version; if you attempted to replace the platform's version of OpenSSL with your own version of OpenSSL; if there's a firewall or "web inspect" box or other middleware goodness running; and what the server receives.


Using -servername lb.example.com doesn't help, and our sysadmin told me our load balancers don't use SNI anyway.

This sounds kind of unusual. But its an extension to TLS, so its ignored if its not used (and won't produce a fatal alert).

The rule of thumb in 2016: always use TLS 1.0 or above, and always use SNI.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.