How to use SSH with PuTTY using a proxy server? <p>This is a journey that doesn't seem to have an end. Please bear with the story.</p> <p>I am wanting to write a variety of Perl programs that connect to an SSH server. The server is a Mac, the client is Windows behind an HTTP proxy. PuTTY works perfectly to connect, but executing the Perl scripts isn't ideal, for several reasons.</p> <p>I want to have an interactive (not with the user, but with the software running on the server) Perl program running on the client and the server, a la how rsync works with the -e option.</p> <p>First step, how do I connect? I use plink (from PuTTY), which has a variety of useful options... tunneling, running a series of commands, etc. From there, I can easily run commands and scripts on the server and get back the result, process the result, and then do the next command. But this is SLOW because it has to renegotiate the PuTTY/SSH connection each time. Hence the desire for an interactive approach.</p> <p>When running plink in this manner, I could interact with the plink command, but I'm having trouble with double-piping (input and output, never mind triple-piping to also get STDERR). I tried everything on <a href="http://docstore.mik.ua/orelly/perl2/prog/ch16_03.htm" rel="nofollow">http://docstore.mik.ua/orelly/perl2/prog/ch16_03.htm</a> and nothing worked. Got various errors, etc.</p> <p>Next I tried writing my own client/server programs using sockets. Worked pretty well, except for some reason each time I run the SocketServer on the server program and then connect to it (using plink to tunnel localhost to the server's port), the port closes itself off and refuses future connections. So I have to change the port every time, which seems counterproductive (probably an issue with my code, but I don't see it).</p> <p>The next step was trying Expect.pm. However, that seems to only work under Linux or CYGWIN, which I don't want to get too deep into. This needs to stay native Windows as much as possible.</p> <p>My latest is looking into Net::SSH::Perl and other SSH modules. I set up a port 22 tunnel with plink and then in CYGWIN I try:</p> <pre><code>ssh user@localhost </code></pre> <p>I enter my password and all is wonderful! Works like a champ!</p> <p>So then I try the following program (again, with the port 22 tunnel established)</p> <pre><code>use Net::SSH::Perl; my $ssh = Net::SSH::Perl-&gt;new('localhost'); $ssh-&gt;login('&lt;user&gt;','&lt;pass&gt;'); my($stdout, $stderr, $exit) = $ssh-&gt;cmd('ls -l'); while (&lt;$stdout&gt;) { print; } </code></pre> <p>(user and pass above are substituted for the real user and pass) I can see the plink tunnel opening the forwarded port, but the program returns</p> <pre><code>Permission denied at E:\Scripts\ExplorationScripts\NetSSHPerl.pl line 3 </code></pre> <p>So, this is where I am... I have many more SSH Perl modules to try, but I was wondering if anyone else had this situation. I see tons of people using PuTTY and SSH stuff, but none of them are going through a proxy (and thus NEED PuTTY). And I don't have the time or patience to mess with something like corkscrew, so please let's not go down that particular rabbit hole.</p> <p>I'm open for suggestions...</p> <p>Thanks.</p> <p>... continuing the journey... the new thing I've tried, and y'all will probably laugh at this bass-ackward solution... I tunneled port 23 through the Mac to a Windows machine on the same network running Telnet. Then, using Net::Telnet I am able to telnet to the Windows machine. Very awkward. I also wanted to be able to establish the tunnel and then kill it at the end of the program, so I added some oddball stuff. Check it out and PLEASE help me get a better solution to this.</p> <pre><code>use Net::Telnet; #establish tunnel open my $tunnel,"| plink -L 23:&lt;local IP of windows machine&gt;:23 &lt;server&gt; -pw &lt;pass&gt;"; sleep 7; #Now it's time to do the telnet boogie! my $t=new Net::Telnet ( Timeout=&gt;10, Errmode=&gt;'return',Prompt =&gt; '/&gt;$/'); #$t-&gt;output_log('telnet.log'); $t-&gt;input_log('telneti.log'); $t-&gt;open("localhost"); $t-&gt;login('&lt;user&gt;','&lt;pass&gt;'); @lines = $t-&gt;cmd("dir /b"); print @lines; $t-&gt;close(); print $tunnel "exit\n"; close $tunnel; </code></pre> <p>The $tunnel thing is the weirdness. plink will establish a terminal session, so I opened a handle to it's STDIN via the pipe. The -L establishes the tunnel. When I'm done with the telnetting, I print "exit" to plink which exits the bash session. I also use the "sleep 7" to give it enough time to establish the session. Ugh! But it seems to work moderately well.</p>