<p>When connecting to remote hosts via ssh, I frequently want to bring a file on that system to the local system for viewing or processing.  Is there a way to copy the file over without (a) opening a new terminal/pausing the ssh session (b) authenticating again to either the local or remote hosts which works (c) even when one or both of the hosts is behind a NAT router?</p>

<p>The goal is to take advantage of as much of the current state as possible: that there is a connection between the two machines, that I'm authenticated on both, that I'm in the working directory of the file---so I don't have to open another terminal and copy and paste the remote host and path in, which is what I do now. The best solution also wouldn't require any setup before the session began, but if the setup was a one-time or able to be automated, than that's perfectly acceptable.  </p>

[{'answer_id': 49913, 'author': 'chris', 'author_id': 4782, 'author_profile': 'https://Stackoverflow.com/users/4782', 'pm_score': -1, 'selected': False, 'text': "<p>You should be able to set up public &amp; private keys so that no auth is needed. </p>\n\n<p>Which way you do it depends on security requirements, etc (be aware that there are linux/unix ssh worms which will look at keys to find other hosts they can attack).</p>\n\n<p>I do this all the time from behind both linksys and dlink routers. I think you may need to change a couple of settings but it's not a big deal.</p>\n"}, {'answer_id': 49945, 'author': 'Ryan Ahearn', 'author_id': 75, 'author_profile': 'https://Stackoverflow.com/users/75', 'pm_score': 0, 'selected': False, 'text': '<p>In order to do this I have my home router set up to forward port 22 back to my home machine (which is firewalled to only accept ssh connections from my work machine) and I also have an account set up with <a href="http://www.dyndns.com" rel="nofollow noreferrer">DynDNS</a> to provide Dynamic DNS that will resolve to my home IP automatically.</p>\n\n<p>Then when I ssh into my work computer, the first thing I do is run a script that starts an ssh-agent (if your server doesn\'t do that automatically).  The script I run is:</p>\n\n<pre><code>#!/bin/bash\n\nssh-agent sh -c \'ssh-add &lt; /dev/null &amp;&amp; bash\'\n</code></pre>\n\n<p>It asks for my ssh key passphrase so that I don\'t have to type it in every time.  You don\'t need that step if you use an ssh key without a passphrase.</p>\n\n<p>For the rest of the session, sending files back to your home machine is as simple as</p>\n\n<pre><code>scp file_to_send.txt your.domain.name:~/\n</code></pre>\n'}, {'answer_id': 49946, 'author': 'Nick', 'author_id': 5222, 'author_profile': 'https://Stackoverflow.com/users/5222', 'pm_score': 0, 'selected': False, 'text': '<p>Here is a <a href="http://matt.ucc.asn.au/ssh-xfer/" rel="nofollow noreferrer">hack called ssh-xfer</a> which addresses the exact problem, but requires patching OpenSSH, which is a nonstarter as far as I\'m concerned.</p>\n'}, {'answer_id': 49956, 'author': 'Eric Hogue', 'author_id': 4137, 'author_profile': 'https://Stackoverflow.com/users/4137', 'pm_score': 2, 'selected': False, 'text': "<p>On a linux box I use the ssh-agent and sshfs. You need to setup the sshd to accept connections with key pairs. Then you use ssh-add to add you key to the ssh-agent so you don't have type your password everytime. Be sure to use -t seconds, so the key doesn't stay loaded forever. <br />\nssh-add -t 3600 /home/user/.ssh/ssh_dsa <br /></p>\n\n<p>After that, <br />\nsshfs hostname:/ /PathToMountTo/ <br />\nwill mount the server file system on your machine so you have access to it. </p>\n\n<p>Personally, I wrote a small bash script that add my key and mount the servers I use the most, so when I start to work I just have to launch the script and type my passphrase. </p>\n"}, {'answer_id': 49976, 'author': 'Antti Kissaniemi', 'author_id': 2948, 'author_profile': 'https://Stackoverflow.com/users/2948', 'pm_score': 3, 'selected': False, 'text': '<p><a href="http://zssh.sourceforge.net/" rel="noreferrer">zssh</a> (a <a href="http://en.wikipedia.org/wiki/ZMODEM" rel="noreferrer">ZMODEM</a> wrapper over openssh) does exactly what you want.</p>\n\n<ul>\n<li><p>Install <a href="http://zssh.sourceforge.net/" rel="noreferrer">zssh</a> and use it instead of openssh (which I assume that you normally use)</p></li>\n<li><p>You\'ll have to have the <a href="http://www.ohse.de/uwe/software/lrzsz.html" rel="noreferrer">lrzsz</a> package installed on both systems.</p></li>\n</ul>\n\n<p>Then, to transfer a file <code>zyxel.png</code> from remote to local host:</p>\n\n<pre><code>antti@local:~$ zssh remote\nPress ^@ (C-Space) to enter file transfer mode, then ? for help\n...\nantti@remote:~$ sz zyxel.png\n**B00000000000000\n^@\nzssh &gt; rz\nReceiving: zyxel.png\nBytes received:  104036/ 104036   BPS:16059729\n\nTransfer complete\nantti@remote:~$ \n</code></pre>\n\n<p>Uploading goes similarly, except that you just switch <a href="http://linux.die.net/man/1/rz" rel="noreferrer">rz(1)</a> and <a href="http://linux.die.net/man/1/sz" rel="noreferrer">sz(1)</a>.</p>\n\n<p>Putty users can try <a href="http://leputty.sourceforge.net/" rel="noreferrer">Le Putty</a>, which has similar functionality.</p>\n'}, {'answer_id': 49993, 'author': 'Polsonby', 'author_id': 137, 'author_profile': 'https://Stackoverflow.com/users/137', 'pm_score': -1, 'selected': False, 'text': '<p><a href="https://stackoverflow.com/questions/49896/which-is-the-best-way-to-bring-a-file-from-a-remote-host-to-local-host-over-an#49901">Use the -M switch.</a></p>\n\n<blockquote>\n  <blockquote>\n    <p>"Places the ssh client into \'master\' mode for connection shar-ing.  Multiple -M options places ssh into ``master\'\' mode with confirmation required before slave connections are accepted.  Refer to the description of ControlMaster in ssh_config(5) for details."</p>\n  </blockquote>\n</blockquote>\n\n<p>I don\'t quite see how that answers the OP\'s question - can you expand on this a bit, David?</p>\n'}, {'answer_id': 74866, 'author': 'Nick', 'author_id': 5222, 'author_profile': 'https://Stackoverflow.com/users/5222', 'pm_score': 1, 'selected': True, 'text': "<p>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.</p>\n\n<pre><code>function grabfrom() { ssh -R 2202:127.0.0.1:22 ${@}; };\nfunction grab() { scp -P 2202 $@ localuser@127.0.0.1:~; };\n</code></pre>\n\n<p>Usage:</p>\n\n<pre><code>localhost% grabfrom remoteuser@remotehost\npassword: &lt;remote password goes here&gt;\nremotehost% grab somefile1 somefile2 *.txt\npassword: &lt;local password goes here&gt;\n</code></pre>\n\n<p>Positives:</p>\n\n<ul>\n<li>It works without special software on either host beyond OpenSSH</li>\n<li>It works when local host is behind a NAT router</li>\n<li>It can be implemented as a pair of two one-line bash function</li>\n</ul>\n\n<p>Negatives:</p>\n\n<ul>\n<li>It uses a fixed port number so:\n\n<ul>\n<li>won't work with multiple connections to remote host</li>\n<li>might conflict with a process using that port on the remote host</li>\n</ul></li>\n<li>It requires localhost accept ssh connections</li>\n<li>It requires a special command on initiation the session</li>\n<li>It doesn't implicitly handle authentication to the localhost</li>\n<li>It doesn't allow one to specify the destination directory on localhost</li>\n<li>If you grab from multiple localhosts to the same remote host, ssh won't like the keys changing</li>\n</ul>\n\n<p>Future work:\nThis 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()</p>\n\n<p>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.</p>\n"}, {'answer_id': 6173790, 'author': 'Kenyon', 'author_id': 124703, 'author_profile': 'https://Stackoverflow.com/users/124703', 'pm_score': 1, 'selected': False, 'text': '<p>Using ControlMaster (the -M switch) is the best solution, way simpler and easier than the rest of the answers here. It allows you to share a single connection among multiple sessions. Sounds like it does what the poster wants. You still have to type the scp or sftp command line though. Try it. I use it for all of my sshing.</p>\n'}, {'answer_id': 8415063, 'author': 'aculich', 'author_id': 462302, 'author_profile': 'https://Stackoverflow.com/users/462302', 'pm_score': 2, 'selected': False, 'text': '<p>Using some little known and rarely used features of the openssh\nimplementation you can accomplish precisely what you want!</p>\n\n<ul>\n<li>takes advantage of the current state</li>\n<li>can use the working directory where you are</li>\n<li>does not require any tunneling setup before the session begins</li>\n<li>does not require opening a separate terminal or connection</li>\n<li>can be used as a one-time deal in an interactive session or can be used as part of an automated session</li>\n</ul>\n\n<p>You should only type what is at each of the <code>local&gt;</code>, <code>remote&gt;</code>, and\n<code>ssh&gt;</code> prompts in the examples below.</p>\n\n<pre><code>local&gt; ssh username@remote\nremote&gt; ~C\nssh&gt; -L6666:localhost:6666\nremote&gt; nc -l 6666 &lt; /etc/passwd\nremote&gt; ~^Z\n[suspend ssh]\n[1]+  Stopped                 ssh username@remote\nlocal&gt; (sleep 1; nc localhost 6666 &gt; /tmp/file) &amp; fg\n[2] 17357\nssh username@remote\nremote&gt; exit\n[2]-  Done                    ( sleep 1; nc localhost 6666 &gt; /tmp/file )\nlocal&gt; cat /tmp/file\nroot:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\n...\n</code></pre>\n\n<p>Or, more often you want to go the other direction, for example if you\nwant to do something like transfer your <code>~/.ssh/id_rsa.pub</code> file from\nyour local machine to the <code>~/.ssh/authorized_keys</code> file of the remote\nmachine.</p>\n\n<pre><code>local&gt; ssh username@remote\nremote&gt; ~C\nssh&gt; -R5555:localhost:5555\nremote&gt; ~^Z\n[suspend ssh]\n[1]+  Stopped                 ssh username@remote\nlocal&gt; nc -l 5555 &lt; ~/.ssh/id_rsa.pub &amp;\n[2] 26607\nlocal&gt; fg\nssh username@remote\nremote&gt; nc localhost 5555 &gt;&gt; ~/.ssh/authorized_keys\nremote&gt; cat ~/.ssh/authorized_keys\nssh-rsa AAAAB3NzaC1yc2ZQQQQBIwAAAQEAsgaVp8mnWVvpGKhfgwHTuOObyfYSe8iFvksH6BGWfMgy8poM2+5sTL6FHI7k0MXmfd7p4rzOL2R4q9yjG+Hl2PShjkjAVb32Ss5ZZ3BxHpk30+0HackAHVqPEJERvZvqC3W2s4aKU7ae4WaG1OqZHI1dGiJPJ1IgFF5bWbQl8CP9kZNAHg0NJZUCnJ73udZRYEWm5MEdTIz0+Q5tClzxvXtV4lZBo36Jo4vijKVEJ06MZu+e2WnCOqsfdayY7laiT0t/UsulLNJ1wT+Euejl+3Vft7N1/nWptJn3c4y83c4oHIrsLDTIiVvPjAj5JTkyH1EA2pIOxsKOjmg2Maz7Pw== username@local\n</code></pre>\n\n<p>A little bit of explanation is in order.</p>\n\n<p>The first step is to open a <code>LocalForward</code>; if you don\'t already have\none established then you can use the <code>~C</code> escape character to open an\nssh command line which will give you the following commands:</p>\n\n<pre><code>remote&gt; ~C\nssh&gt; help\nCommands:\n      -L[bind_address:]port:host:hostport    Request local forward\n      -R[bind_address:]port:host:hostport    Request remote forward\n      -D[bind_address:]port                  Request dynamic forward\n      -KR[bind_address:]port                 Cancel remote forward\n</code></pre>\n\n<p>In this example I establish a <code>LocalForward</code> on port 6666 of localhost\nfor both the client and the server; the port number can be any\narbitrary open port.</p>\n\n<p>The <code>nc</code> command is from the <code>netcat</code> package; it is described as the\n"TCP/IP swiss army knife"; it is a simple, yet very flexible and\nuseful program. Make it a standard part of your unix toolbelt.</p>\n\n<p>At this point <code>nc</code> is listening on port 6666 and waiting for another\nprogram to connect to that port so it can send the contents of\n<code>/etc/passwd</code>.</p>\n\n<p>Next we make use of another escape character <code>~^Z</code> which is <code>tilde</code>\nfollowed by <code>control-Z</code>. This temporarily suspends the ssh process and\ndrops us back into our shell.</p>\n\n<p>One back on the local system you can use <code>nc</code> to connect to the\nforwarded port 6666. Note the lack of a <code>-l</code> in this case because that\noption tells <code>nc</code> to listen on a port as if it were a server which is\nnot what we want; instead we want to just use <code>nc</code> as a client to\nconnect to the already listening <code>nc</code> on the remote side.</p>\n\n<p>The rest of the magic around the <code>nc</code> command is required because if\nyou recall above I said that the <code>ssh</code> process was temporarily\nsuspended, so the <code>&amp;</code> will put the whole <code>(sleep + nc)</code> expression\ninto the background and the <code>sleep</code> gives you enough time for ssh to\nreturn to the foreground with <code>fg</code>.</p>\n\n<p>In the second example the idea is basically the same except we set up\na tunnel going the other direction using <code>-R</code> instead of <code>-L</code> so that\nwe establish a <code>RemoteForward</code>. And then on the local side is where\nyou want to use the <code>-l</code> argument to <code>nc</code>.</p>\n\n<p>The escape character by default is ~ but you can change that with:</p>\n\n<pre><code> -e escape_char\n         Sets the escape character for sessions with a pty (default: ‘~’).  The escape character is only recognized at the beginning of a line.  The escape character followed by a dot\n         (‘.’) closes the connection; followed by control-Z suspends the connection; and followed by itself sends the escape character once.  Setting the character to “none” disables any\n         escapes and makes the session fully transparent.\n</code></pre>\n\n<p>A full explanation of the commands available with the escape characters is available in the <a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh&amp;sektion=1#ESCAPE%20CHARACTERS" rel="nofollow">ssh manpage</a></p>\n\n<pre><code>ESCAPE CHARACTERS\n     When a pseudo-terminal has been requested, ssh supports a number of functions through the use of an escape character.\n\n     A single tilde character can be sent as ~~ or by following the tilde by a character other than those described below.  The escape character must always follow a newline to be interpreted\n     as special.  The escape character can be changed in configuration files using the EscapeChar configuration directive or on the command line by the -e option.\n\n     The supported escapes (assuming the default ‘~’) are:\n\n     ~.      Disconnect.\n\n     ~^Z     Background ssh.\n\n     ~#      List forwarded connections.\n\n     ~&amp;      Background ssh at logout when waiting for forwarded connection / X11 sessions to terminate.\n\n     ~?      Display a list of escape characters.\n\n     ~B      Send a BREAK to the remote system (only useful for SSH protocol version 2 and if the peer supports it).\n\n     ~C      Open command line.  Currently this allows the addition of port forwardings using the -L, -R and -D options (see above).  It also allows the cancellation of existing remote port-\n             forwardings using -KR[bind_address:]port.  !command allows the user to execute a local command if the PermitLocalCommand option is enabled in ssh_config(5).  Basic help is avail‐\n             able, using the -h option.\n\n     ~R      Request rekeying of the connection (only useful for SSH protocol version 2 and if the peer supports it).\n</code></pre>\n'}, {'answer_id': 22710075, 'author': 'user3350771', 'author_id': 3350771, 'author_profile': 'https://Stackoverflow.com/users/3350771', 'pm_score': 0, 'selected': False, 'text': '<p>You can use SCP protocol for tranfering a file.you can refer this link</p>\n\n<p><a href="http://tekheez.biz/scp-protocol-in-unix/" rel="nofollow">http://tekheez.biz/scp-protocol-in-unix/</a></p>\n'}, {'answer_id': 61432784, 'author': 'Googlian', 'author_id': 5380942, 'author_profile': 'https://Stackoverflow.com/users/5380942', 'pm_score': 0, 'selected': False, 'text': '<p>The best way to use this you can expose your files over HTTP and download it from another server, you can achieve this using <code>ZSSH</code> Python library,</p>\n\n<p><strong>ZSSH</strong> - ZIP over SSH (Simple Python script to exchange files between servers). </p>\n\n<p>Install it using PIP.</p>\n\n<pre><code>python3 -m pip install zssh\n</code></pre>\n\n<p>Run this command from your remote server.</p>\n\n<pre><code>python3 -m zssh -as --path /desktop/path_to_expose\n</code></pre>\n\n<p>It will give you an URL to execute from another server.</p>\n\n<p>In the local system or another server where you need to download those files and extract.</p>\n\n<pre><code>python3 -m zssh -ad --path /desktop/path_to_download --zip http://example.com/temp_file.zip\n</code></pre>\n\n<p>For more about this library: <a href="https://pypi.org/project/zssh/" rel="nofollow noreferrer">https://pypi.org/project/zssh/</a></p>\n'}]
['https://Stackoverflow.com/questions/49896', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/5222/']