Skip to main content
Problem SolvedThis guide shows you how to receive Rhombus webhooks on servers behind firewalls or NAT without requiring a public IP address or complex VPN setup.
When working with webhook integrations, it’s common to require a publicly accessible endpoint. However, some environments—particularly on-premises or secured networks—do not allow direct public IP exposure. This guide walks through how to use reverse SSH tunneling to expose a webhook listener running on a private server.

Use Cases

This method is ideal for various scenarios where direct public access isn’t available or desired:

Security Requirements

Your server is behind a NAT/firewall and cannot have a public IP

Webhook Integration

You need to receive webhook POST requests from Rhombus

Secure & Simple

You want a secure way to forward traffic to your local webhook listener

Enterprise Networks

Corporate firewalls prevent direct inbound connections

Architecture Overview

How It WorksThe reverse SSH tunnel connects the public relay back to your local server, forwarding external traffic securely to your webhook listener.

Components

ComponentRoleExamples
Private ServerRuns the webhook listenerlocalhost:8080
Public RelaySmall public cloud instanceEC2, Linode, DigitalOcean
Webhook SenderSends HTTP POST requestsRhombus Cloud Services

Step-by-Step Implementation

1

Provision a Public Relay Server

Set up a lightweight Linux server (e.g., Ubuntu) on a cloud provider like AWS, GCP, or DigitalOcean.Requirements:
  • Assign a public IP or domain name (e.g., relay.yourdomain.com)
  • Open inbound ports (80 or 443) for HTTP/HTTPS traffic
  • Minimal specs: 1 CPU, 512MB RAM is sufficient
AWS EC2 Setup
# Example AWS EC2 instance setup
aws ec2 run-instances \
  --image-id ami-0abcdef1234567890 \
  --count 1 \
  --instance-type t2.micro \
  --key-name my-key-pair \
  --security-groups my-security-group
2

Configure SSH for Remote Tunneling

On the relay server, modify the SSH daemon configuration to allow remote port forwarding:
Edit SSH Config
sudo nano /etc/ssh/sshd_config
Ensure the following options are set:
SSH Configuration
# Enable gateway ports for remote forwarding
GatewayPorts yes

# Allow TCP forwarding
AllowTcpForwarding yes

# Allow opening any port
PermitOpen any
Security NoteThese settings allow remote port forwarding. Only enable on dedicated relay servers and secure with proper firewall rules.
Restart the SSH service:
Restart SSH
sudo systemctl restart ssh

# Verify SSH is running
sudo systemctl status ssh
3

Set Up SSH Key Authentication

On your private server (where the webhook listener runs), generate SSH keys and copy them to the relay:
Generate SSH Keys
# Generate SSH key pair
ssh-keygen -t rsa -b 4096 -C "[email protected]"

# Copy public key to relay server
ssh-copy-id -i ~/.ssh/id_rsa.pub user@<RELAY_PUBLIC_IP>
Verify passwordless SSH access:
Test Connection
# Test connection (should not prompt for password)
ssh user@<RELAY_PUBLIC_IP>
Use a dedicated SSH key for the tunnel to make key rotation easier and improve security isolation.
4

Establish the Reverse SSH Tunnel

Run the following command on your private server:
Basic Reverse SSH Tunnel
# Basic reverse SSH tunnel
ssh -R 80:localhost:8080 user@<RELAY_PUBLIC_IP>
Explanation:
  • 80 - External port exposed by the relay server
  • localhost:8080 - Your local webhook listener address
  • Connection stays active in foreground
5

Test the Setup

Now test that your tunnel is working correctly:
Test Webhook
# 1. Start your webhook listener locally
# Example: Node.js server on port 8080
node webhook-server.js

# 2. Test from external source
curl -X POST http://<RELAY_PUBLIC_IP>/webhook \
  -H "Content-Type: application/json" \
  -d '{"test": "webhook payload"}'

# 3. Check your local server logs for the request
Webhook URL for Rhombus:
http://<RELAY_PUBLIC_IP>/your-webhook-endpoint
Success IndicatorIf you see the request in your local webhook listener logs, the tunnel is working correctly!

Security Enhancements

HTTPS with NGINX

For production environments, add HTTPS support:
Install NGINX
# Install NGINX on relay server
sudo apt update
sudo apt install nginx

# Create basic configuration
sudo nano /etc/nginx/sites-available/webhook-tunnel

Security Best Practices

Key-Based Authentication:
  • Use key-based SSH authentication only
  • Disable password authentication
  • Rotate SSH keys regularly
Secure SSH
# Disable password authentication
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart ssh
Firewall Configuration:
  • Restrict traffic with firewall rules
  • Use fail2ban for SSH protection
  • Monitor tunnel connections
Firewall Rules
# Example firewall rules (UFW)
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
Restrict Access:
  • Limit SSH access to specific IPs when possible
  • Use non-standard SSH ports
  • Enable two-factor authentication for SSH
IP Restriction
# Allow SSH only from specific IP
sudo ufw allow from YOUR_IP to any port 22

Production Deployment

Systemd Service for Auto-Start

Create a systemd service to automatically start the tunnel on boot:
Create Service File
# Create service file
sudo nano /etc/systemd/system/webhook-tunnel.service
Systemd Service Configuration
[Unit]
Description=Webhook SSH Tunnel
After=network.target

[Service]
Type=simple
User=your-username
ExecStart=/usr/bin/autossh -M 0 -N -R 80:localhost:8080 [email protected]
Restart=always
RestartSec=5
Environment="AUTOSSH_GATETIME=0"
Environment="AUTOSSH_POLL=30"

[Install]
WantedBy=multi-user.target
Enable Service
# Enable and start the service
sudo systemctl daemon-reload
sudo systemctl enable webhook-tunnel
sudo systemctl start webhook-tunnel

# Check status
sudo systemctl status webhook-tunnel

Monitoring and Logging

Monitor Tunnel
# Monitor tunnel status
ps aux | grep autossh

# Check tunnel logs
journalctl -u webhook-tunnel -f

# Test tunnel health
curl -s http://<RELAY_PUBLIC_IP>/health || echo "Tunnel down"

Benefits of This Approach

Works Behind Firewalls

Functions perfectly behind NAT or corporate firewalls without any inbound rules

No VPN Required

Eliminates complex VPN setup and maintenance overhead

Easy Automation

Simple to automate with autossh and systemd for production reliability

Enterprise Safe

Fully outbound connection—safe for most enterprise network policies

Cost Effective

Uses minimal resources on a small cloud instance ($5-10/month)

Highly Reliable

Auto-reconnects and self-heals with proper configuration

Troubleshooting

Problem: Cannot establish SSH connection to relay serverSolutions:
Diagnose SSH Issues
# Check SSH service status
sudo systemctl status ssh

# Verify firewall allows SSH
sudo ufw status

# Test with verbose logging
ssh -v user@<RELAY_PUBLIC_IP>

# Check SSH configuration
sudo sshd -t
Problem: Tunnel established but webhook requests don’t reach local serverSolutions:
Diagnose Tunnel Issues
# Check if port is bound on relay
ss -tlnp | grep :80

# Test local webhook server
curl localhost:8080/test

# Verify GatewayPorts setting
sudo grep GatewayPorts /etc/ssh/sshd_config

# Check relay server logs
sudo journalctl -u ssh -f
Problem: Port 80 already in use on relay serverSolutions:
Resolve Port Conflicts
# Find what's using port 80
sudo lsof -i :80

# Use alternative port
ssh -R 8080:localhost:8080 user@<RELAY_PUBLIC_IP>

# Stop conflicting service (e.g., Apache)
sudo systemctl stop apache2
Problem: Tunnel disconnects regularlySolutions:
  • Use autossh instead of regular ssh
  • Add keep-alive settings to SSH config
  • Check network stability between servers
  • Increase timeout values
SSH Keep-Alive
# Add to ~/.ssh/config
Host relay-server
    HostName <RELAY_PUBLIC_IP>
    ServerAliveInterval 60
    ServerAliveCountMax 3

Example Webhook Implementations

webhook-server.js
// webhook-server.js
const express = require('express');
const app = express();

app.use(express.json());

// Rhombus webhook endpoint
app.post('/rhombus-webhook', (req, res) => {
  console.log('Received webhook:', req.body);

  // Process webhook payload
  const { eventType, deviceId, timestamp } = req.body;

  // Your business logic here
  console.log(`Event: ${eventType} from device ${deviceId} at ${timestamp}`);

  // Respond to acknowledge receipt
  res.status(200).json({ status: 'received' });
});

// Health check endpoint
app.get('/health', (req, res) => {
  res.status(200).json({ status: 'healthy' });
});

const PORT = 8080;
app.listen(PORT, () => {
  console.log(`Webhook server running on port ${PORT}`);
});
Installation:
npm install express
node webhook-server.js

Configuring Webhooks in Rhombus

Once your listener is running and tunnel is established:
1

Get Your Webhook URL

Your public webhook URL will be:
http://<RELAY_PUBLIC_IP>/rhombus-webhook
or with HTTPS:
https://your-domain.com/rhombus-webhook
2

Configure in Rhombus Console

  1. Log in to Rhombus Console
  2. Navigate to Settings → Third Party Integrations →Webhooks
  3. Click Add Webhook
  4. Enter your public webhook URL
  5. Select the events you want to receive
  6. Save configuration
3

Monitor Events

Watch your webhook server logs to see incoming events in real-time.

Next Steps

Success!You now have a secure, reliable way to receive Rhombus webhooks on your private infrastructure without exposing your servers to the internet or requiring complex VPN setups.

Additional Resources

  • Webhook Security: Always validate webhook signatures and use HTTPS in production
  • Rate Limiting: Implement rate limiting on your webhook endpoint to prevent abuse
  • Logging: Maintain comprehensive logs of webhook events for debugging and auditing
  • Monitoring: Set up monitoring and alerts for webhook delivery failures
For production deployments, consider implementing webhook signature verification to ensure webhooks are genuinely from Rhombus.