Skip to content

nexus-ncm-certs.sh

mTLS client certificate manager for the NeXuS NCM web dashboard.

Location: ~/scripts/ncm/nexus-ncm-certs.sh
Repo: hackenstacks/nexus-scripts · hackenstacks/nexus-connection-manager


What It Does

The NCM web dashboard at https://localhost:8443/ncm/ includes a live terminal (xterm.js → PTY shell). mTLS locks it down so only browsers holding a valid client certificate can connect — rejection happens at the TLS handshake before any HTTP is served.

This script manages the full certificate lifecycle:

  • Creates a local CA (Certificate Authority) stored in ~/vault/ncm-ca/
  • Issues .p12 bundles (cert + key + CA, ready for browser import) for each trusted device
  • Revokes compromised certs and rebuilds the CRL
  • Patches the web server and proxy script to enforce client cert auth

Quick Start

# 1. Create the CA (one time per node)
nexus-ncm-certs.sh init

# 2. Issue a cert for your laptop browser
nexus-ncm-certs.sh issue laptop
# → creates ~/vault/ncm-ca/clients/laptop.p12
# → prints a random import password

# 3. Wire the CA into the web server
nexus-ncm-certs.sh install

# 4. Restart the web server
nexus-api-proxy.sh restart

# 5. Import laptop.p12 into LibreWolf/Firefox:
#    Settings → Privacy & Security → Certificates → Your Certificates → Import

Commands

init

Creates the Certificate Authority. Run once per node.

nexus-ncm-certs.sh init

Generates a 4096-bit RSA CA key and a self-signed CA certificate valid for 10 years. Both live in ~/vault/ncm-ca/ with permissions set to 700.


issue <name>

Issues a client certificate for one trusted device.

nexus-ncm-certs.sh issue laptop
nexus-ncm-certs.sh issue phone
nexus-ncm-certs.sh issue anon-tablet

Each invocation:

  1. Generates a 2048-bit RSA key for the device
  2. Signs a certificate valid for 2 years
  3. Exports a .p12 bundle with a randomly-generated import password
  4. Prints the import password and browser import instructions

Keep the import password

The .p12 import password is printed once and saved alongside the file as <name>.pass. The password protects the key inside the .p12 — without it the browser cannot import the cert.

Transfer to another device:

# Via SCP
scp ~/vault/ncm-ca/clients/phone.p12 user@192.168.1.x:/tmp/

# As base64 (paste into remote terminal)
base64 ~/vault/ncm-ca/clients/phone.p12

Browser import:

Browser Path
LibreWolf / Firefox Settings → Privacy & Security → Certificates → Your Certificates → Import
Chromium / Chrome Settings → Privacy & Security → Manage Certificates → Import
Android (Chrome) Settings → Security → Install a Certificate → VPN & App User Certificate

list

Shows all issued certificates and their status.

nexus-ncm-certs.sh list

Output:

── NeXuS NCM Client Certificates ──

  CA: /home/user/vault/ncm-ca/ca.crt  (expires Sep  3 06:39:30 2036 GMT)

  NAME                  EXPIRES                       STATUS
  ────────────────────────────────────────────────────────────
  laptop                Sep  3 06:39:30 2028 GMT       VALID
  phone                 Sep  3 06:39:30 2028 GMT       VALID
  old-device            Sep  3 06:39:30 2027 GMT       REVOKED

revoke <name>

Revokes a certificate and rebuilds the CRL (Certificate Revocation List).

nexus-ncm-certs.sh revoke old-device
  • Marks the cert as revoked in the OpenSSL index
  • Rebuilds ~/vault/ncm-ca/crl.pem
  • Removes the .p12 so it cannot be re-imported
  • The revoked cert is rejected on the next TLS handshake after the web server reloads the CRL

Note

Restart the web server after revoking to enforce the new CRL immediately.


install

Patches the web server to require client certificates on every connection.

nexus-ncm-certs.sh install

Two files are patched:

  1. nexus_web_server.py — adds --ca-cert and --ca-crl CLI arguments; wires them into the SSL context with ssl.CERT_REQUIRED
  2. nexus-api-proxy.sh — passes --ca-cert ~/vault/ncm-ca/ca.crt --ca-crl ~/vault/ncm-ca/crl.pem to the server start command

After running install, restart the web server. Any browser without a valid client cert will receive a TLS handshake failure — no HTTP response, no page, no error message to fingerprint.


uninstall

Removes the client cert requirement (interactive confirmation required).

nexus-ncm-certs.sh uninstall

Removes the --ca-cert flags from nexus-api-proxy.sh. The web server reverts to HTTPS-only (no client cert check) after restart.


show-ca

Prints the CA certificate in PEM format for importing into device trust stores.

nexus-ncm-certs.sh show-ca

Useful when a device needs to trust the CA (e.g., to avoid TLS warnings when accessing other services signed by the same CA).


File Layout

~/vault/ncm-ca/
├── ca.key          — CA private key (600 permissions)
├── ca.crt          — CA certificate (import this on devices that need to trust the CA)
├── ca.srl          — Serial number counter
├── crl.pem         — Certificate Revocation List (rebuilt on every revoke)
├── index.txt       — OpenSSL certificate database
├── openssl.cnf     — OpenSSL CA configuration (auto-generated)
└── clients/
    ├── laptop.key  — Device private key (600)
    ├── laptop.crt  — Device certificate
    ├── laptop.p12  — Browser import bundle (cert + key + CA)
    └── laptop.pass — Import password (keep safe)

Security Model

Browser (laptop.p12 installed)
    │
    │ TLS ClientHello + Certificate
    ▼
NeXuS Web Server (ssl.CERT_REQUIRED)
    │ Verifies against CA + CRL
    ├── VALID   → connection proceeds, HTTP served
    └── INVALID → TLS handshake fails, connection dropped
                  no HTTP response, no fingerprint

The CA key never leaves ~/vault/ncm-ca/. Client keys never leave the device they were issued for (the .p12 is the transfer mechanism — once imported and the file deleted from the target device, the key is only in the browser's certificate store).


Environment Variables

Variable Default Description
NCM_CA_DIR ~/vault/ncm-ca CA and client cert storage
NEXUS_PROXY_SCRIPT ~/scripts/nexus-api-proxy.sh Script to patch for mTLS
NEXUS_WEB_SERVER ~/Projects/nexus-web-server/nexus_web_server.py Server to patch