Files
2026-05-21 20:05:02 +02:00

281 lines
8.9 KiB
Markdown

# 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.
## Installatie met Docker
Gebruik je de officiële Zabbix Docker-images, dan is het meestal praktischer om external scripts en de target-config in het persistente Zabbix data-volume te zetten. Met jouw volumeconfig:
```yaml
volumes:
- /media/zabbix/zabbix-server-data:/var/lib/zabbix
- /media/zabbix/zabbix-snmptraps-data:/var/lib/zabbix/snmptraps
- /media/zabbix/zabbix-export-data:/var/lib/zabbix/export
```
kun je op de Docker-host deze paden gebruiken:
```bash
sudo install -d -o 1997 -g 1995 -m 0755 /media/zabbix/zabbix-server-data/externalscripts
sudo install -o 1997 -g 1995 -m 0755 scripts/ssl_discovery.py /media/zabbix/zabbix-server-data/externalscripts/
sudo install -o 1997 -g 1995 -m 0755 scripts/ssl_check.py /media/zabbix/zabbix-server-data/externalscripts/
sudo install -o 1997 -g 1995 -m 0640 config/ssl_targets.json.example /media/zabbix/zabbix-server-data/ssl_targets.json
```
In de container worden deze bestanden dan zichtbaar als:
```text
/var/lib/zabbix/externalscripts/ssl_discovery.py
/var/lib/zabbix/externalscripts/ssl_check.py
/var/lib/zabbix/ssl_targets.json
```
Zet op de host `{$SSL_CONFIG}` in de gelinkte template of host-macro daarom op:
```text
/var/lib/zabbix/ssl_targets.json
```
Test daarna vanuit de Zabbix server-container. Vervang `zabbix-server` door de naam van jouw container:
```bash
docker exec -u zabbix zabbix-server /var/lib/zabbix/externalscripts/ssl_discovery.py --config /var/lib/zabbix/ssl_targets.json
docker exec -u zabbix zabbix-server /var/lib/zabbix/externalscripts/ssl_check.py --config /var/lib/zabbix/ssl_targets.json --host home.blockje.nl --port 443
```
Als jouw image external scripts niet uit `/var/lib/zabbix/externalscripts` leest, mount dan expliciet naar de directory die in de container als `ExternalScripts` is ingesteld. Vaak is dat bij niet-Docker installaties `/usr/lib/zabbix/externalscripts`. Controleer bij twijfel de Zabbix server/proxy configuratie in de container.
Let op met UID/GID: officiële Zabbix containers gebruiken vaak de `zabbix` gebruiker binnen de container. De numerieke `1997:1995` komt veel voor, maar kan per image verschillen. Als de testcommando's permission errors geven, controleer dan met:
```bash
docker exec zabbix-server id zabbix
docker exec zabbix-server ls -l /var/lib/zabbix/externalscripts /var/lib/zabbix/ssl_targets.json
```
## 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.