When working within corporate data center environments, we often face strict firewall policies that only allow inbound SSH connections on port 22. This creates significant challenges when needing to provide external access to multiple virtual machines running on the host server.
The key constraints in this scenario are:
- Only port 22 is open for inbound SSH
- No additional ports can be opened
- Clients expect simple connection methods (Putty/FileZilla)
- Solution must be transparent to end users
Standard approaches like port forwarding or VPNs won't work here because:
# Traditional port forwarding example (won't work in this case)
iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to-destination 192.168.1.100:22
The requirement to maintain simplicity for end users while working within these constraints leads us to explore SSH reverse proxy solutions.
We can leverage SSH's built-in port forwarding capabilities to create a transparent proxy. Here's a basic implementation:
# On the corporate server (acting as jump host)
ssh -N -D 1080 user@internal-vm1
ssh -N -D 1081 user@internal-vm2
However, this requires clients to use SOCKS proxies, which may be too complex for some users.
A more elegant solution uses SSH's ProxyCommand to create transparent routing:
# Client-side ~/.ssh/config
Host vm1-access
HostName corporate-server.example.com
User corporate-user
ProxyCommand ssh -W %h:%p corporate-user@corporate-server.example.com
This approach still requires client-side configuration, which may not be ideal for non-technical users.
The most robust approach combines several techniques:
# On the corporate server
socat TCP-LISTEN:22,fork,reuseaddr EXEC:"ssh -W internal-vm1:22 user@localhost"
# For multiple VMs, use different usernames:
socat TCP-LISTEN:22,fork,reuseaddr EXEC:"ssh -W internal-vm2:22 vm2-user@localhost"
This solution provides:
- Single port access (22) for all VMs
- Transparent to end users (standard SSH clients work)
- No client-side configuration required
- Secure authentication maintained
Here's a complete implementation using a wrapper script:
#!/bin/bash
# /usr/local/bin/ssh-proxy-wrapper
case $USER in
vm1-user) TARGET="internal-vm1";;
vm2-user) TARGET="internal-vm2";;
*) echo "Access denied"; exit 1;;
esac
exec /usr/bin/ssh -W $TARGET:22 $USER@localhost
Configure /etc/ssh/sshd_config:
Match User vm1-user,vm2-user
ForceCommand /usr/local/bin/ssh-proxy-wrapper
AllowTcpForwarding no
PermitTTY no
X11Forwarding no
When implementing this solution:
- Use SSH keys exclusively (disable password auth)
- Implement rate limiting
- Monitor connection attempts
- Consider fail2ban for brute force protection
Many developers face this frustrating scenario: You're working on a server in a tightly controlled corporate data center where only SSH port 22 is accessible through the firewall. You need to provide external access to multiple virtual machines running on that server, but:
- No additional ports can be opened
- You can't modify firewall rules
- End users need simple connection methods (like basic Putty)
Standard approaches like port forwarding or VPNs won't work here because:
# This would require opening new ports - impossible in our scenario
iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to-destination 10.0.0.2:22
The answer lies in using SSH's built-in capabilities to create a reverse proxy tunnel. Here's how it works:
# On your internal server (running on port 22)
ssh -R 2222:localhost:22 external-user@public-proxy.example.com -N
This creates a secure tunnel that forwards connections from the public proxy's port 2222 back to your internal server.
Here's a complete setup example using sshuttle as a more sophisticated solution:
# Install sshuttle on your jump host
sudo apt-get install sshuttle
# Create the reverse proxy tunnel
sshuttle -r user@corporate-server:22 10.0.0.0/24
To make it easy for end users, create simple connection scripts:
:: Windows batch file for Putty users
@echo off
start putty.exe -ssh user@public-proxy.example.com -P 2222 -pw theirpassword
Always implement these security measures:
- Use SSH key authentication instead of passwords
- Implement connection rate limiting
- Set up proper user isolation
For more advanced setups, consider this approach:
# In ~/.ssh/config
Host internal-vm1
HostName public-proxy.example.com
Port 22
ProxyJump corporate-gateway
User vm1-user