TLS Interception Setup Guide#
Pipelock can intercept CONNECT tunnel traffic by performing a TLS MITM: it terminates TLS with the client using a forged certificate, scans the decrypted request and response, then forwards to the upstream server over a separate TLS connection. This closes the body-blindness gap that exists with opaque CONNECT tunnels.
Without TLS interception, CONNECT tunnels only get hostname-level scanning (blocklist, SSRF, rate limiting). With it, you get full DLP on request bodies/headers and response injection detection.
Quick Start#
# 1. Generate a CA
pipelock tls init
# 2. Trust it (prints platform-specific instructions)
pipelock tls install-ca
# 3. Enable in config
cat >> pipelock.yaml << 'EOF'
tls_interception:
enabled: true
EOF
# 4. Run
pipelock run --config pipelock.yaml
Step 1: Generate the CA#
pipelock tls init
This creates two files in ~/.pipelock/:
ca.pem: the CA certificate (share this, it's public)ca-key.pem: the CA private key (protect this,0600permissions)
Options:
| Flag | Default | Description |
|---|---|---|
--out | ~/.pipelock | Output directory |
--org | Pipelock | Organization name in certificate subject |
--validity | 87600h (10 years) | How long the CA is valid |
--force | false | Overwrite existing files |
Custom output directory:
pipelock tls init --out /etc/pipelock/tls --org "My Company"
If using a custom directory, set ca_cert and ca_key in your config:
tls_interception:
enabled: true
ca_cert: /etc/pipelock/tls/ca.pem
ca_key: /etc/pipelock/tls/ca-key.pem
Step 2: Trust the CA#
The agent (or whatever makes HTTPS connections through pipelock) must trust the CA certificate. Otherwise TLS handshakes fail with certificate verification errors.
System Trust Store#
pipelock tls install-ca
This prints platform-specific instructions. You still need to run the commands it shows.
Linux (Debian/Ubuntu):
sudo cp ~/.pipelock/ca.pem /usr/local/share/ca-certificates/pipelock-ca.crt
sudo update-ca-certificates
Linux (RHEL/Fedora):
sudo cp ~/.pipelock/ca.pem /etc/pki/ca-trust/source/anchors/pipelock-ca.crt
sudo update-ca-trust extract
macOS:
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ~/.pipelock/ca.pem
Windows (elevated Command Prompt):
certutil -addstore -f "ROOT" %USERPROFILE%\.pipelock\ca.pem
Per-Application Trust#
Some tools ignore the system trust store. Set the CA path explicitly:
Node.js / npm:
export NODE_EXTRA_CA_CERTS=~/.pipelock/ca.pem
Python (requests/httpx):
export REQUESTS_CA_BUNDLE=~/.pipelock/ca.pem
export SSL_CERT_FILE=~/.pipelock/ca.pem
Go:
export SSL_CERT_FILE=~/.pipelock/ca.pem
curl:
curl --cacert ~/.pipelock/ca.pem https://example.com
# Or set globally:
export CURL_CA_BUNDLE=~/.pipelock/ca.pem
Step 3: Configure#
Minimal config:
tls_interception:
enabled: true
Full options:
tls_interception:
enabled: true
ca_cert: "" # default: ~/.pipelock/ca.pem
ca_key: "" # default: ~/.pipelock/ca-key.pem
max_response_bytes: 5242880 # 5MB, block responses larger than this
passthrough_domains: # bypass interception for these domains
- "*.pinned-service.com"
- "api.payment-provider.com"
Passthrough Domains#
Some services use certificate pinning or mutual TLS that breaks under interception. Add them to passthrough_domains:
tls_interception:
enabled: true
passthrough_domains:
- "*.apple.com" # Apple services pin certificates
- "mtls.internal.corp.com" # mTLS endpoint
Passthrough connections are spliced (bidirectional byte copy) without decryption. Hostname-level scanning (blocklist, SSRF, SNI verification) still applies.
Supports exact match (api.example.com) and wildcard prefix (*.example.com matches sub.example.com but not example.com itself).
Fail-Closed Behavior#
TLS interception is fail-closed:
- Compressed responses (Content-Encoding other than identity): blocked (scanning would be bypassed)
- Responses larger than
max_response_bytes: blocked - TLS handshake failures: connection closed
- Certificate generation errors: connection closed
Verifying It Works#
# Start pipelock with TLS interception
pipelock run --config pipelock.yaml &
# Test through the proxy (should succeed)
HTTPS_PROXY=http://127.0.0.1:8888 curl -s https://example.com
# Test DLP through CONNECT tunnel (should be blocked)
HTTPS_PROXY=http://127.0.0.1:8888 \
curl -s "https://httpbin.org/post" \
-d "token=AKIAIOSFODNN7EXAMPLE"
Check the pipelock logs (stderr) for scan results.
Troubleshooting#
"certificate signed by unknown authority"#
The agent doesn't trust the pipelock CA. Either:
- Install the CA in the system trust store (Step 2)
- Set the per-application CA env var (see above)
- Add the domain to
passthrough_domainsif you can't modify the client
"x509: certificate is valid for X, not Y"#
The hostname in the request doesn't match what pipelock generated. This usually means a DNS or proxy misconfiguration. Check that HTTPS_PROXY is set correctly and the target hostname resolves properly.
Compressed response blocked#
Pipelock blocks compressed responses during interception because it can't scan content it can't read. The upstream server sent Content-Encoding: gzip (or similar). Pipelock's transport sets Accept-Encoding: identity to request uncompressed responses, but some servers ignore this.
If you trust the domain, add it to passthrough_domains.
Performance#
TLS interception adds latency for the MITM handshake. Pipelock mitigates this with:
- Connection pooling (shared
http.Transportreuses TCP+TLS connections) - Bounded certificate cache (avoids regenerating leaf certs for repeated hosts)
- ECDSA P-256 keys (faster than RSA for signing)
For high-throughput environments, consider using passthrough for trusted high-volume domains.