Weil es mir grad passiert ist, möchte ich hier kurz zu de Thema python und Zertifikate einen kleinen Artikel schreiben.
Seit geraumer Zeit habe ich auf meiner Firewall bemerkt, dass keine IP-Adressen mehr über server2pf in das Alias zum Blockieren von neugierigen Benutzern auf meinem Server eingetragen werden.
Das ist mir merkwürdig vorgekommen. Zunächst hatte ich opnsense in Verdacht, dass sich etwas an der API geändert hat, aber das war nicht der Fall.
Schließlich habe ich mir eine Test-IP-Adresse geholt und mit dieser Tests durchgeführt und schau an, mein Zertifikat war abgelaufen. Aber warum ein Zertifikat, wenn man die API nutzen möchte.
Nun gut, ich möchte halt die Verbindungen zu Firewall verschlüsselt aufbauen. Da ich aber auf der opnsense ein selbst-signiertes Zertifikat hatte und dieses vor 2 Wochen abgelaufen ist, gibt es halt hier eine Fehlermeldung:
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 715, in urlopen
httplib_response = self._make_request(
File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 404, in _make_request
self._validate_conn(conn)
File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 1058, in _validate_conn
conn.connect()
File "/usr/local/lib/python3.9/site-packages/urllib3/connection.py", line 419, in connect
self.sock = ssl_wrap_socket(
File "/usr/local/lib/python3.9/site-packages/urllib3/util/ssl_.py", line 453, in ssl_wrap_socket
ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls)
File "/usr/local/lib/python3.9/site-packages/urllib3/util/ssl_.py", line 495, in _ssl_wrap_socket_impl
return ssl_context.wrap_socket(sock)
File "/usr/local/lib/python3.9/ssl.py", line 501, in wrap_socket
return self.sslsocket_class._create(
File "/usr/local/lib/python3.9/ssl.py", line 1074, in _create
self.do_handshake()
File "/usr/local/lib/python3.9/ssl.py", line 1343, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1134)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/requests/adapters.py", line 486, in send
resp = conn.urlopen(
File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 799, in urlopen
retries = retries.increment(
File "/usr/local/lib/python3.9/site-packages/urllib3/util/retry.py", line 592, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='192.168.88.1', port=443): Max retries exceeded with url: /api/firewall/alias_util/list/server2pf (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1134)')))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/root/bin/server2pf.py", line 157, in <module>
main()
File "/root/bin/server2pf.py", line 151, in main
server2pf.get_tablelist() # Es wird das Alias/Table geladen.
File "/root/bin/server2pf.py", line 85, in get_tablelist
self.request = requests.post(url=self.url,
File "/usr/local/lib/python3.9/site-packages/requests/api.py", line 115, in post
return request("post", url, data=data, json=json, **kwargs)
File "/usr/local/lib/python3.9/site-packages/requests/api.py", line 59, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/local/lib/python3.9/site-packages/requests/sessions.py", line 589, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python3.9/site-packages/requests/sessions.py", line 703, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python3.9/site-packages/requests/adapters.py", line 517, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='192.168.88.1', port=443): Max retries exceeded with url: /api/firewall/alias_util/list/server2pf (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1134)'))
Das ist sehr unschön und weil das ganze schon etwas her ist, dass ich das ganze aufgebaut habe, war natürlich guter Rat teuer.
So habe ich im Internet diverse Anleitungen zu dem Thema „python request https self-signed certificate“ gesucht, aber was alle Anleitungen als Fehler hatten, sie waren unvollständig, weil, und hier kommt der Punkt, Sie haben beschrieben, wie man erfolgreich eine Verbindung aufbaut, manche haben auch das Thema verify beschrieben, aber bei den selbst-signierten Zertifikaten gingen keine Anleitungen mehr.
Also habe ich versucht das Zertifikat selber aus dem Kopf in das passende Format zu konvertieren, aber das war auch ohne Erfolg. Ich schaffe es nicht die Zertifikatskette korrekt aufzubauen. Mist, jetzt war guter Rat echt teuer, weil der Schutzebene auf Webserver-Dienst Ebene nicht mehr vorhanden war.
Ich habe mir dann im Browser das Zertifikate geöffnet und da ist mir dann eine Idee gekommen.
Der Browser nutzt ja auch das Zertifikat. Also im Browser mit einem Klick auf das Schloss
- das Popup öffnen
- dort auf „Verbindung ist nicht sicher“ klicken
- und dann unten auch „Weitere Informationen“ klicken
Es öffnet sich ein Fenster mit den Seiteninformationen
In diesem Fenster klickt man auf den Button „Zertifikat anzeigen“ und es öffnet sich ein neues Tab im Browser. Wie der aufmerksame Leser wahrscheinlich bereits erkannt hat, verwendet ich den Firefox Browser. Bei anderen Browser, sollte man dies entsprechend anders machen. 🙂
Auf dieser Seite gibt es sehr viele, nützliche Informationen. Die wichtigste befindet sich im Abschnitt „Verschiedenes“, denn dort kann man das Zertifikat und die gesamte Zertifikatskette herunter speichern.
Und genau diese Zertifikatskette ist das, was für für das server2pf-Skript benötigen.
Also einfach die Zertifikatskette speichern, öffnen und den gesamten Inhalt auf den Webserver gespeichert und Schwupp-di-wupp nun geht alles wieder.
Also, liebe Kollegen, die Anleitungen schreiben, … Bitte vergesst wichtige Teile nicht, denn ansonsten gehen eure Skripte bei anderen nicht.
So nun Viel Spaß weiterhin mit serverv2pf. Übrigens findet ihr das Skript mit einer Beschreibung auch auf github unter https://github.com/bugs-friemmedia/server2pf.