安全Shell是一种用于安全连接的网络协议。它被大量地运用在针对各种服务器的连接、修改、上传和最后退出的环节中。这些操作有时候可以通过工具来实现,有时甚至可以直接使用终端。在这里,您将了解到在标准的SSH之外使用终端的一些技巧。
在深入讨论高级SSH技术之前,我们假设您对SSH密钥的安全性和使用已经具有了一定的基本知识。在这篇文章中,我们将使用用户来指代SSH的用户,用yourserver.tld指代域名或IP地址,所以您需要自行替换成正确的用户名和主机名信息。
为了修改SSH服务器端的配置,您需要直接以root身份登录,或者通过sudo进行一般用户权限的提升。而为了使得在/etc/ssh/sshd_config中的更改能在系统范围内生效,您需要重新加载SSH服务。
根据您所使用的操作系统不同,具体操作上也会有所差异。例如在基于Debian的系统上,您需要以root身份或是做sudo提权后,在终端里输入service ssh reload。每次当您更改了服务器端的SSH配置之后,您就得重新加载(或重新启动)其对应的服务。
配置顺序
和其他的Linux系统工具一样,配置选项生效的顺序如下:
- 在终端/应用程序中直接给出命令行的选项。
- 用户的配置文件(~/.ssh/config)。
- 客户端的系统范围配置文件(/etc/ssh/ssh_config)。
这就意味着:任何通过命令行所输入的SSH参数都比那些在配置文件中的选项有着优先的执行级别。因此对于单次性的操作而言,最好方式是直接使用命令输入;而对于您要经常连接的特定主机,或是要用到不同用户名的情况,最好还是保存在配置文件中。SSH守护程序本身用到的,系统范围的配置文件被存放在etc/ssh/sshd_config处。
主机匹配
您可以在各种SSH配置文件中使用通配符,也就是说您可以把一个指令集应用到大范围的主机上,然后对每个主机再使用一些特定的指令,例如:
在~/.ssh/config中,
- Host myhost-*
- Port 1234
- Host myhost-one
- Hostname myhost-one.yourserver.tld
- User admin
- Host myhost-two
- Hostname myhost-two.yourserver.tld
- User anotheradmin
在上面的例子中,两台服务器使用相同端口号1234,不同的用户名建立不同的连接。有了这些基础知识,我们就可以开始用SSH来实现6种应用了。
1. SFTP
我想访问存储在服务器上的文件,但无需安装任何额外的软件。
大多数FTP应用程序(例如FileZilla)都可以使用SFTP(SSH的文件传输协议),它是将文件传输到您的Web主机的首选方式。在其GUI上,您可以填写地址、端口、用于SSH连接的用户名以及要传输的文件。通常情况下,您需要进入应用程序的设置界面,禁用固定的密码,而改用您的SSH私钥来建立连接。
在终端上,您可以通过输入sftp,来调出交互式控制台。请记住,由于其SFTP只提供有限的命令选项,如:创建目录、浏览访问的目录和下载/上传文件,因此您无法在控制台内使用到SSH的其他所有命令。您可以通过链接:https://itservices.usc.edu/sftp/cline/来了解更多的SFTP命令行操作。
2. KeepAlive
我的防火墙老是关闭我的连接!
有时候,您的防火墙可能会中断掉一些正常的连接。下面就有三个指令能够防止SSH连接被过早地掐断。
- TCPKeepAlive可以在SSH的客户端和守护进程的配置文件中使用。它决定了是否需要发送保持连接的TCP消息。TCPKeepAlive的默认值为yes。它会发出TCP消息,提醒防火墙注意到连接的继续,而不要掐断它。当然有些用户在不需要的时候可以将TCPKeepAlive设置为no。
- ServerAliveInterval验证其连接是否存活。在客户端配置中,您可以指定客户端在发送数据包给服务器之前所需等待的秒数。如果将该值设置为0,即禁用此选项,则会在一段空闲的时间之后断开SSH会话。而指令ServerAliveCountMax指定了从发送数据包,到该连接由于没有来自服务器的响应而被取消的反复尝试次数(一般为整数)。
- ClientAliveInterval是在SSH守护进程的服务配置文件/etc/ssh/sshd_config中所使用的指令。它指定了服务器在发送数据包给客户端之前所需等待的秒数。您可以将该值设置为0,即禁用该选项。而指令ClientAliveCountMax指定了从发送数据包,到该连接由于没有来自客户端的响应而被取消的反复尝试次数(一般为整数)。
所有主机都使用相同的客户端SSH配置文件,来设置keep alive的参数:
在~/.ssh/config中
- Host *
- ServerAliveInterval 30
- ServerAliveCountMax 10
这样的配置意味着客户在发送一个空包之前要等待30秒,并且要尝试多达10次,以确认在服务器无响应的情况下中断连接。
3. SSH代理
我觉得每次输入密码短语很繁琐,也许我应该生成一些密钥而非密码短语?
一种常见且有效的安全做法是加密您的SSH私钥,并用密码短语来进行解密。这种方法的缺点是:您每次都必须繁琐地重新输入密码以初始化SSH连接,而这本质上就是反复输入密码的过程。
为了解决这个问题,您可以使用ssh-agent。它是一种能在会话期间将私钥保持在内存之中的工具。当代理启动后,所有需要SSH连接的窗口和应用程序都将通过该代理来获得您的私钥,因此您只需要在会话开始的时候一次性输入密码短语便可。
在大多数Linux操作系统上,SSH代理是默认运行的,因此不需要额外进行安装。如果您想检查ssh代理是否正在运行,您可以在终端里输入:
- ps x | grep ssh-agent
如果还没有运行的话,您可以这样启动它:
- eval $(ssh-agent)
一旦它运行起来,您就可以罗列出ssh代理当前可用的所有密钥:
- ssh-add –L
如果要用的密钥丢失,您可以通过ssh-add /path/to/your/ssh/privatekey来添加它。当您想连接一台主机,却碰到Too many authentication failures for user的错误时,这就意味着SSH代理正在试图检查所有可用的密钥。因此最好的方法是在您的配置文件中定义一个IdentityFile /path/to/your/ssh/privatekey/forthishost。如果您要确保只能使用由IdentityFile所定义的连接,则可以在配置中使用指令IdentitiesOnly yes,它会告诉SSH只使用由终端或配置文件所提供的密钥。请看如下的例子:
在~/.ssh/config中,
- Host yourserver
- HostName yourserver.tld
- IdentityFile ~/.ssh/yourprivatekeyname
- IdentitiesOnly yes
- User user
(1) 代理转发
我就只想在最开始的时候输入一次密码短语,之后就算我从一台主机连接到另一台主机的时候,也不要提示我再次输入。
为了能够在互连的主机之间共用相同的信任凭证,代理也是可以被转发的。虽然这样的转发非常方便,但是请记住:代理仅能将您的私钥保存在内存之中。一旦某个恶意程序攻破了联网的一台主机,就能使用您的密钥在其他主机上执行各种命令。可见,代理转发是一种不安全的方法,只能在您所连接的信任主机上被使用。
为了用到代理转发,您需要在客户端的ssh_config上设置ForwardAgent yes,并在任何需要用到转发代理的服务器上的/etc/ssh/sshd_config里设置AllowAgentForwarding yes。
4. 通过本地端口转发的隧道
我想要做的事情,本地电脑不允许,但我知道哪里会有一台电脑是允许的。
隧道是SSH的一种最常见的高级使用案例。它在SSH连接内通过加密应用的流量,从而实现安全保护。这对于传统软件或其他安全性欠佳的应用和系统来说是非常有用的,它为软件设置了一个不能也无法改变的安全包装,以抵御不安全网络环境。
(1) 服务器端
服务器端可以修改文件/etc/ssh/sshd_config中的配置。由于以#开头的行是被注释掉的,因此如果您想使用该选项的话,只要复制出另外一行进行修改或者直接取消掉注释便可。对于端口转发式的隧道,为了使其工作,您需要开启TCP的转发。
在/etc/ssh/sshd_config中,
- AllowTcpForwarding yes
如果您修改了服务器的配置文件,请记得重新加载SSH服务。至于如何重载或重新启动您的服务端的服务,则取决于操作系统的类型。在大多数情况下,应该是如下命令:
- service ssh reload
(2) 客户端
在客户端有好几种方法来使用SSH隧道。大多数情况下,您会这样来实现SSH隧道:
- 如果您想对一个仅供另一台机器访问的数据库来执行查询操作,那么就需要用隧道来连接那台机器。下面的例子展示了如何运用yourserver.tld来隧道连接到一台PostgreSQL数据库服务器,并且在那里使用基于终端的psql frontend。
- ssh -L 5000:psql.server.ip:5432 user@yourserver.tld
- psql -p 5000 -h 127.0.0.1 -U postgres
- ssh -L 1337:yourwebsite.com:80
5. X11转发
我并没有一些昂贵软件的许可证,我只能在连上服务器后,显示在我家里的屏幕上。
您可以通过SSH来初始化X11转发,这就意味着你可以显示远程的计算机桌面环境,并将各种X11包转发到您所使用的计算机上。X11转发有着广泛的适用性,特别是在您必须使用某个特定软件的GUI时。在下面的例子中,我们将测试用X11来转发xclock。
(1) 先决条件
为了能将X11包转发给客户端,xauth包必须被预先安装在服务器上。所以如果你想测试xclock的话,就必须提前安装好它。
(2) 服务器
在服务器上,您需要在/etc/ssh/sshd_config里启用X11Forwarding。具体操作是:定位到具有X11Forwarding的一行,将其设置为yes,也就是说:如果该行已经存在,并被注释掉了的话,您直接删除前面的#便可。
在/etc/ssh/sshd_config中,
- X11Forwarding yes
在修改了配置文件之后,请不要忘记重新加载SSH服务。
(3) 客户端
- ssh -X
现在,您可以使用X11来将服务器转发到客户端的计算机上了。通过输入xclock,一个时钟窗口会在您的桌面电脑上弹出,如截图所示。
X11转发的伟大之处在于:当你想使用一个由于授权方面的原因而只能安装在一台服务器上的软件,或是与您的普通电脑有着不同的性能需求时,都可以用到X11转发。
6. 代理跳转(ProxyJump)
我想访问与外界相隔离的专用网络,我会搭建一台能够连接的服务器,然后跳转到我要去的那些机器上。
SSH的一种常见访问策略是连接到一台堡垒主机上,然后从那里跳转到没有公共路由的设备上。该堡垒主机被称为代理链上的第一跳主机。ProxyJump是OpenSSH的一个新功能,它简化了所用到的跳跃主机。在您不希望被公开暴露时,它为主机添加了一层额外的安全。
这方面的一个用例是:用一台小机器作为路由器后面的堡垒实体机,您在上面运行sshd,并从那里跳转到其他主机上。可见,这对于家庭网络是很实用的。这与从端口转发和从一台主机隧道到下一台上并没什么不同,只是现在这种情况下,用关键字ProxyJump描述的是在指定的多台主机间跳跃,参照的是含有逗号分隔的列表。在终端上,请使用参数-J,如下所示:
- ssh -J proxy.server.tld:22 yourserver.tld
对于更为复杂的、需要使用不同的用户名来实现的若干台主机间的跳转,可以使用:
- ssh -J [email protected]:port1,[email protected]:port2
由于您可能会经常使用到主机间的跳转,因此最好把它们包含在您的用户或系统常规SSH配置之中。如下的配置文件就适用于上述的用例:
在~/.ssh/config中,
- Host yourserver.tld
- HostName yourserver.tld
- ProxyJump user1@proxy.server1.tld:port1,user2@proxy.server2.tld:port2
- User user
你也可以为每一个主机的跳转指定SSH配置,并使用ProxyJump字段来指定它们的别称。
在~/.ssh/config中,
- Host firstproxy
- HostName proxy.server1.tld
- Port 1234
- User user1
- Host secondproxy
- HostName proxy.server2.tld
- Port 5678
- User user2
- Host yourserver.tld
- HostName yourserver.tld
- ProxyJump firstproxy,secondproxy
- User user
注意,新添加的ProxyJump和那些旧的ProxyCommand指令都完全遵守“先到先得”的原则,这就意味着先设定的会被先执行、以此类推下去。如果您的SSH客户端并不支持ProxyJump的话,您可以改用ProxyJump的指令:ProxyCommand ssh firstproxy -W %h:%p。