hacs-hafas icon indicating copy to clipboard operation
hacs-hafas copied to clipboard

KVB no connections

Open nils-keller-dev opened this issue 9 months ago • 15 comments

Yesterday my KVB sensor stopped showing any connections:

Image

Also I can't add any new KVB entities, as I get this error after clicking "Submit":

Image

I checked the log for the second error and I think this is the relevant line:

2025-02-22 14:55:34.983 ERROR (MainThread) [homeassistant.components.sensor] Error while setting up hafas platform for sensor: HTTPSConnectionPool(host='auskunft.kvb.koeln', port=443): Max retries exceeded with url: /gate (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1018)')))

nils-keller-dev avatar Feb 23 '25 14:02 nils-keller-dev

Thanks for investigating so thoroughly!

I tried the bare https://auskunft.kvb.koeln URL in Chrome and it also says the certificate has expired. This seems to also affect the main kvb.koeln site: It does not show connections either. But if I "accept the risk" on auskunft.kvb.koeln and open it insecurely, the main site will start to give connections, despite Chrome showing a warning about insecure parts of the site.

So, I think it is a technical error on the KVB end, which they will want to fix first thing tomorrow morning.

(I was dreading they might also have shut down their hafas endpoint. But the fact that it's used on the main site gives me some confidence in it surviving some more time...)

akloeckner avatar Feb 23 '25 14:02 akloeckner

You're right, I get the same behavior on their site. Let's hope they fix it soon! And thank you for the quick reply :)

nils-keller-dev avatar Feb 23 '25 14:02 nils-keller-dev

KVB updated their certificates. However, I now get another error (after reloading the configuration entries):

requests.exceptions.SSLError: HTTPSConnectionPool(host='auskunft.kvb.koeln', port=443): Max retries exceeded with url: /gate (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1018)')))

Do you see this, too? Or is it only me?

akloeckner avatar Feb 25 '25 20:02 akloeckner

I get the same error :(

nils-keller-dev avatar Feb 25 '25 21:02 nils-keller-dev

Hmm... I am currently out of ideas. It seems to be some mismatch between HA and KVB. I run HA in Docker and I cannot even run

import requests

requests.get("https://auskunft.kvb.koeln")

on the Docker container's python3. In online python tools, this works without issues. The root certificate's test site works on HA, too.

akloeckner avatar Feb 25 '25 22:02 akloeckner

That's really weird. I will check if I can find anything else when I have the time, though I doubt it.

nils-keller-dev avatar Feb 26 '25 18:02 nils-keller-dev

Update: The same happens even outside python3 but just inside the Docker container, using wget. Even in the baseline python:3.13-alpine and alpine:3.21 images. And it's also in the alpine:latest image.

/ # wget https://auskunft.kvb.koeln
Connecting to auskunft.kvb.koeln (195.14.249.164:443)
284B3767CE7F0000:error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:2103:
ssl_client: SSL_connect
wget: error getting response: Connection reset by peer
/ #
/ #
/ # wget https://global-root-g2.chain-demos.digicert.com/
Connecting to global-root-g2.chain-demos.digicert.com (216.168.244.44:443)
saving to 'index.html'
index.html           100% |*****************************|  1854  0:00:00 ETA
'index.html' saved

The connection even fails in the latest Ubuntu image:

# wget https://auskunft.kvb.koeln
--2025-02-27 19:28:24--  https://auskunft.kvb.koeln/
Resolving auskunft.kvb.koeln (auskunft.kvb.koeln)... 195.14.249.164
Connecting to auskunft.kvb.koeln (auskunft.kvb.koeln)|195.14.249.164|:443... connected.
ERROR: cannot verify auskunft.kvb.koeln's certificate, issued by 'CN=Thawte TLS RSA CA G1,OU=www.digicert.com,O=DigiCert Inc,C=US':
  Unable to locally verify the issuer's authority.
To connect to auskunft.kvb.koeln insecurely, use `--no-check-certificate'.

So... New suspected culprit: libssl (openssl)?

Or the server is configured incompletely, in that it does not provide the intermediate certificate. This would be downloaded by browsers, but not by command-line libssl uses. This would need to be verified with a PC browser, first. If we can then find a browser, which also does not download intermediate certificates, this could make a case to ask KVB zu fix their configuration.

akloeckner avatar Feb 27 '25 14:02 akloeckner

As it appears, the KVB server is not configured correctly, because it does not serve the intermediate certificate, see this checker:

https://whatsmychaincert.com/?auskunft.kvb.koeln

I'm thinking about how to ignore this in our package while KVB (hopefully) fixes their setup. Possibly, we could also locally install this one intermediate certificate. But I currently have no idea how to do either of those...

akloeckner avatar Feb 28 '25 22:02 akloeckner

In Firefox on mobile I still get a security warning when opening the website (I didn't test on desktop). I will write them an email about that today and hopefully they will fix it soon 🤞

nils-keller-dev avatar Mar 02 '25 06:03 nils-keller-dev

I think, I found a workaround. The following command will add the missing intermediate certificate as an additional root CA certificate into python's certifi package's certificate store. Not a very elegant solution, but it's working on my end.

Home assistant apparently needs to be restarted after this change. I'll investigate more closely, because I want #34 to work.

Be aware, that mangling with root certificates might compromise your server's security!

Run this inside your HA's docker container:

cat <<EOF >> /usr/local/lib/python3.13/site-packages/certifi/cacert.pem

# Add KVB intermediate certificate 
-----BEGIN CERTIFICATE-----
MIIEizCCA3OgAwIBAgIQCQ7oxd5b+mLSri/3CXxIVzANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xNzExMDIxMjI0MjVaFw0yNzExMDIxMjI0MjVaMF4xCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xHTAbBgNVBAMTFFRoYXd0ZSBUTFMgUlNBIENBIEcxMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAxjngmPhVetC0b/ozbYJdzOBUA1sMog47030cAP+P
23ANUN8grXECL8NhDEF4F1R9tL0wY0mczHaR0a7lYanlxtwWo1s2uGnnyDs6mOCs
66ew2w3YETr6Tb14xgjpu1gGFtAeewaikO9Fud8hxGJTSwn8xeNkfKVWpD2L4vFN
36FNgxeilK6aE4ykgGAzNlokTp6hNOLAYpDySdLAPKzuJSQ7JCEZ6O+SDKywIdXL
oMTnpxuBKGSG88NWTo3CHCOGmQECia2yqdPDjgLqnEiYNjwQL8uMqj8rOvlMgviB
cHA7xty+7/uYLN6ZS7Vq1/F/lVhVOf5ej6jZdmB85szFbQIDAQABo4IBQDCCATww
HQYDVR0OBBYEFKWM/jLM6w8s1BnGCLgAJIhdw8W3MB8GA1UdIwQYMBaAFE4iVCAY
lebjbuYP+vq5Eu0GF485MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEF
BQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADA0BggrBgEFBQcBAQQo
MCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBCBgNVHR8E
OzA5MDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9i
YWxSb290RzIuY3JsMD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxo
dHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA0GCSqGSIb3DQEBCwUAA4IBAQC6
km0KA4sTb2VYpEBm/uL2HL/pZX9B7L/hbJ4NcoBe7V56oCnt7aeIo8sMjCRWTCWZ
D1dY0+2KZOC1dKj8d1VXXAtnjytDDuPPf6/iow0mYQTO/GAg/MLyL6CDm3FzDB8V
tsH/aeMgP6pgD1XQqz+haDnfnJTKBuxhcpnx3Adbleue/QnPf1hHYa8L+Rv8Pi5U
h4V9FwHOfphdMXOxi14OqmsiTbc5cOs9/uukH+YVsuFdWTna6IVw1qh+tEtyH16R
vmi7pkqyZYULOPMIE7avrljVVBZuikwARtY8tCVV6Pp9l3VeagBqb2ffgqNJt3C0
TYNYQI+BXG1R1cABlold
-----END CERTIFICATE-----
EOF

If you are not running HA in Docker, you might want to use the following commands to find the correct cacert.pem file:

Python 3.13.1 (main, Dec 15 2024, 21:16:25) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import certifi
>>> certifi.where()
'/usr/local/lib/python3.13/site-packages/certifi/cacert.pem'

akloeckner avatar Mar 19 '25 00:03 akloeckner

I tried this but the file does not exist. I searched the file system for a cacert.pem file using find / -name "cacert.pem" 2>/dev/null and got one result in /usr/lib/python3.12/site-packages/pip/_vendor/certifi/cacert.pem.

So I added the certificate in there and restarted, but it still doesn't work :( Do you have any idea what my issue might be? Also, I don't have the module certifi installed (I checked using python -m certifi). Do I need to install it first?

EDIT: I worked it out. I wasn't running the command inside HA's docker container. After running docker exec -it homeassistant /bin/bash, it worked like a charm. Thank you so much!

nils-keller-dev avatar Mar 21 '25 15:03 nils-keller-dev

👍 I updated the description to reflect that hint.

akloeckner avatar Mar 21 '25 18:03 akloeckner

Not sure if it makes a difference, but there was a similar issue in the hafas-client repo and it was fixed: https://github.com/public-transport/hafas-client/issues/338
Maybe it makes sense to update the dependency?

nils-keller-dev avatar May 22 '25 14:05 nils-keller-dev

We're not using hafas-client. And the fix is not readily portable, because we use Python (and not JavaScript). But if anybody came up with a fix that doesn't require manual tweaking by the user, it would be better...

akloeckner avatar May 22 '25 17:05 akloeckner

I stumbled against this other issue in the pyhafas repo yesterday. And we could disable SSL checks as proposed there by setting client.profile.request_session.validate = False in get_client. But I would consider it unsafe...

Note to self: Maybe this might work: client.profile.request_session.verify = 'path/to/root'. See: https://requests.readthedocs.io/en/latest/user/advanced/#ssl-cert-verification

akloeckner avatar May 30 '25 08:05 akloeckner