From 269b098f0d5f500cadd2891c610c3f485a025621 Mon Sep 17 00:00:00 2001 From: tdv Date: Fri, 3 Oct 2025 13:22:47 +0300 Subject: [PATCH] added mtls for device endpoints --- docker-compose.yaml | 23 +++------ nginx/dev.conf | 120 +++++++++++++++++++++++++++++++++++++++----- readme.md | 20 +++++++- 3 files changed, 133 insertions(+), 30 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 693d99c..9d8d118 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -36,20 +36,6 @@ services: networks: - snoopBack - vault: - image: hashicorp/vault:1.16 - environment: - VAULT_API_ADDR: http://0.0.0.0:8200 - VAULT_TOKEN: root - ports: - - 8200:8200 - cap_add: - - IPC_LOCK - volumes: - - vault-data:/vault/data - networks: - - snoopBack - snoop-api: restart: unless-stopped build: @@ -93,8 +79,14 @@ services: - snoop-api ports: - "80:80" + - "443:443" volumes: - ./nginx/dev.conf:/etc/nginx/conf.d/default.conf:ro,Z + # - ./nginx/nginx_ssl/fullchain.pem:/etc/nginx/ssl/certs/fullchain.pem + # - ./nginx/nginx_ssl/privkey.pem:/etc/nginx/ssl/certs/privkey.pem + - ./nginx/nginx_ssl:/etc/nginx/ssl/certs/:ro,Z + - ./nginx/nginx_ssl/iot_int_cert.pem:/etc/nginx/ssl/iot_int_cert.pem:ro,Z + - ./nginx/nginx_ssl/iot.crl:/etc/nginx/ssl/iot.crl:ro,Z networks: - proxy @@ -162,8 +154,9 @@ services: volumes: pgdata: miniodata: - vault-data: mediamtx-recordings: + emqx-data: + emqx-log: networks: proxy: diff --git a/nginx/dev.conf b/nginx/dev.conf index 1a144c3..17a04ac 100644 --- a/nginx/dev.conf +++ b/nginx/dev.conf @@ -41,19 +41,6 @@ server { proxy_send_timeout 3600s; } - # --- LIVE --- - # HLS playlist/segments - location /hls/ { - proxy_pass http://mediamtx:8888/; - proxy_http_version 1.1; - } - - # WebRTC WHIP/WHEP/test pages - location /webrtc/ { - proxy_pass http://mediamtx:8889/; - proxy_http_version 1.1; - } - # --- MQTT over WebSocket (EMQX) --- # Clients connect to ws:///mqtt/ws location /mqtt/ws { @@ -64,4 +51,111 @@ server { proxy_read_timeout 3600s; proxy_send_timeout 3600s; } +} + +# ============================================== +# HTTPS :443 — mTLS enforced only on listed paths +# ============================================== +server { + listen 443 ssl http2; + server_name _; + + ssl_certificate /etc/nginx/ssl/certs/fullchain.pem; + ssl_certificate_key /etc/nginx/ssl/certs/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + + # mTLS trust chain (from Vault) + ssl_client_certificate /etc/nginx/ssl/iot_int_cert.pem; + ssl_verify_client optional; # locations below require SUCCESS + ssl_verify_depth 3; + + # Client cert revocation (optional) + ssl_crl /etc/nginx/ssl/iot.crl; + + # Forward client cert details upstream + proxy_set_header X-SSL-Client-Verify $ssl_client_verify; + proxy_set_header X-SSL-Client-Serial $ssl_client_serial; + proxy_set_header X-SSL-Client-Issuer $ssl_client_i_dn; + proxy_set_header X-SSL-Client-DN $ssl_client_s_dn; + proxy_set_header X-SSL-Client-Cert $ssl_client_escaped_cert; + + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + + error_page 495 = @mtls_error; + + # location @mtls_error { + # return 403 "ERR_SSL_VERSION_OR_CIPHER_MISMATCH \n"; + # } + + location @mtls_error { + return 403 "mTLS required or client certificate invalid.\n"; + } + + location = /_mtls_check { + return 200 "$ssl_client_verify\n$ssl_client_s_dn\n$ssl_client_i_dn\n"; + } + + # ---- mTLS-protected paths ---- + location ^~ /records { + if ($ssl_client_verify != SUCCESS) { + return 495; + } + proxy_pass http://snoop-api:8080; + } + + location ^~ /tasks { + if ($ssl_client_verify != SUCCESS) { + return 495; + } + proxy_pass http://snoop-api:8080; + } + + location ^~ /renew { + if ($ssl_client_verify != SUCCESS) { + return 495; + } + proxy_pass http://snoop-api:8080; + } + + # MediaMTX HLS + location ^~ /hls/ { + if ($ssl_client_verify != SUCCESS) { + return 495; + } + proxy_pass http://mediamtx:8888/; + } + + # MediaMTX WebRTC (WHIP/WHEP/test) + location ^~ /webrtc/ { + if ($ssl_client_verify != SUCCESS) { + return 495; + } + proxy_pass http://mediamtx:8889/; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + } + + # MQTT WS entry points (guarded by mTLS) + location = /loc { + if ($ssl_client_verify != SUCCESS) { + return 495; + } + proxy_pass http://emqx:8083/mqtt; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + } + + location = /gtasks { + if ($ssl_client_verify != SUCCESS) { + return 495; + } + proxy_pass http://emqx:8083/mqtt; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + } + } \ No newline at end of file diff --git a/readme.md b/readme.md index f123bf7..ed30697 100644 --- a/readme.md +++ b/readme.md @@ -74,13 +74,16 @@ vault write pki_iot/config/urls \ # Role that limits cert subjects to your device GUIDs vault write pki_iot/roles/device \ - allow_any_name=false \ + allow_any_name=true \ allowed_uri_sans="urn:device:*" \ allowed_other_sans="" \ + require_cn=false \ + cn_validations= \ allow_ip_sans=false \ allowed_domains="" \ enforce_hostnames=false \ - key_type=ec key_bits=256 \ + key_type=ec \ + key_bits=256 \ max_ttl=720h ttl=720h # 30 days ``` @@ -107,3 +110,16 @@ curl -fsSL https://vault.example.local/v1/pki_iot/crl -o /etc/nginx/iot.crl nginx -s reload ``` - Automate via systemd timer/cron (e.g., every 10–15 min). + +- Nginx fix for DER CRL format +```bash +# sed -i 's/\r$//' ./nginx/nginx_ssl/int_iot.crl +curl http://vault.local:8200/v1/pki_iot/crl -o nginx/nginx_ssl/int_iot.crl +openssl crl -in ./nginx/nginx_ssl/int_iot.crl -out ./nginx/nginx_ssl/int_iot.crl.clean -outform PEM +mv ./nginx/nginx_ssl/int_iot.crl.clean ./nginx/nginx_ssl/int_iot.crl +curl http://vault.local:8200/v1/pki_root/crl -o nginx/nginx_ssl/root_iot.crl +openssl crl -in ./nginx/nginx_ssl/root_iot.crl -out ./nginx/nginx_ssl/root_iot.crl.clean -outform PEM +mv ./nginx/nginx_ssl/root_iot.crl.clean ./nginx/nginx_ssl/root_iot.crl +(sed 's/\r$//' ./nginx/nginx_ssl/int_iot.crl; echo; sed 's/\r$//' ./nginx/nginx_ssl/root_iot.crl; echo) \ +> ./nginx/nginx_ssl/iot.crl +``` \ No newline at end of file