How to use putty (and/or plink) command line to forward through 2 intermediate hosts to a database

port-forwardingputty

I need to write a script for some co-workers to connect over the following topology, using a private key for authentication (the same key for each person works on both bastion and db access):

 ┌────────────┐    ┌────────────┐     ┌────────────┐     ┌────────────┐
 │            │    │            │     │            │     │            │
 │  desktop   │───>│  bastion   │────>│  db access │────>│  db 3306   │
 │  (windows) │    │  (linux)   │     │  (linux)   │     │  (mysql)   │
 └────────────┘    └────────────┘     └────────────┘     └────────────┘

My co-workers will then use this connection in a desktop db query tool.

To make this as easy to deploy as possible, I want to specify all the configuration on the command line without referring to any saved session data configured in the Putty UI. I have .ppk files for the private keys that the script can refer to.

What is the (probably very lengthy) putty and/or plink command line that will enable this?

From my interpretation of the manual, I've tried this:

plink -ssh -2  -i C:\temp\key.ppk -agent -A -t -l user -L 6035:127.0.0.1:6035 user@BASTION ssh -v -L 6035:DBHOST:3306 user@DBACCESS

That gets me to the bastion, but it then looks for a private key on the bastion to make the connection to db access.

I am able to connect to it with ssh from my Mac (code shown below), so I know that the current configuration of the boxes permits this kind of access. I am looking for a putty/plink solution for use for access from windows boxes.

ssh -v -A -t \
-L ${LOCAL_PORT}:localhost:${LOCAL_PORT} ${USER}@${BASTION_HOST} \
-t ssh -v -L ${LOCAL_PORT}:${DB_HOST}:${DB_PORT} ${USER}@${DB_ACCESS_HOST}

Best Answer

With the release of PuTTY 0.68 plink got a new command line option called -proxycmd. Using this new functionality yields a more robust less cluttered solution to the problem IMHO.

Unfortunately there is not much help for the -proxycmd option. It does execute a local command and uses it as a proxy. One can use even plink with the -nc option to create a tunnel up to the db access host.

For your topology the command executed on desktop machines this on the command prompt looks like this:

plink -A ^
  -proxycmd "plink -A -nc DBACCESS:22 user@BASTION" ^
  -L 6035:DBHOST:3306 ^
  user@DBACCESS

Note: For a password less login peagent must be running on the desktop host and have the appropriate keys loaded. As already mentioned in the comments, agent forwarding must be enabled on the bastion hosts to make it work seamlessly.

The connection looks like the ASCII art below. An outer tunnel goes up to the host db access via the proxy command. Encapsulated in the tunnel runs plink and establishes the port forward to the db host.

 ┌────────────┐    ┌────────────┐    ┌────────────┐    ┌────────────┐
 │            │    │            │    │            │    │            │
 │            ─────────────────────────────       │    │            │
 │                      (1)                       │    │            │  
 │           ────────────────────────────────────────────           │
 │                      (2)                                         │
 │           ────────────────────────────────────────────           │
 │            ─────────────────────────────       │    │            │
 │  desktop   │    │  bastion   │    │  db access │    │  db 3306   │
 │  (windows) │    │  (linux)   │    │  (linux)   │    │  (mysql)   │
 └────────────┘    └────────────┘    └────────────┘    └────────────┘

 1) Tunnel via `-proxycmd "plink -A -nc DBACCESS:22 user@BASTION"`
 2) Proxied `plink` connection with port forward `-L 6035:DBHOST:3306`