1.建立SSH反向隧道链接:
A要控制B
A主机:外网,ip:123.123.123.123,sshd端口:2221
B主机:内网,sshd端口:2223
无论是外网主机A,还是内网主机B都需要跑ssh daemon
1.1.首先在B上执行
1 | $ ssh -NfR 1234:localhost:2223 user1@123.123.123.123 -p2221 |
这句话的意思是将A主机的1234端口和B主机的2223端口绑定,相当于远程端口映射(Remote Port Forwarding)。
这里每次需要输入A主机user1的登陆密码,后面会讲到解决办法。
1.2.这时在A主机上sshd会listen本地1234端口
1 2 3 | $ ss -ant State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 127.0.0.1:1234 *:* |
1.3.像平时一样连接到A主机的1234端口就可以控制内网B主机了
1 | $ ssh localhost -p1234 |
2.这种反向连接(Reverse Connection)不稳定,可能随时断开,需要内网主机B再次向外网A发起连接,将自动连接ssh的应用Autossh制作成daemon,每次开机自动运行,并且可以使用service进行开关控制。
在此之前还要解决之前的一个问题,那就是每次内网主机B连接外网主机A时都需要输入密码,这个问题ssh本身是提供另外一种验证方式——通过密钥验证用户身份,实现自动登录。
2.1.在内网B主机上生产公钥和私钥
1 2 3 4 | $ ssh-keygen ...(一直按Enter,最后在~/.ssh/下生成密钥) $ ls ~/.ssh/ id_rsa id_rsa.pub known_hosts |
2.2.复制B主机上生成的id_rsa.pub公钥到外网A主机上,并将内容加入到~/.ssh/authorized_keys
ssh-copy-id命令添加到远程主机的自动验证
1 | $ ssh-copy-id user1@123.123.123.123 |
2.3.制作Autossh的daemon
使用vim编辑,如果没有则新建
SysV:/etc/inid.d/autossh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | #!/bin/bash ### BEGIN INIT INFO # # Provides: location_server # Required-Start: $local_fs $remote_fs # Required-Stop: $local_fs $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: initscript # Description: This file should be used to construct scripts to be placed in /etc/init.d. # ### END INIT INFO ## Fill in name of program here. PROG="autossh" PROG_PATH="/usr/bin" ## Not need, but sometimes helpful (if $PROG resides in /opt for example). PROG_ARGS="-M 5678 -NR *:2222:127.0.0.1:8080 root@123.123.123.123 -p 22" PID_PATH="/var/run/" start() { if [ -e "$PID_PATH/$PROG.pid" ]; then ## Program is running, exit with error. echo "Error! $PROG is currently running!" 1>&2 exit 1 else ## Change from /dev/null to something like /var/log/$PROG if you want to save output. $PROG_PATH/$PROG $PROG_ARGS 2>&1 >/var/log/$PROG & $pid=`ps ax | grep -i 'location_server' | sed 's/^[0−9]{1,}.*/\1/g' | head -n 1` echo "$PROG started" echo $pid > "$PID_PATH/$PROG.pid" fi } stop() { echo "begin stop" if [ -e "$PID_PATH/$PROG.pid" ]; then ## Program is running, so stop it pid=`ps ax | grep -i 'location_server' | sed 's/^[0−9]{1,}.*/\1/g' | head -n 1` kill $pid rm -f "$PID_PATH/$PROG.pid" echo "$PROG stopped" else ## Program is not running, exit with error. echo "Error! $PROG not started!" 1>&2 exit 1 fi } ## Check to see if we are running as root first. ## Found at http://www.cyberciti.biz/tips/bash-root-user-check-script.html if [ "$(id -u)" != "0" ]; then echo "This script must be run as root" 1>&2 exit 1 fi case "$1" in start) start exit 0 ;; stop) stop exit 0 ;; reload|restart|force-reload) stop start exit 0 ;; **) echo "Usage: $0 {start|stop|reload}" 1>&2 exit 1 ;; esac |