# Zabbix SSL Checker Centrale SSL/TLS- en HTTPS-monitoring voor homelab- en kleine infra-omgevingen met Zabbix 7.x. ## Architectuur Deze checker gebruikt één centrale Zabbix host, bijvoorbeeld **Zabbix SSL Checker**. Op die host draaien external scripts vanuit `/usr/lib/zabbix/externalscripts/`. De Zabbix-template gebruikt Low-Level Discovery om targets uit `/etc/zabbix/ssl_targets.json` te ontdekken. Per ontdekt target draait één master item: ```text ssl_check.py["--config","{$SSL_CONFIG}","--host","{#SSL_HOST}","--port","{#SSL_PORT}"] ``` Dat master item geeft één JSON-object terug met TLS-, certificaat- en HTTP-informatie. Alle andere items zijn dependent items met JSONPath preprocessing. Er is dus géén Zabbix agent-interface nodig op je losse homelab-hosts. Dat voorkomt rode **ZBX agent availability** op systemen waar je helemaal geen agent wilt of kunt installeren. Zabbix bewaakt alleen de centrale checker-host; de echte HTTPS-targets worden agentloos vanaf die plek gecontroleerd. ## Bestanden ```text zabbix-ssl-checker/ README.md config/ ssl_targets.json.example scripts/ ssl_discovery.py ssl_check.py zabbix/ template_ssl_checker_relaxed_zabbix_7.yaml MANUAL_TEMPLATE_STEPS.md tests/ test_config_validation.py test_ssl_check_basic.py ``` ## Requirements - Python 3.11+ - Zabbix server of proxy met external scripts enabled - Geen verplichte Python dependencies buiten de standaardbibliotheek Optioneel: - `cryptography` voor betere parsing van SAN, issuer, subject, public key type, key size en signature algorithm. Zonder `cryptography` blijft de checker werken. Velden die niet betrouwbaar te bepalen zijn, worden `null` en er komt een melding in `warnings`. ## Installatie Voer dit uit op de Zabbix server, proxy of checker-host: ```bash sudo install -o zabbix -g zabbix -m 0755 scripts/ssl_discovery.py /usr/lib/zabbix/externalscripts/ sudo install -o zabbix -g zabbix -m 0755 scripts/ssl_check.py /usr/lib/zabbix/externalscripts/ sudo install -o zabbix -g zabbix -m 0640 config/ssl_targets.json.example /etc/zabbix/ssl_targets.json ``` Controleer dat de Zabbix user de config kan lezen: ```bash sudo chown zabbix:zabbix /etc/zabbix/ssl_targets.json sudo chmod 0640 /etc/zabbix/ssl_targets.json ``` Pas daarna `/etc/zabbix/ssl_targets.json` aan voor je eigen targets. ## Configuratie Voorbeeld: ```json [ { "name": "Blockje Home", "host": "home.blockje.nl", "port": 443, "owner": "blockje", "profile": "relaxed", "expected_issuer_contains": "Let's Encrypt", "expected_hostname": "home.blockje.nl", "http_check": true, "expected_http_status": [200, 301, 302, 401, 403], "timeout": 10 } ] ``` Verplichte velden: - `name` - `host` - `port` - `owner` - `profile` Toegestane profiles: - `relaxed` - `serious` - `internal` - `external` Als `expected_hostname` ontbreekt, gebruikt de checker automatisch `host`. Dubbele targets op dezelfde `host:port` worden één keer meegenomen in discovery. ## Testcommando's Als gebruiker `zabbix`: ```bash sudo -u zabbix /usr/lib/zabbix/externalscripts/ssl_discovery.py --config /etc/zabbix/ssl_targets.json sudo -u zabbix /usr/lib/zabbix/externalscripts/ssl_check.py --config /etc/zabbix/ssl_targets.json --host home.blockje.nl --port 443 ``` Zonder config kan ook: ```bash ./scripts/ssl_check.py --host home.blockje.nl --port 443 --expected-hostname home.blockje.nl --http-check ``` De scripts schrijven meetdata naar stdout en fouten/debugmeldingen naar stderr. `ssl_check.py` geeft bij TLS- of bereikbaarheidsproblemen nog steeds JSON terug, zodat dependent items stabiel blijven. ## Zabbix import 1. Ga naar **Data collection -> Templates -> Import**. 2. Importeer `zabbix/template_ssl_checker_relaxed_zabbix_7.yaml`. 3. Maak een nieuwe host: - Host name: `Zabbix SSL Checker` - Interfaces: geen externe homelab-agent interfaces nodig - Link template: `Template SSL Checker Relaxed` - Macro `{$SSL_CONFIG}`: `/etc/zabbix/ssl_targets.json` 4. Laat discovery draaien of klik op **Execute now** bij de discovery rule. Als import faalt door YAML-verschillen tussen Zabbix 7.x minor releases, gebruik dan `zabbix/MANUAL_TEMPLATE_STEPS.md`. ## Wat wordt gecontroleerd TLS/certificaat: - bereikbaarheid - hostname match - chain validity via de default trust store - self-signed detectie waar mogelijk - geldigheid nu, not before, not after en days left - issuer CN/org, subject CN, SAN names - SHA256 fingerprint - negotiated TLS version - TLS 1.0, 1.1, 1.2 en 1.3 support waar Python/OpenSSL dat toestaat HTTP: - HTTPS request met maximaal 5 redirects - response time - final URL - statuscode en verwachte status - Server header - HSTS - X-Content-Type-Options - X-Frame-Options - Content-Security-Policy - Referrer-Policy - simpele security header score van 0 tot 5 ## Debugtips Unsupported items: - Controleer of de scripts executable zijn. - Controleer of ze in de Zabbix `ExternalScripts` directory staan. - Run exact dezelfde key als `zabbix` user. - Kijk in `zabbix_server.log` of `zabbix_proxy.log`. Script permissies: - Scripts: `0755`, owner `zabbix:zabbix` - Config: `0640`, owner `zabbix:zabbix` Python dependencies: - De basis gebruikt alleen standaardbibliotheken. - Installeer optioneel `cryptography` als je rijkere key- en signaturevelden wilt. DNS/firewall: - Test DNS vanaf de checker-host, niet vanaf je laptop. - Test of de checker-host TCP 443 naar het target mag openen. CA trust store: - Chain-validatie gebruikt de default trust store van Python/OpenSSL. - Voor interne CA's moet de CA op de checker-host trusted zijn. SNI: - De checker gebruikt SNI met `expected_hostname`. - Bij shared hosting moet `expected_hostname` overeenkomen met de certificaatnaam die je verwacht. ## Security - Het configbestand bevat geen secrets. - Maak het toch niet world-writable. - Hostnamen, poorten en profiles worden gevalideerd. - Er wordt geen `shell=True` gebruikt. - Er wordt geen ruwe input in shellcommando's gestopt. - De checker gebruikt geen `openssl` subprocess; TLS loopt via Python `ssl` en `socket`. - Timeouts worden op netwerkverbindingen toegepast zodat checks niet blijven hangen. ## Tuning Standaard in de template: - Discovery interval: `1h` - Check interval: `15m` - History raw JSON: `7d` - History dependent items: `30d` - Trends numerieke dependent items: `365d` De profiles `relaxed`, `serious`, `internal` en `external` zijn nu vooral metadata en tags. Je kunt later per profile extra triggers of strengere policies toevoegen. ## Tests Lokaal: ```bash python -m pytest ``` De tests controleren configuratievalidatie, discovery output en JSON-output bij een onbereikbaar target.