2011-10-07 10 views
25

Potrzebuję zeskanować listę adresów IP i pobrać nazwę pospolitą z certyfikatu na tym IP (dla każdego IP, który pozwala na połączenia portu 443). Udało mi się to zrobić z użyciem gniazd i modułów ssl. Działa dla wszystkich adresów IP z ważnymi, podpisanymi certyfikatami, ale nie działa dla certyfikatów z podpisem własnym.Jak mogę pobrać certyfikat równorzędny TLS/SSL zdalnego hosta przy użyciu Pythona?

Gdybym użyć tej metody, wymaga ważnego cert, który jest potwierdzony przez moją CA-wiązki:

from socket import socket 
import ssl 

s = socket() 
c = ssl.wrap_socket(s,cert_reqs=ssl.CERT_REQUIRED, ca_certs='ca-bundle.crt') 
c.connect(('127.0.0.1', 443)) 

print c.getpeercert() 

Jeśli usunąć cert_reqs=ssl.CERT_REQUIRED następnie łączy, ale nie dostać certyfikat w ogóle.

Jak mogę odzyskać nazwę pospolitą dla certyfikatu na IP, czy sprawdza się przed pakietem ca, czy nie?

Odpowiedz

37

Biblioteka Pythona ssl wygląda na to, że analizuje tylko dla ciebie certyfikat, jeśli ma prawidłowy podpis.

"""Returns a formatted version of the data in the 
    certificate provided by the other end of the SSL channel. 
    Return None if no certificate was provided, {} if a 
    certificate was provided, but not validated.""" 

Nadal można uzyskać certyfikat serwera z funkcją ssl.get_server_certificate(), ale zwraca go w formacie PEM. (Alternatywnie, można nazwać c.getpeercert(True), która zwraca cert w formacie binarnym DER, czy to potwierdzone, czy nie.)

>>> print ssl.get_server_certificate(('server.test.com', 443)) 
-----BEGIN CERTIFICATE----- 
MIID4zCCAsugAwIBA..... 

Stąd użyłbym M2Crypto lub OpenSSL do zapoznania się z cert i uzyskać wartości:

# M2Crypto 
cert = ssl.get_server_certificate(('www.google.com', 443)) 
x509 = M2Crypto.X509.load_cert_string(cert) 
x509.get_subject().as_text() 
# 'C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com' 

# OpenSSL 
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) 
x509.get_subject().get_components() 
#[('C', 'US'), 
# ('ST', 'California'), 
# ('L', 'Mountain View'), 
# ('O', 'Google Inc'), 
# ('CN', 'www.google.com')] 
+1

Warto również zauważyć, że jeśli wyodrębnisz certyfikat za pośrednictwem ssl.getpeercert (True), musisz załadować go za pomocą OpenSSL.crypto.FILETYPE_ASN1 zamiast FILETYPE_PEM –

+3

Od czasu usterki "Poodle" w SSLv3 wiele serwerów internetowych ją wyłączyło. Może być konieczne dodanie 'ssl_version = ssl.PROTOCOL_TLSv1' do twojego wywołania' get_server_certificate (..) ', jeśli zobaczysz coś takiego jak" niepowodzenie uśpienia alertu sslv3 " –

+0

Wywołanie M2Crypto SocketServer, które zmieni się na socketserver pod python3. M2Crypto zostanie złamane w python3. – mootmoot

4

W systemie Mac należy zainstalować łyk i M2Crypto

na zacisku rUN:

brew install swig 

A potem:

sudo pip install m2crypto 

Następnie można uruchomić kod powyżej:

from socket import socket 
import ssl 
import M2Crypto 
import OpenSSL 

# M2Crypto 
cert = ssl.get_server_certificate(('www.google.com', 443)) 
x509 = M2Crypto.X509.load_cert_string(cert) 
print x509.get_subject().as_text() 
# 'C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com' 

# OpenSSL 
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) 
print x509.get_subject().get_components() 
#[('C', 'US'), 
# ('ST', 'California'), 
# ('L', 'Mountain View'), 
# ('O', 'Google Inc'), 
# ('CN', 'www.google.com')] 
Powiązane problemy