2013-06-19 435 views
1

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

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

另外,我遇​​到的另一个问题是我想从证书中获取服务器类型(例如,apache,nginx等),但是OpenSSL似乎没有提供该信息。另一方面,Curl确实使用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 
+0

['subprocess.check_output()'](http://docs.python.org/2/library/subprocess.html#subprocess.check_output)将允许您更容易地刮擦curl调用的结果。 – Droogans

+0

['socket.gethostbyaddr()'](http://stackoverflow.com/a/2575779/881224)*可能*是你正在寻找与DNS查找。 – Droogans

回答

1

SNI

你应该能够与Python 3.x系列到那里,3.2+如果我理解正确。

如果您遇到了Python 2,请查看python请求对两个可选依赖关系ndg-httpsclientpyasn1的处理方式。

我的理解是,你真的不能做与普通的Python < = 2.7.8由于开发者令人困惑的观点,即SNI is somehow a feature of Python

编辑

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

其他项目

也许sslyze (github)可以做你想做什么已经?