Here is my preferred solution to this problem. Set up a reverse ssh tunnel upon creating the ssh session. This is made easy by two bash function: grabfrom() needs to be defined on the local host, while grab() should be defined on the remote host. You can add any other ssh variables you use (e.g. -X or -Y) as you see fit.
function grabfrom() { ssh -R 2202:127.0.0.1:22 ${@}; };
function grab() { scp -P 2202 $@ [email protected]:~; };
Usage:
localhost% grabfrom remoteuser@remotehost
password: <remote password goes here>
remotehost% grab somefile1 somefile2 *.txt
password: <local password goes here>
Positives:
- It works without special software on either host beyond OpenSSH
- It works when local host is behind a NAT router
- It can be implemented as a pair of two one-line bash function
Negatives:
- It uses a fixed port number so:
- won't work with multiple connections to remote host
- might conflict with a process using that port on the remote host
- It requires localhost accept ssh connections
- It requires a special command on initiation the session
- It doesn't implicitly handle authentication to the localhost
- It doesn't allow one to specify the destination directory on localhost
- If you grab from multiple localhosts to the same remote host, ssh won't like the keys changing
Future work:
This is still pretty kludgy. Obviously, it would be possible to handle the authentication issue by setting up ssh keys appropriately and it's even easier to allow the specification of a remote directory by adding a parameter to grab()
More difficult is addressing the other negatives. It would be nice to pick a dynamic port but as far as I can tell there is no elegant way to pass that port to the shell on the remote host; As best as I can tell, OpenSSH doesn't allow you to set arbitrary environment variables on the remote host and bash can't take environment variables from a command line argument. Even if you could pick a dynamic port, there is no way to ensure it isn't used on the remote host without connecting first.