SSH隧道及其使用

SSH隧道及其使用,第1张

SSH隧道是一种通过加密的SSH连接传输任意网络数据的方法。它可以用来为任何应用程序添盯丛加加密通道;也可以宴迹用它来实现VPN和跨防火墙访问局域网的服务。

SSH是一个通过不受信任的网络进行安全远程登录和文件传输的标准。通过SSH隧道传输TCP/IP数据,它还提供了一种使用端口转发保护任何给定应用程序数据流量的方法。采用了这种方法后,应用程序的数据流量都会走SSH的加密连接,从而不会被窃听或拦截。对于本身不支持加密的应用程序来说,使用SSH隧道可以很方便地添加网络安全性。

上图简要介绍了SSH隧道。不可信网络的安全连接建立在SSH客户端和SSH服务器之间。这个连接是加密的,可用于保护机密性和完整性,并且可以对通信方进行身份验证。

客户端应用使用SSH来连接到服务端应用。隧道启用后

通过上面的转发,无需修改应用程序,就能保证应用程序客户端和服务端通信的安全。

这个方式的缺点是,任何能登陆服务器的用户都可以启用端口转发。内部IT人员经常在他们的家里的机器或云上的服务器上启用转发,从而能在企业内网中,从工作机器上访问家里的机器或云上的服务器。黑客或恶意软件会利用类似的方式在局域网中留一个后门。还可以在多个设备上开启隧道,攻击者通过在这些隧道晌则并中跳来跳去来隐藏踪迹。

本地代理用于将端口从客户端计算机转发到服务端计算机。SSH客户端监听来自某个端口的连接,当它收到连接时,将请求通过隧道转发到SSH服务器;然后SSH服务器将请求转到目标端口。

本地转发比较常见的场景有:

在OpenSSH中,使用 -L 参数开启本地转发

这个命令工作的过程如下图

默认情况下,其他的机器都能够连接到本地的SSH客户端指定的端口;为了安全起见,一般绑定地址,将连接来源限制在同一主机的程序

也可以在 OpenSSH客户端的配置中 配置本地转发,这样就不用单独输入命令行了

比如在~/.ssh/config中这样写

这样在开启转发的时候只需要输入 ssh serverfw 而不用再输入完整的命令了

如果希望通过本地计算机,让远程服务器 remote 可以连接到 server 上的服务,可以使用SSH远程转发。

使用SSH远程转发一个典型的用途是,在企业内部开一个后门,让公网的计算机可以访问到企业的某个内部服务,这个是有一定风险的,使用的时候需要特别小心。

在OpenSSH中,远程转发通过 -R 参数开启,在本地计算机上输入命令

上面命令的工作过程如下

默认情况下,OpenSSH仅允许从服务器主机(上图的 remote )连接到远程转发端口 server:p2 ,如果想要其他的主机也能连上 server:p2 ,需要在 sshd_config 文件中设置

如果需要指定来源IP,可以将配置改为

比如

将只允许52.192.1.73到端口8080的连接

OpenSSH的远程转发支持多个规则,比如

同样的,可以在 ~/.ssh/config 配置host,比如

这条通道可以用很多技术来建立,这里我们仅仅介绍如何使用SSH服务器来建立这样一个通道-他被称为SSH隧道。

如何建立本地SSH隧道

在我们计划建立一个本地SSH隧道之前,我们必须清楚下面这些数据:

中间服务器d的IP地址

要访问服务器c的IP地址

要访问服务器c的端口

现在,我们把上面这张图变得具体一些,给这些机器加上IP地址。并且根据下面这张图列出我们的计划:

需要访问234.234.234.234的FTP服务,也就是端口21

中间服务器是123.123.123.123

现在我们使用下面这条命令来达成我们的目的

ssh -N -f -L 2121:234.234.234.234:21 123.123.123.123

ftp localhost:2121 # 现在访问本地2121端口,就能连接234.234.234.234的21端口了

这里我们用到了SSH客户端的三个参数,下面我们一一做出解释:

-N 告诉SSH客户端,这个连接不需要执行任何命令。仅仅做端口转发

-f 告诉SSH客户端在后台运行

-L 做本地映射端口,被冒号分割的三个部分含义分别是

需要使用的本地端口号

需要链搏旦访问的目标机器IP地址(IP: 234.234.234.234)

需要访问的目标机器端口(端口: 21)

最后一个参数是我们用来建立隧道的中间机器的IP地址(IP: 123.123.123.123)

我们再重复一下-L参数的行为。-L X:Y:Z的含义是,将IP为Y的机器的Z端口通过中间服务器映射到本地机器的X端口。

在这条命令成功执行之后,我们已经具有绕过公司防火墙的能力,并且成功访问到了我们喜欢的一个FTP服务器了。

如何建立远程SSH隧道

通过建立本地SSH隧道,我们成功地绕过防火墙开始下载FTP上的资源了棚扰。那么当我们在家里的时候想要察看下载进度怎么办呢?大多数公司的网络是通过路由器接入互联网的,公司内部的机器不会直接与互联网连接,也就是不能通过互联网直接访问。通过线路D-B-A访问公司里的机器a便是不可能的。也许你已经注意到了,银如虽然D-B-A这个方向的连接不通,但是A-B-D这个方向的连接是没有问题的。那么,我们能否利用一条已经连接好的A-B-D方向的连接来完成D-B-A方向的访问呢?答案是肯定的,这就是远程SSH隧道的用途。

与本地SSH一样,我们在建立远程SSH隧道之前要清楚下面几个参数:

需要访问内部机器的远程机器的IP地址(这里是123.123.123.123)

需要让远程机器能访问的内部机器的IP地址(这里因为是想把本机映射出去,因此IP是127.0.0.1)

需要让远程机器能访问的内部机器的端口号(端口:22)

在清楚了上面的参数后,我们使用下面的命令来建立一个远程SSH隧道

ssh -N -f -R 2222:127.0.0.1:22 123.123.123.123

现在,在IP是123.123.123.123的机器上我们用下面的命令就可以登陆公司的IP是192.168.0.100的机器了。

ssh -p 2222 localhost

-N,-f 这两个参数我们已经在本地SSH隧道中介绍过了。我们现在重点说说参数-R。该参数的三个部分的含义分别是:

远程机器使用的端口(2222)

需要映射的内部机器的IP地址(127.0.0.1)

需要映射的内部机器的端口(22)

例如:-R X:Y:Z 就是把我们内部的Y机器的Z端口映射到远程机器的X端口上。

建立SSH隧道的几个技巧

自动重连

隧道可能因为某些原因断开,例如:机器重启,长时间没有数据通信而被路由器切断等等。因此我们可以用程序控制隧道的重新连接,例如一个简单的循环或者使用 djb’s daemontools . 不管用哪种方法,重连时都应避免因输入密码而卡死程序。关于如何安全的避免输入密码的方法,请参考我的 如何实现安全的免密码ssh登录 。这里请注意,如果通过其他程序控制隧道连接,应当避免将SSH客户端放到后台执行,也就是去掉-f参数。

保持长时间连接

有些路由器会把长时间没有通信的连接断开。SSH客户端的TCPKeepAlive选项可以避免这个问题的发生,默认情况下它是被开启的。如果它被关闭了,可以在ssh的命令上加上-o TCPKeepAlive=yes来开启。

另一种方法是,去掉-N参数,加入一个定期能产生输出的命令。例如: top或者vmstat。下面给出一个这种方法的例子:

ssh -R 2222:localhost:22 123.123.123.123 "vmstat 30"

检查隧道状态

有些时候隧道会因为一些原因通信不畅而卡死,例如:由于传输数据量太大,被路由器带入stalled状态。这种时候,往往SSH客户端并不退出,而是卡死在那里。一种应对方法是,使用SSH客户端的ServerAliveInterval和ServerAliveCountMax选项。ServerAliveInterval会在隧道无通信后的一段设置好的时间后发送一个请求给服务器要求服务器响应。如果服务器在ServerAliveCountMax次请求后都没能响应,那么SSH客户端就自动断开连接并退出,将控制权交给你的监控程序。这两个选项的设置方法分别是在ssh时加入-o ServerAliveInterval=n和-o ServerAliveCountMax=m。其中n, m可以自行定义。

如何将端口绑定到外部地址上

使用上面的方法,映射的端口只能绑定在127.0.0.1这个接口上。也就是说,只能被本机自己访问到。如何才能让其他机器访问这个端口呢?我们可以把这个映射的端口绑定在0.0.0.0的接口上,方法是加上参数-b 0.0.0.0。同时还需要打开SSH服务器端的一个选项-GatewayPorts。默认情况下它应当是被打开的。如果被关闭的话,可以在/etc/sshd_config中修改GatewayPorts no为GatewayPorts yes来打开它。

如何寻找中间服务器

如果你家里使用ADSL上网,多半你会比较幸运。一般的ADSL(例如 联通 的ADSL)都是有互联网地址的。你只需要在家里的路由器上一台装有OpenSSH server机器的SSH端口映射出去即可。同时一些提供SSH访问的虚拟主机也可以用于这一用途。例如: Hostmonser 或者 Dreamhost .

通过SSH隧道建立SOCKS服务器

如果我们需要借助一台中间服务器访问很多资源,一个个映射显然不是高明的办法(事实上,高明确实没有用这个方法)。幸好,SSH客户端为我们提供了通过SSH隧道建立SOCKS服务器的功能。

通过下面的命令我们可以建立一个通过123.123.123.123的SOCKS服务器。

ssh -N -f -D 1080 123.123.123 # 将端口绑定在127.0.0.1上

ssh -N -f -D 0.0.0.0:1080 123.123.123.123 # 将端口绑定在0.0.0.0上

通过SSH建立的SOCKS服务器使用的是SOCKS5协议,在为应用程序设置SOCKS代理的时候要特别注意。

总结

至此,我们已经对如何利用SSH隧道有一个基本的认识了。现在,文章开始时的那些问题应该迎刃而解了吧。这里要特别说一下,由于SSH隧道也使用了SSH加密协议,因此是不会被防火墙上的内容过滤器监控到的。也就是说一切在隧道中传输的数据都是被加密的。当然,离开隧道后的数据还是会保持自己原有的样子,没有加密的数据还是会被后续的路由设备监控到。

SSH是每一台Linux电脑的标准配置

随着Linux设备从电脑逐渐扩展到手机、外设和家用电器,SSH的适用范围也越来越广。不仅程序员离不开它,很多普通用户也每天使用;SSH具备多种功能,可以用于很多场合。有些事情,没有它就是办不成

简单说,SSH是一种网络协议,用于计算机之间的加密登录。

如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会泄露。

最早的时候,互联网通信都是明文通信,一旦被截获,内容就暴露无疑。1995年,芬兰学者Tatu Ylonen设计了SSH协议,将登录信息全部加密,成为互联网安全的一个基本解决方案,迅速在全世界获得推广,目前已经成为Linux系统的标准配置。雹和陵

需要指出的是,SSH只是一种协议,存在多种实现,既有商业实现,也有开源实现。

SSH主要用于远程登录。假定你要以用户名user,登录远程主机host,只要一条简单命令就可以了。

如果本地用户名与远程用户名一致,登录时可以省略用户名。

SSH的默认端口是22,也就是说,你的登录请求会送进远程主机的22端口。使用p参数,可以修改这个端口。

上面这条命令表示,ssh直接连接远程主机的2222端口。

SSH之所以能够保证安全,原因在于它采用了公钥加密。

整个过程是这样的:(1)远程主机收到用户的登录请求,把自己的公钥发给用户。(2)用户使用这个公钥,将登录密码加密后,发送回来。(3)远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。

这个过程本身是安全的,但是实施的时候存在一个风险:如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。因为不像https协议,SSH协议的公钥是没有证书中心棚裤(CA)公证的,也就是说,都是自己签发的。

可以设想,如果攻击者插在用户与远程主机之间(比如在公共的wifi区域),用伪造的公钥,获取用户的登录密码。再用这个密码登录远程主机,那么SSH的安全机制就荡然无存了。这种风险就是著名的“中间人攻击”(Man-in-the-middle attack)。

SSH协议是如何应对的呢?

如果你是第一次登录对方主机,系统会出现下面的提示:

这段话的意思是,无法确认host主机的真实性,只知道它的公钥指纹,问你还想继续连接吗?

所谓”公钥指纹”,是指公钥长度较长(这里采用RSA算法,长达1024位),很难比对,所以对其进行MD5计算,将它变成一个128位的指纹。上例中是98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d,再进行比较,就容易多了。

很自然的一个问题就是,用户怎么知道远程主机的公钥指纹应该是多少?回答是没有好办法,远程主机必须在自己的网站上贴出公钥指纹,以便用户自行核对。

假定经过风险衡量以后,用户决定接受这个远程主机的公钥。

系统会出现一句提示,表示host主机已经得到认可。

然后,会要求输入密码。

如果密码正确,就可以登录了。

当远程主机的公钥被接受以后,它就会被保存在文件 $HOME/.ssh/known_hosts 之中。下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。

每个SSH用户都有自己的 known_hosts 文件,此外系统也有一个这样的文件,通常是 /etc/ssh/ssh_known_hosts ,保存一些对所有用户都可信赖的远程主机的公钥。

使用密码登录,每次都必须输入密码,非常麻烦。好在SSH还提供了公钥登录,可以省去输入密码的步骤。

所谓”公钥登录”,原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。

这种方法要求用户必须提供自己的公钥。如果没有现成的源戚,可以直接用 ssh-keygen 生成一个:

运行上面的命令以后,系统会出现一系列提示,可以一路回车。其中有一个问题是,要不要对私钥设置口令(passphrase),如果担心私钥的安全,这里可以设置一个。

运行结束以后,在$HOME/.ssh/目录下,会新生成两个文件: id_rsa.pub 和 id_rsa 。前者是你的公钥,后者是你的私钥。

这时再输入下面的命令,将公钥传送到远程主机host上面:

好了,从此你再登录,就不需要输入密码了。

如果还是不行,就打开远程主机的 /etc/ssh/sshd_config 这个文件,检查下面几行前面”#”注释是否取掉。

然后,重启远程主机的ssh服务。

远程主机将用户的公钥,保存在登录后的用户主目录的 $HOME/.ssh/authorized_keys 文件中。公钥就是一段字符串,只要把它追加在 authorized_keys 文件的末尾就行了。

这里不使用上面的ssh-copy-id命令,改用下面的命令,解释公钥的保存过程:

这条命令由多个语句组成,依次分解开来看:

(1) ”$ ssh user@host” ,表示登录远程主机;

(2)单引号中的 mkdir .ssh &&cat >>.ssh/authorized_keys ,表示登录后在远程shell上执行的命令:

(3) ”$ mkdir -p .ssh” 的作用是,如果用户主目录中的.ssh目录不存在,就创建一个;

(4) ’cat >>.ssh/authorized_keys’ <~/.ssh/id_rsa.pub 的作用是,将本地的公钥文件 ~/.ssh/id_rsa.pub ,重定向追加到远程文件 authorized_keys 的末尾。

写入 authorized_keys 文件后,公钥登录的设置就完成了。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12272258.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存