Outbound Service Tunneling
This post describes a remote access architecture using outbound-initiated, TLS-wrapped tunnels. The pattern is useful for home labs behind CGNAT, development workstations, and distributed infrastructure where opening inbound ports isn't possible or desirable.
What This Is
Machines establish outbound connections to external endpoints, then expose internal services back through those connections.
Key properties:
- Outbound initiation only; no inbound ports required
- TLS wraps inner protocols (SSH, database connections)
- Services become accessible via external endpoint
Common scenarios: Home labs behind CGNAT, development workstations on corporate networks, distributed infrastructure.
The Problem
You have services running on a machine that can't accept inbound connections:
- Behind carrier-grade NAT (no public IP)
- Corporate firewall blocking inbound
- Network policy restricting port exposure
Traditional solutions like VPNs or port forwarding don't work in these environments.
How It Works
The architecture uses layered protocols:
Internal Network External Endpoint (VPS)
┌─────────────────┐ ┌─────────────────┐
│ Internal │ │ Exposed │
│ Services │ │ Endpoints │
│ (DBs, APIs) │ │ (now reachable) │
└────────┬────────┘ └────────▲────────┘
│ │
┌────────▼────────┐ ┌────────┴────────┐
│ SSH Client │◄─────Reverse──────────│ SSH Daemon │
│ Reverse Tunnels │ Tunnels │ Tunnel Endpoint │
└────────┬────────┘ └────────▲────────┘
│ │
┌────────▼────────┐ ┌────────┴────────┐
│ TLS Wrapper │ │ TLS Termination │
│ (stunnel) │ │ (stunnel) │
└────────┬────────┘ └────────▲────────┘
│ │
└──────────TLS on 443─────────────────────┘
(looks like HTTPS)
The Mechanism
- Internal machine opens outbound TLS connection (port 443)
- TLS handshake with optional mutual certificate authentication
- SSH session authenticates inside TLS wrapper
- SSH reverse tunnels bind external ports to internal services
Services on the internal network become reachable via the external endpoint. The outbound TLS connection looks indistinguishable from normal HTTPS traffic.
Why TLS Wrapping?
Many corporate networks only allow outbound traffic on specific ports (80, 443). By wrapping SSH in TLS on port 443:
- Traffic appears as standard HTTPS
- Passes through most firewalls and proxies
- TLS encryption protects the inner SSH session
This isn't about evading security—it's about working within network constraints while maintaining proper authentication and audit trails.
Security Layers
The architecture provides multiple independent security layers:
| Layer | Function | Scope |
|---|---|---|
| TLS encryption | Protects data in transit | Transport |
| Mutual TLS (optional) | Verifies both endpoints have valid certificates | Endpoint authentication |
| SSH key auth | Requires possession of private key | User authentication |
| Explicit tunnels | Only specified services are exposed | Service exposure |
Trust Model
Trust is enforced at the application layer rather than network perimeter:
- Service accessibility: Controlled via tunnel endpoint authentication
- Authentication: Explicit credentials at multiple layers (TLS certs, SSH keys)
- Access control: Managed by tunnel operator; scoped to specific services
- Audit trail: Maintained at external endpoint with full connection context
What's Visible Where
Network layer (corporate firewall):
- Standard TLS on port 443
- Connection metadata (destination IP, SNI hostname)
- Cannot see payload content
Tunnel endpoint (your VPS):
- Full visibility into exposed services
- Authentication logs for tunnel establishment
- Access logs for tunneled services
Implementation with stunnel
On the internal machine (client):
# /etc/stunnel/stunnel.conf
[ssh-out]
client = yes
accept = 127.0.0.1:2222
connect = vps.example.com:443
On the VPS (server):
# /etc/stunnel/stunnel.conf
[ssh-in]
accept = 443
connect = 127.0.0.1:22
cert = /etc/stunnel/server.pem
Then establish the SSH reverse tunnel:
# From internal machine
ssh -p 2222 -R 5432:localhost:5432 user@127.0.0.1
This exposes the internal PostgreSQL (port 5432) on the VPS.
Making It Robust
For production use:
# autossh for automatic reconnection
autossh -M 0 \
-o "ServerAliveInterval 30" \
-o "ServerAliveCountMax 3" \
-p 2222 \
-R 5432:localhost:5432 \
-N user@127.0.0.1
Run as a systemd service for persistence across reboots.
Comparison with Alternatives
| Approach | Trust Model | Network Visibility |
|---|---|---|
| Traditional VPN | Network-level access | VPN protocol traffic |
| Outbound TLS tunneling | Service-level access | Standard HTTPS |
| Zero-trust proxies (Cloudflare, Tailscale) | Identity-based access | Provider infrastructure |
| Direct port exposure | IP-based access | Inbound connections |
The outbound tunneling approach gives you service-level access control without depending on third-party infrastructure.
Detection and Monitoring
This architecture produces observable patterns:
Traffic characteristics:
- Persistent connections with consistent duration (hours to days)
- Predictable traffic patterns distinct from interactive browsing
- Connections to infrastructure hosting providers
- Regular connection re-establishment schedules
Analysis opportunities:
- Statistical modeling of connection behavior
- Anomaly detection based on duration baselines
- Infrastructure correlation via DNS and certificate data
Network security teams can detect these patterns. The goal isn't stealth—it's working within policy constraints while maintaining proper security controls.
Use Cases
Home Lab
- Remote access without public IP or inbound ports
- Self-hosted services accessible from anywhere
- Full control over the tunnel endpoint
Development Workstations
- Expose local dev servers to collaborators
- Demo applications without deployment
- Database access for remote debugging
Distributed Infrastructure
- Connect services across network boundaries
- Centralized logging and audit trails
- Service-specific access without full VPN
Summary
Outbound TLS tunneling is useful when you need external service access without inbound connections. The pattern provides:
- Application-layer trust enforcement
- Service-scoped access control
- Standard protocols (TLS, SSH) on standard ports
- No inbound ports required
For the Docker networking complications that can arise when combining this pattern with containerized services, see my post on Docker bridge network isolation.