我正在使用 Ubuntu Server 12.04 Minimal 设置一台无人值守的 Ubuntu PC,由于这台 PC 将被放置在没有键盘或屏幕(无人值守)的远程位置,所以我需要从这台机器到中间服务器(在它自己和我之间)建立永久的 SSH 连接 - 原因是,这台 PC 将位于 NAT 防火墙后面。
我按照点对点的指示 http://wiki.fabelier.org/index.php?title=Permanent_Reverse_SSH_Tunneling 但是当我连接时,我只收到一个错误 Quote: ssh: 连接到主机 5.175.145.251 端口 19999: 连接被拒绝 所以我回去谷歌搜索解决方案并发现 http://www.alexonlinux.com/reverse-ssh-tunnel-or-connecting-to-computer-behind-nat-router
令人惊讶的是,Alexonlinux 的解决方案开箱即用。
看到这种情况,我尝试了之前的方法,这次使用端口 6333,但没有成功。然后我尝试了 Alexonlinux 的方法,使用端口 19999,再次成功。
我不能坚持使用 Alexonlinux 的解决方案的原因是,它需要在 NAT 后面的 PC 上输入一些命令,而这对我来说是不可能的。
我真的很想知道使用 Fabelier 方法时是什么原因导致连接中断。可能是脚本没有加载?我确实尝试过手动运行脚本,但仍然没有成功。
我也设置了
GatewayPorts yes
在 NAT 后面的 PC 上。
为了记录,下面是我使用的 Fabalier 方法的脚本:
a=`ps -ef | grep 19999 | grep -v grep`
if [ ! "$a" ]; then
ssh -fN -R 19999:localhost:22 <middle-usename>@<middle-hostname>
fi
(显然我已将@更改为必要的)我不得不更改第一行,因为括号是不可接受的。
如果能得到帮助我将非常感谢。
答案1
我找到了其他人编写的这个预期脚本。它对我有用 - 我拥有其他公司拥有的防火墙和路由后面的远程/无人值守设备。我不想与他们合作通过端口转发将我的 ssh 端口暴露给世界以便我可以访问这些设备,而是希望能够使用反向 SSH。所以我建立了自己的小系统来解决这个问题。
服务器端运行基于 PHP 和 MySQL 的网站。我可以点击一个设备并转到其页面。我点击“反向 SSH”按钮,该按钮将命令“反向 SSH”与设备 ID 一起放入数据库中。
在客户端,我有一个通过 crontab 每分钟运行一次的 python 脚本。每次运行时,它都会通过 HTTP 向服务器报告系统健康信息、CPU 负载、内存、磁盘空间等。在该 HTTP 事务期间,如果命令正在等待签入的设备,我会将该命令发回。然后客户端匹配该命令,并执行对 bash 的调用“expect /path/to/client/reversessh.expect”。
expect 脚本已预先填充了我的服务器 ssh 信息(是的,我知道它“不安全”,但目前可以使用),并建立最长 1 小时的反向 SSH 连接(如果需要,您可以将其设置为更长)。然后我就可以从我所在的位置登录到远程设备。
我运行的服务器是 Ubuntu Server 14.04,远程设备范围从 beaglebone black 和虚拟服务器到台式电脑、RPi 和 RPi2。
在基于 debian 的系统上,我通过 apt-get 安装 expect:
apt-get 安装 expect
这是预期脚本,请根据需要进行修改。可能需要一点时间才能使其工作,但确实有效。我希望格式不会弄乱,很难复制和粘贴像这样的大代码块并使其正确显示:
示例 reversssh.expect
#!/usr/bin/expect -f
#Author: g0 2010 , kod.ipduh.com
#License:Same as Expect - Public Domain
#revtun sets up a reverse ssh tunnel
#ssh example: ssh -R 1025:localhost:22 -p 443 [email protected] -fN
#Hardcode the arguments or pass them at this order on the command line
#eg:$revtun 1025 22 443 user 192.0.2.123 password http://kod.ipduh.com
set remoteport "1234" # this is the port on your server that will serve the tunnel
set localport "22" # ssh port of remote/target device
set port "2222" # This is the port in which the remote device will ssh into your server. If you use standard port for ssh on server then it is, it's 22.
set user "" #ssh user on your server
set host "" # server host ie blah.com or 123.123.123.123
set password "" # user password for servers ssh user
set report_to "" # I never used this...see below line that starts with curl. In your web server php script do <?php print_r($_GET); ?>
if {$argc > 0} { set remoteport [lindex $argv 0] }
if {$argc > 1} { set localport [lindex $argv 1] }
if {$argc > 2} { set port [lindex $argv 2] }
if {$argc > 3} { set user [lindex $argv 3] }
if {$argc > 4} { set host [lindex $argv 4] }
if {$argc > 5} { set password [lindex $argv 5] }
if {$argc > 6} { set report_to [lindex $argv 6] }
set message "m"
set timeout 3600 # number of seconds to keep the tunnel open, this is set to 1 hour.
set pid [spawn ssh -N -R $remoteport:localhost:$localport $user@$host -p $port]
while {1} {
expect -nocase -re ".*yes/no?.*" {
send "yes\r"
} -nocase -re "password*" {
send -- "$password\r\n"
#send -- "\n"
} -re "(%|\\\$|#) " {
set message "$message-prompt"
break
} eof {
set message "$message-eof"
break
} -re "incorrect|invalid" {
set message "$message-incorrect"
break
} -nocase -re ".*Warning.*" {
set message "$message-warning"
break
} timeout {
set message "$message-timeout"
break
}
}
set user "$env(USER)"
exec curl $report_to?$user-$message --silent >/dev/null
#1 hour max connection time used to keep the script running
如果你想在它关闭时保持它运行,我会使用 cron 运行一个 bash 脚本来检查 sshd 程序是否正在运行,如果没有运行就启动它,否则什么也不做。如果你还有其他 SSH 连接正在进行,检查 sshd 可能对你不起作用。由于这个反向 SSH 脚本是远程设备上唯一的 SSH 活动,所以它对我来说是有效的。在我的系统中,我可以通过向远程设备发出另一个命令“断开反向 SSH”来终止设备上的反向 SSH 连接,当它登录时,这会导致客户端使用 bash 运行此命令:
kill `pidof sshd`
使用以下命令编辑你的 crontab:crontab -e
下面的 crontab 文件的前 6 行很好指定,您可能希望根据自己的喜好进行编辑。
示例 crontab
MAILTO="" # local mail address to get cron messages, leave blank to disable
SHELL=/bin/bash
USER=root # run these cron jobs as root user
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/root # root users home dir
LOGNAME=root
# Example check reverse SSH connection - runs every minute
* * * * * bash /path/to/check_reverse_ssh.bash
示例 check_reverse_ssh.bash
#!/bin/bash
process_id=`ps aux | grep "sshd" | grep -v "grep"`
if [ -z "$process_id" ]; then
echo "process not running for certain."
expect /path/to/reversessh.expect &
else
echo "sshd is running, If so, your tunnel should be good to go";
fi
祝你好运!