【linux】建立ssh隧道端口转发大穿越

应用场景:

运维工作中在执行远程维护或测试时,往往只开通了一条远程通道,并加以访问限制,然后通过单一跳转机访问其它服务器和服务,如此我们如何通过一台中间服务器,供多人访问很多资源呢?

有时我们需要在家里临时完成某些工作,如何通过公司的某台电脑,访问公司内部众多资源呢?

公司不让我们上网,限制某些应用服务或端口,我们如何通过外部某台服务器突破封锁实现内网穿透呢?

以上各种情况,可能你有这样那样的方法,vpn、专线、堡垒机等这些都没有毛病,但是今天博主要分享的是:

基于linux系统下的ssh隧道技术,加密连接协议端口转发大穿越的实现!

®ssh隧道具体配置操作步骤:


首先我们来看左边这张图,a是自己办公中员工机;b是公司的网络防线,防火墙、上网行为管理、入侵检测IDS、安全防护IPS、VPN等硬件级网络设备;c是外部托管的一台web服务器;d是自己家中或在外时使用的某台服务器;e则是公司内部的某台服务器;

如此我们通过这一套拓扑来一一模拟不同情况下关于ssh隧道的配置:

``````

没做之前我们先规划确定一下网络架构:

  • 简单点,a和e都在公司内部局域网下,a的ip为“192.168.1.101”e的ip为“192.168.1.102”
  • 如此办公网络网关即b的ip为“192.168.1.1”、并通过公网ip“124.207.1.1”做snat统一对外访问互联网;
  • d主机待定确切位置,可能在家、在宾馆、餐厅、或分公司某台pc;
  • c则是公司托管服务器中的某台web服务器:snat“124.207.2.1”dnat“124.207.2.2”;
    注意

    snat表示做的源地址nat转换,ip为内部服务器访问互联网时使用的公网ip;

    dnat表示目标地址nat转换,一般是目标地址端口转换,为的是开放内部某个服务,供外部互联网的pc访问其资源,ip即外部访问其资源访问的ip;

①、在“d”上通过中间服务器“e”,来访问c网站服务器的ftp服务,即21端口;

说明:web服务器“c”没有完全对外开放ftp服务,只做了两条dnat,开放了ssh的22端口对应124.207.2.2的19022端口,以及ftp的21端口对应124.207.2.2的19021端口,并只允许公司的124.207.1.1这个ip可以访问;如此“d”是家里的一台pc,也想要访问“c”服务器上的ftp服务,则我们可以通过在“d”pc上创建经中间服务器的ssh隧道;当然“e”需要是一台linux服务器,我们可要有访问“e”的ssh权限,这个不难,公司网络里开放一个,这个权限还是应该有的,如,dnat:124.207.1.2的18022对应192.168.1.102的22端口:

(然后我们就可以在“d”pc上,执行操作,分为两种)

(“d”是一台linux操作系统,直接执行命令)

ssh -p 18022 -N -f -g -C -L 2121:124.207.2.2:19021 124.207.1.2

(“d”是一台windows操作系统时,需要借助ssh客户端,如xshell或putty)

如使用xshell,要先使用其工具ssh登陆到“e”服务器上:ssh 124.207.1.2 18022

登陆之后,点击顶层工具菜单中的“查看”,下拉选中“隧道窗格”打开隧道窗口,一般位于终端区域的下方;

点击“转移规则”选项页,右击选中“添加”按钮,打开“转移规则”窗口;

依次输入:“类型”选择local(outg0ing)、“源主机”选择localhost、“侦听端口”则为本地某个端口如上面的2121端口、“仅接受本地连接”不打勾、“目标主机”则是“124.207.2.2”、“目标端口”则是19021

如此我们就可以在“d”上通过访问本地的2121端口,实际上访问了“c”的ftp服务;

注意

上面ssh命令:-p是指定ssh端口,为的是远程目标ssh服务端口不是默认22的情况下使用,如本案例就是用的18022端口;

-N是为了告诉ssh客户端,这个链接不需要执行任何命令,仅仅用来做端口转发;

-f则是告诉ssh客户端,在后台运行,不会进入中间服务器系统终端;

-g则允许远程主机连接到本地转发端口,和xshell“隧道转移规则”中的“仅接受本地连接”不打勾一个意思;即参数GatewayPorts=yes;

-C、表示压缩数据传输;

-L,则表示做的本地端口映射,意思也就是,把本地的某个端口,通过中间服务器,映射到中间服务器能够访问的某个服务器的ip和服务端口;

  • 格式用“:”隔开,依次是:
  • 需要访问的本地端口,如2121;
  • 需要访问的目标机器的ip地址,如这里的124.207.2.2;
  • 需要访问的目标机器的端口,如这里的19021;

值得注意的是,这里映射到本地的端口不要已被使用占用的端口,否则不生效;

上面说的xhsell的隧道方法,包括putty客户端也有,使用的原理都是这个理;

②、我在家“d”主机上,通过中间服务器“e”,访问公司办公pc“a”:

很多时候,为了安全考虑,windows的远程桌面一般不给予对外开放,linux的ssh则较安全一些,所以有这么一个需求,在外访问公司内部的windows服务器,如公司自己的办公pc,我可以通过中间服务器“e”来做建立ssh隧道:

ssh -p 18022 -CfNg -L 18038:192.168.1.101:3389 root@124.207.1.2

如此便可在“d”上通过mstsc,链接“127.0.0.1:18038”从而远程“a”;

注意

这里的远程ip,填写的是“192.168.1.101”是内网ip而不是案例①中的外网ip;

这里我们填写的目标ip,是以中间服务器为基准,能够直接访问到目标主机的ip,其实也就是说我们是通过中间服务器访问的目标主机;

案例①中,我们通过“e”访问“d”的ftp,而“e”直接访问“d”是访问公网ip“124.207.2.2:19021”;案例②中,“e"访问“a”,两个是在同一局域网,所以是“192.168.1.101:3389";

当然我们同样可以通过xshell的方法创建ssh隧道链接;

③、在“a”上通过中间服务器"d"配置隧道穿透内网访问“c”的web服务:

特殊情况下,公司内部限制了访问外部web网站,这时如果我们有一台外部的linux服务器“d”,则可通过它来穿透内网限制访问外部web资源;

(当然前提是我们能够通过ssh远程“d”,如“124.207.3.2:16922”

ssh -p 16922 -CfNg -L 16980:124.207.2.2:80 124.207.3.2

如此我们可以在“a”上,访问本地端口的16980来访问“c”的web服务

④、“e”上通过ssl的vpn可以访问“c”上的资源,现让公司所有员工机通过“e”可以访问“c”上的资源:

“e”通过vpn链接“c”,则“e”和“c”网络理论上是直连网络,通过内网访问,我们给“c”分配内网ip为“192.168.10.101”;

事实上,本案例中“c”作为目标主机,也作为了中间转发服务器;

ssh -p 22 -CfNg -L 19022:192.168.10.101:21 root@192.168.10.101

或是写成:

ssh -CfNg -L 19022:localhost:21 192.168.10.101

因为目标ip就是中间服务器它本身,所以可以用“localhost”或是“127.0.0.1”作为目标ip;在xshell中的隧道转移中也可以这么配置;

⑤、“e”上配置隧道,让“d”可以通过“c”的某个端口来进行访问“a”的远程桌面服务:

这个就比较厉害了,相比于上面四个案例,都是谁访问,谁来创建隧道,属于主动发出的隧道连接,也就是说总要有个环节需要你有足够的访问权限,归根就是借用权限做转发;

但有时候你没有任何公司内部对外开放的权限时,却又需求从外部访问公司内部资源,如远程办公主机在外作业,怎么办?

这时你只需要有一台你自己控制的外部linux服务器,如一台云主机“c”;如此我们便可以通过在“e”上配置隧道转发,把本地的某个服务,或是局域网自己能访问的某个服务器的某个服务,给转发到远程服务器上,也就是“c”上,如此,我们便可以在外部通过访问“c”从而访问公司内部的某个服务。

比如这里,我要在“e”上配置ssh远程隧道,把同局域网中的“a”的3389服务,映射到中间服务器“c”上,然后在“d”上通过访问“c”从而访问“a”:

ssh -p 19022 -CfNg -R 19038:192.168.1.101:3389 root@124.207.2.2
注意

以上,如果云主机“c”直接配置的公网ip,则把19022直接改成22就好了,如此,在“d”上就可以直接访问(全屏)“mstsc /console /v:124.207.2.2:19038 /f”;

如果“c”配置有内网ip,则可能要注意,还要把其转发的端口19038开放出去;“mstsc /console /v:124.207.2.2:19038 /w:width /h:height”

-R、表示创建远程隧道映射转发,意思也就是说吧本地的某个服务,映射到远程服务器的某个端口上,然后通过访问远程服务器从而访问本地的那个服务;

当然这种方法,是可以实现穿越本地网络束缚的。

此外在xshell上配置远程隧道转发的方法,则在“转移规则”中的“类型(方向)”处选择“remote(incoming)”类型;

⑥、通过ssh隧道建立socks服务器:

什么叫socks服务器,其实就是代理服务器了,我们常说的翻墙就可以用它来实现了;

当然如果要做翻墙,首先你要有一台可以访问的外国的云主机vps;

而这里,我们不翻国内外的墙,仅仅翻一下公司的墙吧;

我们假设公司不允许内部网络访问外部web资源,现外部有一台服务器就是“c”,在“e”上配置ssh隧道的socks代理服务器,然后其它员工机如“a”通过浏览器配置代理“e”访问外部网络资源;

ssh -p 19022 -CfNg -D 16980 root@124.207.2.2

或是:

ssh -p 19022 -CdNg -D 0.0.0.0:16980 124.207.2.2

如此便可以在其它员工机“a”上的浏览器配置socks代理,指向192.168.1.102的16980端口,通过其访问web资源;

注意

值得一说的是,ssh的socks和远程隧道都具备穿越内网的能力,但是前者更具备高效性;

-D、表示创建ssh隧道socks服务;

当然xshell中也有类似的配置,则在“转移规则”中的“类型(方向)”处选择“Dynamic(socks4/5)”类型;

至此,通过以上六个案例,我们可以对ssh隧道的神奇有个很清晰客观的认识,当然具体使用还要针对具体情况,希望对你有所帮助;

总结·扩展

虽然我们已经知道如何配置ssh隧道,但是有关它的一些问题,我们也有必要知道:

1、如何让隧道保持长时间连接,特别是案例⑤中的远程隧道:

(ssh客户端的tcpkeepalive选项可以避免超时断开,默认是开启的,如果没有开启,可执行命令时加上此参数)

ssh -p 19022 -N -f -o TCPKeepAlive=yes -D 16980 124.207.2.2

(第二种方法,去掉“N”后台执行选项,并添加一个定期能输出的命令,从而使链接一直保持活跃状态,如“top、vmstat、sar”)

ssh -p 19022 -f -D 16980 124.207.2.2 "sar -n DEV 10"
2、检查隧道状态,避免假死链接:

使用ssh两个参数“ServerAliveInterval”、“ServerAliveCountMax”:

表示为,当隧道在无通信后一段时间后,会向服务器发送一个请求要求服务器响应,这个时间由ServerAliveInterval参数设定;

如果服务器在n次请求后仍然没有响应,则ssh客户端会判断连接故障并自动断开退出连接,避免假死,这个次数由ServerAliveCountMax参数设定;

ssh -p 19022 -Nf -o ServerAliveInterval=10 -o ServerAliveCountMax=10 -D 16980 124.207.2.2
3、实现全局访问,即其它主机也可通过隧道访问资源;

事实上,上面的“-g”参数,就已经是实现这个功能的参数了;

但是有时候这个参数不生效,任然只能本地能访问,这个时候可以选择尝试修改/etc/ssh/sshd.conf配置文件:

找到“GatewayPorts yes”选项,把后面的no改成yes;

4、查看已建立的ssh隧道,并删除:

上面我们创建了隧道,并且让其后台执行,那么如何查看这些隧道并删除它们呢?

[root@Moni ~]# ps -ef | grep ssh
[root@Moni ~]# netstat -anpt | grep ssh
[root@Moni ~]# kill -9 session-id
[root@Moni ~]# killall ssh

通过查看进程或网络连接,找到隧道的进程id,杀死即可,当然可以“killall ssh”杀死所有ssh链接;

5、扩展分享:

(以上我们是通过linux的ssh创建的隧道转发,总的来说还是很实用的;那么windows服务器能不能实现类似的需求呢?)

下一篇文章,将为您总结分享:【windows】netsh创建的portproxy端口映射转发

(好的就分享到这里,如果您有高见或好的分享,记得留言哦!)


原创文章,转载请注明:转自于公牛博客

本文链接地址:【linux】建立ssh隧道端口转发大穿越

20
祝福我们的祖国繁荣昌盛
  • 请尽情挥洒您的笔墨!