I wrote this bit of code to get the Common Name of the subject field in the SSL certificate for a given domain:

$ echo -e "GET / HTTP/1.1\nEOT" | \
   openssl s_client -connect google.com:443 2>&1 | \
   grep subject
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com

However, this only gives me the “subject” value. Alternative CNs may be listed in the “Subject Alternative Name” field. For example:

So, how can I get the value of the Subject Alternative Name field in Bash?


This might not work under every circumstance, but try

openssl s_client -connect google.com:443 2>&1 | openssl x509 -text | grep DNS
  • 1
    Thanks so much! openssl x509 -text is what I was looking for. I guess I was Googling for the wrong keywords. – Mathias Bynens Mar 7 '13 at 14:28

What @stuart-p-bentley wrote got me thinking and I came up with this way of getting a comma delimited list of "Subject Alternative Names" using openssl, awk and tr. The sed line in his answer does not work on FreeBSD per example.

openssl s_client -connect google.com:443 2>&1 | openssl x509 -text | awk '/X509v3 Subject Alternative Name/ {getline;gsub(/ /, "", $0); print}' | tr -d "DNS:"

Here is what you get with google.com

  • tr -d "DNS:" is not a good solution to get all the domains in the SAN, as the SAN field may contain other kinds of values than DNS, such as IP addresses. I don't know how you'd do it with awk, but sed -nr '/^ {12}X509v3 Subject Alternative Name/{n; s/(^|,) *DNS:/,/g; s/(^|,) [^,]*//gp}' is how I did it with sed here. – Stuart P. Bentley Oct 15 '14 at 6:25
  • The equivalent awk translation would probably be awk '/^ {12}X509v3 Subject Alternative Name/ {getline; gsub(/(^|,) *DNS:/, ",", $0); gsub(/(^|,) [^,]*/, "", $0); print}', though I don't know why that would be any better than using sed (I can't see why the sed wouldn't work on FreeBSD, unless you need to use -nE instead of -nr due to being on an old version). – Stuart P. Bentley Oct 15 '14 at 6:37
  • Another reason tr -d "DNS:" is not a good solution is because tr -d deletes sets of characters, not strings. You might as well do tr -d ":A-Z". (While you're at it, throw out the gsub(/ /, "", $0); and add spaces to the set for deletion. Or just do all your deletion in the awk command in the first place, where you can do it with strings and patterns - at which point you reach my previous comment's code.) – Stuart P. Bentley Jun 1 '15 at 9:12
  • (The code referenced at the end of my first comment has moved to github.com/plushu/plushu-app-nginx-servers/blob/master/hooks/… .) – Stuart P. Bentley Jun 1 '15 at 9:14

Here's a version that will work in every circumstance (and strips leading space):

openssl s_client -connect google.com:443 2>&1 | openssl x509 -text |
  sed -nr '/^ {12}X509v3 Subject Alternative Name/{n;s/^ *//p}'
  • Can you be more specific about what kind of issues this works around (that the other answer doesn’t)? Thanks! – Mathias Bynens Aug 8 '14 at 13:44
  • 1
    Unlike the other answer, this doesn't inadvertently include other fields that contain "DNS" (such as what you could encounter running the other answer for the certificate of a service that provides DNS). – Stuart P. Bentley Aug 8 '14 at 21:20

Also use the switch

-certopt no_pubkey,no_sigdump,no_validity,no_serial,no_header,no_issuer,no_version,no_aux,no_signame,no_subject

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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