How to Dynamically Parse SSH Hostnames and Use Variables in SSH Config


2 views

When managing multiple identical datacenter environments, maintaining separate SSH config entries for each server behind jumpboxes becomes tedious. The only difference between environments is typically the jumpbox IP or hostname.

SSH's configuration file supports pattern matching in Host declarations, allowing you to extract parts of the hostname as variables. Here's how it works:

Host *-*
    HostName %h
    User your_username
    ProxyCommand ssh -W $(echo %h | cut -d'-' -f2-):%p $(echo %h | cut -d'-' -f1)

Let's implement a full solution for connecting to database servers behind jumpboxes:

# Jumpbox definitions
Host dc1
    HostName jumpbox1.example.com
    User admin

Host dc2
    HostName jumpbox2.example.com
    User admin

# Dynamic backend server access
Host *-*
    ProxyCommand ssh -q -W $(echo %h | sed 's/^[^-]*-//'):%p $(echo %h | cut -d- -f1)
    ServerAliveInterval 60
    TCPKeepAlive yes

# Specific server configurations
Host *-db
    User dbadmin
    Port 5432

Host *-redis
    User redisuser
    Port 6379

The key components in our solution:

  • *-* pattern matches any host with a hyphen
  • $(echo %h | cut -d'-' -f1) extracts the datacenter prefix
  • $(echo %h | sed 's/^[^-]*-//') removes the datacenter prefix

For more complex environments with multiple segments:

Host *-*-*
    ProxyCommand ssh -W $(echo %h | cut -d'-' -f3-):%p $(echo %h | cut -d'-' -f1)-$(echo %h | cut -d'-' -f2)

This would handle patterns like region1-dc1-mysql where you need to extract both region and datacenter.

When using this approach:

  • Ensure proper permissions on your SSH config file (chmod 600 ~/.ssh/config)
  • Use SSH keys with limited permissions for jumpbox access
  • Consider adding IdentitiesOnly yes to prevent unintended key usage

If connections fail:

  1. Test with -v flag: ssh -v dc1-mysql
  2. Verify the extracted components with: echo %h | cut -d'-' -f1
  3. Check jumpbox connectivity separately

Managing SSH connections across multiple identical datacenter environments often leads to bloated configuration files. When you have dozens of servers behind jump hosts in different locations, maintaining separate entries for each combination becomes tedious and error-prone.

OpenSSH's configuration file supports powerful pattern matching that most administrators underutilize. The % wildcard can capture parts of hostnames and reuse them in other directives:

Host *-servertype
    HostName internal-server
    ProxyCommand ssh -W %h:%p $(echo %h | cut -d'-' -f1)

Here's a complete solution for your multi-datacenter scenario:

# Base jumpbox configurations
Host datacenter1
    HostName 203.0.113.1
    User admin
    IdentityFile ~/.ssh/dc1_key

Host datacenter2
    HostName 203.0.113.2
    User admin
    IdentityFile ~/.ssh/dc2_key

# Dynamic backend server access
Host *-*
    ProxyCommand ssh -W $(echo %h | awk -F'-' '{print $2}':%p $(echo %h | awk -F'-' '{print $1}')
    User appuser
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null

# Specific service templates
Host *-db
    Port 3306

Host *-redis
    Port 6379

For more complex scenarios, you can create wrapper scripts:

Host *-*
    ProxyCommand bash -c 'dc=${1%%-*}; target=${1#*-}; ssh -W ${target}:%p $dc' - %h

While this approach is convenient, consider these security measures:

  • Use StrictHostKeyChecking appropriately
  • Limit SSH agent forwarding
  • Implement jump host authentication separately

With this configuration, you can now connect using intuitive commands:

ssh datacenter1-db  # Connects to database via datacenter1 jumpbox
ssh datacenter2-redis  # Connects to Redis via datacenter2 jumpbox