在Python中获取服务器/服务器名称指示

时间:2013-06-19 17:15:45

标签: python curl ssl openssl

我一直在研究一个Python程序,它搜索多个IP地址范围并检查SSL证书/从中读取某些信息,然后将其写入CSV文件。

我现在遇到的麻烦是,我要搜索的一些IP地址可能在同一个IP地址上有多个域名。我一直在寻找尝试为此提出某种解决方案,但似乎没有太多关于在OpenSSL中使用SNI检查IP地址的文档

另外,我遇​​到的另一个问题是我想从证书中获取服务器类型(例如apache,nginx等),但OpenSSL似乎没有提供该信息。另一方面卷曲,我实际上使用curl来确定是否在IP地址上找到证书 - 我只是不知道如何从curl的输出中获取该信息。

如果有人能就我如何实现上面列出的两项功能给出一些意见,我真的很感激

这是我到目前为止的代码(请原谅很长时间的硬编码线程 - 我没有机会清理它):

from subprocess import *
import time
import ssl
import OpenSSL
import threading
import sys
import csv

def main():
    global IP_list
    IP_list = []

    global certInfoHolder
    certInfoHolder = []

    getRanges()


def getRanges():
    print 'Enter a range(ex. From: 192.168.1.0 , To: 192.168.1.10)'
    starting_IP = raw_input('From: ')
    ending_IP = raw_input('To: ')


    ip_ranges = ipRange(starting_IP, ending_IP)
    addMore = raw_input('Do you want to add another IP range?Y/N')
    addmore = addMore.lower()
    if addMore == 'y' or addMore == 'yes':
        getRanges()

    elif addMore == 'n' or addMore =='no':
        print 'Done gathering IP Addresses'
        createdThreads = 0
        threadSplit = len(IP_list) / 10

        #Splitting the work up between the threads
        thread_1_list = IP_list[0:threadSplit]
        thread_2_list = IP_list[threadSplit:(threadSplit*2)]
        thread_3_list = IP_list[(threadSplit*2):(threadSplit*3)]
        thread_4_list = IP_list[(threadSplit*3):(threadSplit*4)]
        thread_5_list = IP_list[(threadSplit*4):(threadSplit*5)]
        thread_6_list = IP_list[(threadSplit*5):(threadSplit*6)]
        thread_7_list = IP_list[(threadSplit*6):(threadSplit*7)]
        thread_8_list = IP_list[(threadSplit*7):(threadSplit*8)]
        thread_9_list = IP_list[(threadSplit*8):(threadSplit*9)]
        thread_10_list = IP_list[(threadSplit*9):(threadSplit*10)]


        print '5 Threads..Splitting the work up to: ' , threadSplit
        for address in range(threadSplit):
            print address
            thread_1 = getCertInfo(thread_1_list[address])
            thread_2 = getCertInfo(thread_2_list[address])
            thread_3 = getCertInfo(thread_3_list[address])
            thread_4 = getCertInfo(thread_4_list[address])
            thread_5 = getCertInfo(thread_5_list[address])
            thread_6 = getCertInfo(thread_6_list[address])
            thread_7 = getCertInfo(thread_7_list[address])
            thread_8 = getCertInfo(thread_8_list[address])
            thread_9 = getCertInfo(thread_9_list[address])
            thread_10 = getCertInfo(thread_10_list[address])
            thread_1.start()
            thread_2.start()
            thread_3.start()
            thread_4.start()
            thread_5.start()
            thread_6.start()
            thread_7.start()
            thread_8.start()
            thread_9.start()
            thread_10.start()
            thread_1.join()
            thread_2.join()
            thread_3.join()
            thread_4.join()
            thread_5.join()
            thread_6.join()
            thread_7.join()
            thread_8.join()
            thread_9.join()
            thread_10.join()
            if address == threadSplit-1:
                for address in range(threadSplit,len(thread_5_list)):
                     thread_10 = getCertInfo(thread_10_list[address])
                     thread_10.start()
                     thread_10.join()

        c = csv.writer(open("AInfo.csv", "a"))
        CIH = certInfoHolder

        for info in CIH:
            c.writerow([info[0], info[1], info[2], info[3], info[4]])

        print 'DONE'



def ipRange(start_ip, end_ip):
    start = list(map(int, start_ip.split(".")))
    end = list(map(int, end_ip.split(".")))
    temp = start

    IP_list.append(start_ip)
    while temp != end:
        start[3] += 1
        for i in (3, 2, 1):
            if temp[i] == 256:
                temp[i] = 0
                temp[i-1] += 1        
        IP = ".".join(map(str, temp))
        IP_list.append(IP)
    print 'IP_List size', len(IP_list)


class getCertInfo(threading.Thread):
     def __init__(self,IP):
         threading.Thread.__init__(self)
         self.IP_check=IP

     def run(self):
        try:
            #Using curl to check for a timeout
            self.getCert = check_output('curl --max-time 2 '+self.IP_check,
            stderr=STDOUT,
            shell=True)
            #OpenSSL get server certificate
            self.server_certificate = ssl.get_server_certificate((self.IP_check, 443))
            self.x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, self.server_certificate)

            #Formatting expiration date and time
            self.eDateT = str(self.x509.get_notAfter())
            #173.252.110.27
            self.certInfo = self.x509.get_subject()
            self.commonName = self.certInfo.commonName
            self.companyName = self.certInfo.O
            self.serialNumber = self.x509.get_serial_number()
            self.x  = [str(self.IP_check),str(self.companyName),str(self.eDateT),
                       str(self.commonName),str(self.serialNumber)]
            certInfoHolder.append(self.x)

        except CalledProcessError as detail:
            print str(detail) + '   ' + self.IP_check +'\n'
            pass

1 个答案:

答案 0 :(得分:1)

<强> SNI

如果我理解正确,你应该可以使用Python 3.x系列,3.2+。

如果您遇到Python 2,请查看python-requests对两个可选依赖项ndg-httpsclientpyasn1执行的操作。

我的理解是,由于开发人员对SNI is somehow a feature of Python

的看法感到困惑,你无法用普通的Python&lt; = 2.7.8做很多事情。

修改

感谢PEP466,Python 2.7.9包含从Python 3.4反向移植的ssl模块,并且您拥有所有OpenSSL功能。

其他项目

也许sslyze (github)可以做你想做的事情吗?