SSH端口转发与反向连接

SSH两个常用的功能:端口转发、反向连接,偶尔自己会傻傻分不清。

端口转发:

OpenSSH能够创建一个加密隧道,并在这个加密的会话中封装另一种协议。

下面的命令将告诉SSH在本地主机和远程主机建立一条加密隧道,并使得本机的8099端口的信息转发到本地主机SSH端口(发送过程依然如普通会话进行加密),远程主机会话端口(22)再转发至目标主机8080端口(响应则是相反)。示意图如上:

 

% ssh -2 -N -f -g -L 8099:localhost:8080 root@remotehost

这条SSH命令使用以下选项:

-2 –强制使用协议版本二,默认

-N –禁止执行任何远端程序(若是端口转发或反向连接需带有此选项,否则打开的只是普通SSH会话

-f –强制SSH后台运行,可选。-C 可启用压缩

-g –允许远程主机连接转发端口

-L –指明本地端口8099和远程转发端口8080,及远程地址

root@remotehost –为目标地址
上述的代码是通过端口转发,使得能够能够通过访问本地端口8089,实现访问远程主机的8080端口(假设在ECS上的Tomcat)的效果

反向连接:

  • 什么是反向连接?
    反向连接是主机A SSH主动连接主机B,在主机A和主机B之间建立一个远程连接(此时 A控制B),再通过这个连接主机B可以主动的向主机A发送一些请求,实现主机B控制 A。
  • 为什么需要主机A主动去连接主机B呢?
    这是因为主机A在局域网内,如果没有对主机A进行端口映射,对于主机B来说主机A是不可见的,如果在主机B这边向主机A发送连接请求,这个请求是不可达的。而主机B有自己独立的IP,对于主机A来说是可见的,可以直接向主机B请求连接。
  • SSH反向连接的过程
    方法就是主机A主动去连接主机B,主机B响应主机A的连接请求,它们之间就建立了一个远程连接。然后主机B在本地再创建一个本地连接,重定向到主机A和主机B刚才建立的远程连接上,之后对这个本地连接的操作都会反馈到远程连接上去。整个过程类似于文件的DUP,这就在主机A和主机B之间建立了连接通道,此时对于主机B来说,主
    机A已经是可见了。连接流程如下:
  • 主机A ssh客户端向主机B sshd服务端发送请求,建立远程连接。
  • 主机B sshd服务端创建本地连接到远程连接的映射(反向连接通道)。
  • 主机B ssh客户端向主机B sshd服务端的连接通道发送请求, 建立主机B ssh和主机A sshd的连接。完成连接后,主机A对于主机B可见的形式就是存在于主机B的那个本地连接。
  • 实例:*

本地主机A 在各种NAT环境下的局域网内,远程主机B 是具有公网IP的ECS

首先确保两台主机的SSH正常开启,22端口正常监听。

在本地主机A 中运行:

ssh -f -N -R 8099:localhost:22 root@remotehost

命令参数中的:

-R –指明远程主机对远程连接的本地连接映射端口8099

其他参数同上端口转发
之后在远程主机B 中运行(因本次实验机B 为ECS,故需新建一个SSH会话方可进入主机B ):

ssh localhost -p 8099

将远程主机B 连接到本地连接映射端口,输入本地主机A 密码即可通过B 控制A (又因实验机B 为ECS,此处还需建立一个SSH会话以监控 主机A B的情况)。

本地主机A 网络端口情况:

本地主机B 网络端口情况:

当前状态如下:A、B 间有三条SSH连接(多出的两条均因实验机B 的特殊情况),其中可以看到A、B 各自对远程连接进行了本地连接映射。

其中可能出现一个小问题:就是当反向连接以建立后(即B 已能成功控制A ),若是因通信故障等原因导致异常中断,则B 将无法在与A 建立连接,除非在重新回去操作A 连接B ,不过可以通过一个脚本来监控连接状态并自动重连(不过需要实现设置免密码SSH登录,具体设置参考 http://chenlb.iteye.com/blog/211809或在最下端下载脚本)。

#!/bin/bash
while true;do
RET=`ps aux | grep "ssh -f -N -R 8099:localhost:22" | grep -v "grep"`
if [ "$RET" = "" ]; then
echo "restart ssh server"
ssh -f -N -R 8099:localhost:22 root@remotehost
fi
sleep 10
done

 

参考资料:

觉得不错不妨打赏一笔