SSH反向代理相关介绍(网上摘抄+修改)

问题提出

有时我们会碰到这样一个需求。在公司内部有一台可以上外网Linux主机(也可能为虚拟机,假设该机器命名为A)用于日常工作,其内网IP地址为192.168.1.A,该机器已经开了某些远程访问的服务,在同网段的下主机可以访问A。当我们在公司外面时需要远程访问该机器,有什么方法可以实现呢?

你可能想到通过VPN。远程登录到公司VPN,然后使用A的内网IP直接访问该机器,但是如果A主机所在的网络是公司内部网络的子网甚至是子网的子网,或者公司没有VPN服务器该怎么办呢?有没有其他更简单的方法呢?答案是肯定的。

其中一个简单的方法便是使用本文所要讲述的SSH反向代理方法。不过使用SSH反向代理的前提是在公司外部需要有一台具有公网IP的Linux主机,或者虽然没有公网IP,但是提供一个公网IP对外开放的端口转发,通过该端口可以直接访问到该台Linux主机,假设该台Linux主机命名为B。

网络环境描述

主机

IP

备注

A

192.168.1.A

公司内部主机,在局域网内,可以访问B

B

223.72.211.B

外部Linux主机,具有公网IP,不能直接访问A

在现实中,B机器可能是我们家里的电脑,通过宽带拨号上网从运营商获取临时的独立IP,或者是一台具有独立IP的VPS主机。

目标

从B机器能够访问A。

解决方案

使用SSH的远程转发功能,把A机器的指定端口PortA远程转发到B机器上的某个端口PortB,在B机器上访问PortB就相当于访问A机器的PortA。

环境需求

在B机器上需要安装SSH服务端,A机器上需要有SSH客户端。

实施步骤

在A机器上执行远程端口转发命令,其基本命令格式为:

ssh -R  [B机IP或*号或省略:]<PortB>:<A机IP>:<PortA> <B机用户名@B机公网IP> [-p B机ssh服务端口(默认22)]

这里假设要把A机23端口(Telnet服务器监听端口)转发到B机9022端口,实现在B机上通过Telnet命令登录到A机;假设B机用户名为root,ssh服务器端口号为8022。在A机上执行命令如下:

ssh –R 9022:127.0.0.1:23 root@223.72.211.B –p 8022

A机上执行上述命令时,会发现该过程跟通过ssh远程登录B机是一样的,要求输入root密码,完成后会登入B机shell。这时在B上执行netstat -an|grep 9022,会发现已经有进程在监听9022端口了,如图1.1所示。


图1.1 sshd进程监听9022端口

这时在B机执行telnet 127.0.0.1 9022,会发现能够通过Telnet远程登录A机了。

其他有用的参数:

-N Donotexecute a remote command.  This is useful for just forwarding ports (protocol version only).

-f  Requests ssh to goto background just before command execution.

在A机上退出上次的登陆,添加以上两个参数并再次执行:

ssh –NfR 9022:127.0.0.1:23 root@223.72.211.B –p 8022

输入B机密码后,会发现立刻返回A机shell。同时在B机上依然能够远程登录A机。

原理推测

首先整理下上面连接过程:在内网中的A机执行ssh反向连接命令,相当于把127.0.0.1:PortA远程映射到了B机的127.0.0.1:PortB,在B上连接127.0.0.1:PortB,其效果跟在A机内连接127.0.0.1:PortA是一样的。

考虑到NAT防火墙的存在,不可能在PortB和PortA之间又建立了一条连接,它们之间的数据传输应该还是通过ssh这条通路进行传递的,因此推断整个连接过程如下。

1)  A机:执行ssh反向连接命令,AB机之间建立ssh连接;A同时告诉B:你去监听localhost:PortB,把PortB上监听到的数据通过ssh通路传输给我

2)  B机:ssh服务端在收到上面指令后就去localhost:PortB上监听数据,如果有数据通过PortB传入(该数据是向localhost:PortB上发起连接的客户端数据,如上面例子中Telnet连接命令),B机便把这些数据打包成一个特征包,通过ssh连接发给A

3)  A机:ssh客户端接收到B机发来的特征包后,把该特征包转发到localhost:PortA,如果监听PortA的服务有回应,则把回应数据打包成特征包通过ssh通路发给B

4)  B机:ssh服务端收到A机传来的特征包后,把这些特征包返回给发起连接的客户端(Telnet客户端)

由此整个代理通路打通。

进阶1

考虑下面的需求。B是我们的某台服务器,现在已知我们可以在B机shell里面访问A机了,也就是要访问A机,必须首先登录到B机,然后在B机shell里执行登录命令才能访问A机。这样有点麻烦,我们能不能跳过登录B机,以B机作为跳板,在任意一台能上网的电脑上访问A机呢?或者情况是B机不带界面,但是转发的PortA是一个UI服务器的监听端口(比如3389端口,远程桌面),我们想在B机里登录A机的远程桌面是不可能的,因为B机不带界面;你可能想到我们能不能在一台联网的windows机器上通过远程桌面客户端使用 B机公网IP:PortB 地址远程登录A呢?以上答案是肯定的。

下面是ssh man page里对-R参数说明的摘抄。

-R  [bind_address:]port:host:hostport

... ...

Bydefault, the listening socket on the server will be boundto
the loopback interface only.  This may be overridden by
specifying a bind_address.  An empty bind_address, or the address
`*', indicates that the remote socket should listen on all
interfaces. Specifying a remote bind_address will only succeed
if the server's GatewayPorts option is enabled (sshd_config(5)).

通过上面的man page我们发现,默认情况下bind_address只是绑定到B机的loopback接口,也就是127.0.0.1地址,这就是上面我们在B机shell里为什么用127.0.0.1的地址来访问A。但是我们可以通过指定一个空的bind_address或者‘*’来绑定到B机的所有可用端口上,前提是需要配置B机的ssh服务器使能GatewayPorts

GatewayPorts应该是ssh服务的一个安全选项,如果使能该功能,ssh服务便能向ssh客户端指定的任意IP:Port监听/转发数据包。下面具体来实施。首先说明一下,我的B机所用Linux发行版为Debian,Ubuntu等基于Debian的发行版应该是一样的,其他发行版可能稍有不同。

  •  |配置sshd,打开GatewayPorts

vi /etc/ssh/sshd_config,在最后一行增加配置:GatewayPortsyes,完成后保存

  • |重启sshd服务

/etc/init.d/ssh restart

  • |防火墙允许PortB传入连接

B机ssh服务端监听B机公网IP的PortB,如果B机使能了防火墙,需要在该端口上允许数据传入。

做完上面步骤后,在A上执行:

ssh –NfR *:9022:127.0.0.1:23 root@223.72.211.B –p 8022

连接建立后,在任意一台能上网主机上执行telnet 223.72.211.B 9022,发现能够直接登录A机了。

上面PortA不只是23端口,可以是A上提供TCP服务的其他任意端口,如ssh服务(22)、web服务(80)、远程桌面服务(3389)等,假如A机提供远程桌面服务,在A上执行:

ssh –NfR *:9022:127.0.0.1:3389 root@223.72.211.B –p 8022

连接建立后,在任意一台能上网的windowas主机上打开远程桌面客户端,远程连接地址填写223.72.211.B:9022,便能连接A机远程桌面了。

进阶2

有时我们可能还有下面的需求。AB机都是Linux主机,但是跟A在同一局域网的C机是Windows主机(假设其IP地址为192.168.1.C),C提供远程桌面服务。现在我们能够通过B机远程连接A了,能不能通过B机、A机访问C机的远程桌面呢?答案也是肯定的。

在A上执行:

ssh –NfR *:9022:192.168.1.C:3389 root@223.72.211.B –p 8022

连接建立后,在任意一台能上网的windowas主机(假设为D)上打开远程桌面客户端,远程连接地址填写223.72.211.B:9022,便能连接C机远程桌面了。

该过程也很好理解:A机ssh客户端把从B机传来的远程桌面连接特征包转发到192.168.1.C:3389,C机远程桌面服务接收到连接请求后把回应返回给A,A再把回应包转给B,B把该包再回给远程桌面客户端便可以了,过程如下。

发起远程桌面连接:D机远程桌面客户端 -> B机IP:9022 -> B机ssh服务 -> A机ssh客户端 -> C机IP:3389 -> C机远程桌面服务

远程桌面服务回应:C机远程桌面服务 -> (A机IP:A机发起连接时随机端口) -> A机ssh客户端 -> B机ssh服务端 -> (D机连接时外网IP:NAT源端口号) -> D机远程桌面客户端。

上面过程,在C机看来,就是A机连接了C机远程桌面服务,C机并不知道有B机和D机的存在;从D机看,相当于搭建了一条到C机的隧道。

参考链接

ssh支持的端口转发类型不只远程转发(反向代理),还支持本地转发(正向代理)和动态转发。正向代理:把上面ssh命令行中的-R换成-L即可,把B机的PortB端口转发到A机的PortA端口。ssh端口转发参考参链接:

https://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/

不只Linux的ssh客户端(ssh也有Windows版本)支持端口转发,在Windows下的plink工具、Putty、SecureCRT和Xshell等都支持ssh端口转发功能。参考链接:http://blog.csdn.net/fgf00/article/details/51284335

ssh端口转发优点:对全程传输的数据进行加密,安全性高;支持传输数据压缩,提高传输效率。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值