SSH Tunneling Through a Proxy Host (B) to Target Host (C) Using Private Key on Intermediate Server


3 views

When you need to access Host C through an intermediate Host B where the private key resides, you're dealing with a classic SSH jump host scenario. This setup is common in secure environments where direct access to production servers is restricted.

The modern approach uses the ProxyJump directive in your SSH config file. Here's how to set it up:

Host HostB
    HostName b.example.com
    User bridgeuser
    IdentityFile ~/.ssh/your_local_key

Host HostC
    HostName c.example.com
    User targetuser
    ProxyJump HostB
    ForwardAgent yes

If ProxyJump isn't available (OpenSSH < 7.3), you can use agent forwarding:

ssh -A -t user@HostB ssh user@HostC

Important: Only use this with trusted jump hosts as it exposes your local keys to the intermediate server.

For cases where you can't move the private key from Host B to your local machine:

ssh -J userB@HostB:port userC@HostC

Or with config:

Host HostC-via-B
    HostName HostC
    User userC
    ProxyCommand ssh -W %h:%p userB@HostB

Add these flags for troubleshooting:

ssh -vvv -J user@HostB user@HostC

Common pitfalls:

  • Ensure HostB can reach HostC
  • Verify the private key on HostB has proper permissions (600)
  • Check that AgentForwarding is enabled on HostB's sshd_config

Here's a complete working example for accessing a PostgreSQL server:

Host production-db-bastion
    HostName bastion.example.com
    User devops
    IdentityFile ~/.ssh/devops_key

Host production-db
    HostName db.internal.example.com
    User postgres
    ProxyJump production-db-bastion
    LocalForward 5432 localhost:5432

Usage: ssh production-db will tunnel through the bastion host and forward port 5432 locally.


When you need to SSH from machine A through intermediary B to target C, but the private key resides exclusively on B, traditional SSH forwarding won't work. This is particularly common in enterprise environments where security policies prevent key distribution.

Here's how to configure ~/.ssh/config for this scenario:

Host intermediate-b
    HostName b.example.com
    User proxyuser
    IdentityFile ~/.ssh/id_rsa_local_to_b

Host target-c-via-b
    HostName c.internal
    User targetuser
    ProxyCommand ssh -W %h:%p intermediate-b
    IdentityFile /home/proxyuser/.ssh/id_rsa_b_to_c

For more control, execute sequential SSH commands:

ssh -t b.example.com "ssh -i ~/.ssh/id_rsa_b_to_c targetuser@c.internal"
  • Ensure ssh-agent forwarding isn't used (security risk)
  • Verify B has network access to C
  • The private key on B should have 600 permissions

If connection fails, debug with:

ssh -vvv intermediate-b

Then verify the proxy can reach C:

ssh intermediate-b "nc -zv c.internal 22"