When administering multiple servers through an SSH gateway, maintaining individual entries in ~/.ssh/config
becomes unwieldy. A typical scenario looks like this:
Host server1-via-gateway
Hostname server1.internal
IdentityFile ~/.ssh/id_rsa
ProxyCommand ssh gateway.example.com nc %h 22
Host server2-via-gateway
Hostname server2.internal
IdentityFile ~/.ssh/id_rsa
ProxyCommand ssh gateway.example.com nc %h 22
SSH config does support pattern matching and variable substitution, though not as extensively as shell scripting. Here's the solution:
Host *.via-gateway
Hostname %h
IdentityFile ~/.ssh/id_rsa
ProxyCommand ssh gateway.example.com nc ${${(%):-%n}#*.} 22
For more complex transformations, use a wrapper script:
Host *
ProxyCommand /usr/local/bin/ssh-proxy-wrapper %h
Then create ssh-proxy-wrapper
:
#!/bin/bash
# Extract the actual hostname from the pattern
TARGET_HOST="${1%.via-gateway}"
exec ssh gateway.example.com nc $TARGET_HOST 22
For dynamic environments, generate configs programmatically:
#!/bin/bash
# Generate SSH config entries for all hosts in inventory
while read host; do
echo "Host $host.via-gateway"
echo " Hostname $host"
echo " ProxyCommand ssh gateway nc $host 22"
echo
done < host-list.txt >> ~/.ssh/config
SSH 7.3+ supports includes for modular configurations:
Include config.d/*.conf
Then maintain separate files for different host groups.
Remember to:
- Set proper permissions:
chmod 600 ~/.ssh/config
- Audit generated configurations
- Use SSH certificates for large deployments
When managing multiple servers behind a gateway, manually maintaining SSH config entries becomes tedious. Here's a smarter approach to automate this process while maintaining security and convenience.
The standard approach requires individual entries for each host:
Host server1
Hostname server1.internal
ProxyCommand ssh gateway -W %h:%p
Host server2
Hostname server2.internal
ProxyCommand ssh gateway -W %h:%p
We can leverage pattern matching and variable substitution in SSH config:
Host *.internal
ProxyCommand ssh gateway -W $(echo %h | sed 's/.internal$//'):%p
User admin
IdentityFile ~/.ssh/gateway_key
For more complex naming schemes, consider these approaches:
# For hosts following pattern dev-XXX
Host dev-*
ProxyCommand ssh gateway -W $(echo %h | cut -d'-' -f2).dev.env:%p
# Using different environments
Host *.prod
ProxyCommand ssh prod-gateway -W %h:%p
Host *.stage
ProxyCommand ssh stage-gateway -W %h:%p
To keep your config manageable:
- Group related hosts with common patterns
- Document naming conventions in config comments
- Consider generating config snippets from inventory systems
When automating configurations:
# Restrict access to specific hosts
Host restricted-*
ProxyCommand ssh gateway -W $(echo %h | sed 's/restricted-//').secure:%p
User limited
IdentityFile ~/.ssh/restricted_key