একাধিক রিমোট সার্ভারের জন্য এসএসএল শংসাপত্রের মেয়াদ শেষের তারিখটি পরীক্ষা করুন


18

আমি এই ওপেনএসএসএল কমান্ডটি ব্যবহার করে এসএসএল শংসাপত্রগুলির মেয়াদ শেষ হওয়ার তারিখটি জানতে পারি:

openssl x509 -noout -in <filename> -enddate

তবে যদি শংসাপত্রগুলি বিভিন্ন ওয়েব সার্ভারগুলিতে ছড়িয়ে যায় তবে আপনি সমস্ত সার্ভারে এই সমস্ত শংসাপত্রের মেয়াদ শেষ হওয়ার তারিখটি কীভাবে খুঁজে পাবেন?

অন্য হোস্টের সাথে সংযোগ করার একটি উপায় রয়েছে বলে মনে হচ্ছে তবে এটি ব্যবহার করে কীভাবে মেয়াদ শেষ হবে তা নিশ্চিত নই:

openssl s_client -connect host:port

উত্তর:


15

আমার একই সমস্যা ছিল এবং এটি লিখেছিলাম ... এটি দ্রুত এবং নোংরা, তবে কাজ করা উচিত। এটি যে কোনও শংসাপত্রগুলি এখনও বৈধ নয় বা পরবর্তী 90 দিনের মধ্যে মেয়াদোত্তীর্ণ নয় এমন কোনও শংসাপত্রগুলি লগইন করবে (এবং ডিবাগিং দিয়ে স্ক্রিনে মুদ্রণ করবে)'ll কিছু বাগ থাকতে পারে তবে এটিকে পরিষ্কার করে নির্বিঘ্নে বোধ করতে পারেন।

#!/bin/sh

DEBUG=false
warning_days=90 # Number of days to warn about soon-to-expire certs
certs_to_check='serverA.test.co.uk:443
serverB.test.co.uk:8140
serverC.test.co.uk:443'

for CERT in $certs_to_check
do
  $DEBUG && echo "Checking cert: [$CERT]"

  output=$(echo | openssl s_client -connect ${CERT} 2>/dev/null |\
  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' |\
  openssl x509 -noout -subject -dates 2>/dev/null) 

  if [ "$?" -ne 0 ]; then
    $DEBUG && echo "Error connecting to host for cert [$CERT]"
    logger -p local6.warn "Error connecting to host for cert [$CERT]"
    continue
  fi

  start_date=$(echo $output | sed 's/.*notBefore=\(.*\).*not.*/\1/g')
  end_date=$(echo $output | sed 's/.*notAfter=\(.*\)$/\1/g')

  start_epoch=$(date +%s -d "$start_date")
  end_epoch=$(date +%s -d "$end_date")

  epoch_now=$(date +%s)

  if [ "$start_epoch" -gt "$epoch_now" ]; then
    $DEBUG && echo "Certificate for [$CERT] is not yet valid"
    logger -p local6.warn "Certificate for $CERT is not yet valid"
  fi

  seconds_to_expire=$(($end_epoch - $epoch_now))
  days_to_expire=$(($seconds_to_expire / 86400))

  $DEBUG && echo "Days to expiry: ($days_to_expire)"

  warning_seconds=$((86400 * $warning_days))

  if [ "$seconds_to_expire" -lt "$warning_seconds" ]; then
    $DEBUG && echo "Cert [$CERT] is soon to expire ($seconds_to_expire seconds)"
    logger -p local6.warn "cert [$CERT] is soon to expire ($seconds_to_expire seconds)"
  fi
done

যদি ওএস এক্স ব্যবহার করে, আপনি দেখতে পাবেন যে dateকমান্ডটি সঠিকভাবে কাজ করে না। এটি এই ইউটিলিটির ইউনিক্স এবং লিনাক্স সংস্করণে পার্থক্যের কারণে । লিঙ্কযুক্ত পোস্টে এই কাজটি করার জন্য বিকল্প রয়েছে।


মেল সার্ভার শংসাপত্রগুলি যাচাই করতে পাশাপাশি সমস্ত শংসাপত্রগুলির স্থিতি সম্পর্কে একটি সুন্দর লিটল ভিউ দেওয়া যেতে সক্ষম করতে আমি আপনার স্ক্রিপ্টটি কিছুটা সংশোধন / প্রসারিত করেছি। আপনি পরিবর্তিত স্ক্রিপ্টটি এখানে পাবেন: gist.github.com/lkiesow/c9c5d96ecb71822b82cd9d194c581cc8
লার্স কিসো

1
সার্ভার sni ব্যবহার করছে, তাহলে আপনি অন্তর্ভুক্ত করতে হবে -servername, যুক্তি ভালো:openssl s_client -servername example.com -connect example.com:443
Flimm

11

কেবল নীচের কমান্ডটি চালান এবং এটি সমাপ্তির তারিখ সরবরাহ করবে:

echo q | openssl s_client -connect google.com.br:443 | openssl x509 -noout -enddate

আপনি এই কমান্ডটি ব্যাচ ফাইলে ব্যবহার করতে পারেন, আরও দূরবর্তী সার্ভারগুলির জন্য এই তথ্যটি সংগ্রহ করতে।


2
আপনি যেভাবে এই লিখেছেন, এটি শেষ করতে আপনাকে CTRL-C টি চাপতে হবে। আপনি এটির মাধ্যমে এটি ঠিক করতে পারেন: openssl s_client- সংযুক্ত google.com.br:443 </ dev / null 2> & 1 | ওপেনএসএল x509 -আউট -েন্ডেটেট কেবল একটি চিন্তাভাবনা।
সংখ্যা

1
সার্ভার sni ব্যবহার করেন, তাহলে আপনি ব্যবহার করতে হবে -servernameভালো, যুক্তি:openssl s_client -servername google.com.br -connect google.com.br:443
Flimm

6

নীচে আমার স্ক্রিপ্ট যা নগিওসের মধ্যে একটি চেক হিসাবে। এটি একটি নির্দিষ্ট হোস্টের সাথে সংযুক্ত হয়, এটি শংসাপত্রটি -c / -w বিকল্পগুলির দ্বারা সেট করা একটি প্রান্তিকের মধ্যে বৈধ কিনা তা যাচাই করে। এটি যাচাই করতে পারে যে শংসাপত্রের সিএন আপনার প্রত্যাশিত নামের সাথে মেলে।

আপনার পাইথন ওপেনসেল লাইব্রেরি দরকার এবং আমি পাইথন ২.7 দিয়ে সমস্ত পরীক্ষা করেছি।

শেল স্ক্রিপ্টটি একাধিকবার কল করা তুচ্ছ হবে। স্ক্রিপ্টটি সমালোচনামূলক / সতর্কতা / ওকে স্থিতির জন্য মানক নাগিও থেকে বেরিয়ে আসা মানগুলি দেয়।

গুগলের শংসাপত্রের একটি সাধারণ চেক এইভাবে সম্পাদন করা যেতে পারে।

./check_ssl_certificate -H www.google.com -p 443 -n www.google.com

Expire OK[108d] - CN OK - cn:www.google.com

check_ssl_certificate

#!/usr/bin/python

"""
Usage: check_ssl_certificate -H <host> -p <port> [-m <method>] 
                      [-c <days>] [-w <days>]
  -h show the help
  -H <HOST>    host/ip to check
  -p <port>    port number
  -m <method>  (SSLv2|SSLv3|SSLv23|TLSv1) defaults to SSLv23
  -c <days>    day threshold for critical
  -w <days>    day threshold for warning
  -n name      Check CN value is valid
"""

import getopt,sys
import __main__
from OpenSSL import SSL
import socket
import datetime

# On debian Based systems requires python-openssl

def get_options():
  "get options"

  options={'host':'',
           'port':'',
           'method':'SSLv23',
           'critical':5,
           'warning':15,
           'cn':''}

  try:
    opts, args = getopt.getopt(sys.argv[1:], "hH:p:m:c:w:n:", ['help', "host", 'port', 'method'])
  except getopt.GetoptError as err:
    # print help information and exit:
    print str(err) # will print something like "option -a not recognized"
    usage()
    sys.exit(2)
  for o, a in opts:
    if o in ("-h", "--help"):
      print __main__.__doc__
      sys.exit()
    elif o in ("-H", "--host"):
      options['host'] = a
      pass
    elif o in ("-p", "--port"):
      options['port'] = a
    elif o in ("-m", "--method"):
      options['method'] = a
    elif o == '-c':
      options['critical'] = int(a)
    elif o == '-w':
      options['warning'] = int(a)
    elif o == '-n':
      options['cn'] = a
    else:
      assert False, "unhandled option"

  if (''==options['host'] or 
      ''==options['port']):
    print __main__.__doc__
    sys.exit()

  if options['critical'] >= options['warning']:
    print "Critical must be smaller then warning"
    print __main__.__doc__
    sys.exit()

  return options

def main():
  options = get_options()

  # Initialize context
  if options['method']=='SSLv3':
    ctx = SSL.Context(SSL.SSLv3_METHOD)
  elif options['method']=='SSLv2':
    ctx = SSL.Context(SSL.SSLv2_METHOD)
  elif options['method']=='SSLv23':
    ctx = SSL.Context(SSL.SSLv23_METHOD)
  else:
    ctx = SSL.Context(SSL.TLSv1_METHOD)

  # Set up client
  sock = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
  sock.connect((options['host'], int(options['port'])))
  # Send an EOF
  try:
    sock.send("\x04")
    sock.shutdown()
    peer_cert=sock.get_peer_certificate()
    sock.close()
  except SSL.Error,e:
    print e

  exit_status=0
  exit_message=[]

  cur_date = datetime.datetime.utcnow()
  cert_nbefore = datetime.datetime.strptime(peer_cert.get_notBefore(),'%Y%m%d%H%M%SZ')
  cert_nafter = datetime.datetime.strptime(peer_cert.get_notAfter(),'%Y%m%d%H%M%SZ')

  expire_days = int((cert_nafter - cur_date).days)

  if cert_nbefore > cur_date:
    if exit_status < 2: 
      exit_status = 2
    exit_message.append('C: cert is not valid')
  elif expire_days < 0:
    if exit_status < 2: 
      exit_status = 2
    exit_message.append('Expire critical (expired)')
  elif options['critical'] > expire_days:
    if exit_status < 2: 
      exit_status = 2
    exit_message.append('Expire critical')
  elif options['warning'] > expire_days:
    if exit_status < 1: 
      exit_status = 1
    exit_message.append('Expire warning')
  else:
    exit_message.append('Expire OK')

  exit_message.append('['+str(expire_days)+'d]')

  for part in peer_cert.get_subject().get_components():
    if part[0]=='CN':
      cert_cn=part[1]

  if options['cn']!='' and options['cn'].lower()!=cert_cn.lower():
    if exit_status < 2:
      exit_status = 2
    exit_message.append(' - CN mismatch')
  else:
    exit_message.append(' - CN OK')

  exit_message.append(' - cn:'+cert_cn)

  print ''.join(exit_message)
  sys.exit(exit_status)

if __name__ == "__main__":
  main()

2

get_pem

হোস্টের সাথে সংযোগ করুন: বন্দরে, সেড সহ শংসাপত্রটি বের করুন এবং এটি /tmp/host.port.pem এ লিখুন।

get_expiration_date

প্রদত্ত পেম ফাইলটি পড়ুন এবং ব্যাশ ভেরিয়েবল হিসাবে নোটএফটার কীটি মূল্যায়ন করুন। তারপরে ফাইলের নাম এবং তারিখটি যখন কোনও প্রদত্ত লোকালে শেষ হয় তখন মুদ্রণ করুন।

get_pem_expiration_dates

কিছু ইনপুট ফাইল ইটারেট করুন এবং উপরের কাজগুলি চালান।

check.pems.sh

#!/bin/bash
get_pem () {
    openssl s_client -connect $1:$2 < /dev/null |& \
    sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/w'/tmp/$1.$2.pem
}
get_expiration_date () {
    local pemfile=$1 notAfter
    if [ -s $pemfile ]; then
        eval `
          openssl x509 -noout -enddate -in /tmp/$pemfile |
          sed -E 's/=(.*)/="\1"/'
        `
        printf "%40s: " $pemfile
        LC_ALL=ru_RU.utf-8 date -d "$notAfter" +%c
    else
        printf "%40s: %s\n" $pemfile '???'
    fi
}

get_pem_expiration_dates () {
    local pemfile server port
    while read host; do
        pemfile=${host/ /.}.pem
        server=${host% *}
        port=${host#* }
        if [ ! -f /tmp/$pemfile ]; then get_pem $server $port; fi
        if [   -f /tmp/$pemfile ]; then get_expiration_date $pemfile; fi
    done < ${1:-input.txt}
}

if [ -f "$1" ]; then
    get_pem_expiration_dates "$1" ; fi

নমুনা আউটপুট

 $ sh check.pems.sh input.txt
             www.google.com.443.pem: Пн. 30 дек. 2013 01:00:00
              superuser.com.443.pem: Чт. 13 марта 2014 13:00:00
               slashdot.org.443.pem: Сб. 24 мая 2014 00:49:50
          movielens.umn.edu.443.pem: ???
 $ cat input.txt
 www.google.com 443
 superuser.com 443
 slashdot.org 443
 movielens.umn.edu 443

এবং আপনার প্রশ্নের উত্তর দিতে:

$ openssl s_client -connect www.google.com:443 </dev/null |& \
sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' | \
openssl x509 -noout -enddate |& \
grep ^notAfter

সার্ভার sni ব্যবহার করছে, তাহলে আপনি অন্তর্ভুক্ত করতে হবে -servername, যুক্তি ভালো:openssl s_client -servername example.com -connect example.com:443
Flimm

1

এখানে গৃহীত উত্তরের একটি ওয়ান-লাইন সংস্করণ রয়েছে, যা কেবলমাত্র বাকি দিনগুলিকে ছাড়িয়ে যায়:

( export DOMAIN=example.com; echo $(( ( $(date +%s -d "$( echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | openssl x509 -noout -enddate | sed 's/.*notAfter=\(.*\)$/\1/g' )" ) - $(date +%s) ) / 86400 )) )

Www.github.com সহ উদাহরণ:

$ ( export DOMAIN=www.github.com; echo $(( ( $(date +%s -d "$( echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | openssl x509 -noout -enddate | sed 's/.*notAfter=\(.*\)$/\1/g' )" ) - $(date +%s) ) / 86400 )) )
210

আমি অপ্রত্যাশিত টোকেন `রফতানির কাছে সিনট্যাক্স ত্রুটি
পেয়েছি

@ ব্যবহারকারী 1130176 সাব-শিট ( ... )সিনট্যাক্সটি ব্যাশের জন্য নির্দিষ্ট হতে পারে; আমার ধারণা আপনি আলাদা শেল ব্যবহার করছেন?
ম্যাথিউ রে

0

ফাইলটিতে হোস্টনাম: পোর্ট ফর্ম্যাটে 443 পোর্ট সহ হোস্টনামের তালিকা দিন এবং এটি ফাইলের নাম হিসাবে দিন।

! / বিন / ব্যাশ

ফাইলের নাম = / রুট / kns / শংশাপত্র

তারিখ 1 = $ (তারিখ | কাট-ডি "" -f2,3,6)

বর্তমান তারিখ = $ (তারিখ -d "$ তারিখ 1" + "% Y% m% d")

পড়ার সময় লাইন না

dcert = $ (প্রতিধ্বনি

প্রতিধ্বনি হোস্টনাম: $ লাইন শেষ তারিখ = $ (তারিখ -d "$ ডসার্ট" + "% ওয়াই% এম% ডি")

d1 = $ (তারিখ -d "$ শেষ তারিখ" +% s) d2 = $ (তারিখ -d "$ বর্তমান তারিখ" +% s) হোস্টনাম: $ লাইন - দিন বাকি রয়েছে $ (((ডি 1 - ডি 2) / 86400))

প্রতিধ্বনি $ dcert <"name ফাইলের নাম"

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.