浅析SSH简介、基本用法(查看/安装/登录/nohup)、中间人攻击、SSH安全机制、口令登录/公钥登录流程、远程操作/绑定本地端口/本地端口转发/远程端口转发/其他参数等的处理介绍

  最近做的那个需求涉及到 SSH 连接,不大清楚,所以研究了一下,推荐阅读这 4 篇文章,以下来自于这 4 篇文章的学习总结:

1、SSH原理与运用(一):远程登录 —— https://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html

2、SSH原理与运用(二):远程操作与端口转发 —— https://www.ruanyifeng.com/blog/2011/12/ssh_port_forwarding.html

3、SSH简介及两种远程登录的方法  ——  https://blog.csdn.net/li528405176/article/details/82810342

4、Linux ssh命令详解  ——  https://www.cnblogs.com/ftl1012/p/ssh.html

一、什么是SSH

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

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

3、Secure Shell(SSH)是由 IETF(The Internet Engineering Task Force)制定的建立在应用层基础上的安全网络协议。它是专为远程登录会话和其他网络服务提供安全性的协议,可有效弥补网络中的漏洞。通过SSH,可以把所有传输的数据进行加密,也能够防止DNS欺骗和IP欺骗。

4、还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。目前已经成为Linux系统的标准配置。

5、SSH(远程连接工具)连接原理:ssh服务是一个守护进程(demon),系统后台监听客户端的连接,ssh服务端的进程名为sshd,负责实时监听客户端的请求(IP 22端口),包括公共秘钥等交换等信息。

6、ssh 服务端由 2 部分组成:openssh(提供ssh服务)、openssl(提供加密程序)

二、最基本的用法

1、SSH 的安装  ——  SSH分为客户端 openssh-client 和服务器 openssh-server

// 以利用以下命令确认电脑上是否安装了客户端和服务器
dpkg -l | grep ssh

// 安装
sudo apt-get install openssh-client
sudo apt-get install openssh-server

// 查看ssh-server是否启动
ps -e | grep ssh

// 启动 ssh-server
sudo /etc/init.d/ssh start

sudo /etc/init.d/ssh stop  // server停止ssh服务 
sudo /etc/init.d/ssh restart  // server重启ssh服务

2、口令登录  ——  口令登录非常简单,只需要一条命令,命令格式为: ssh 客户端用户名@服务器ip地址

// 口令登录
ssh ldz@192.168.0.1

// 调用图形界面程序可以使用 -X 选项
ssh -X ldz@192.168.0.1

// SSH服务的默认端口是22,如果你不设置端口的话登录请求会自动送到远程主机的22端口
// 我们可以使用 -p 选项来修改端口号
ssh -p 1234 ldz@192.168.0.1

3、公钥登录

// 在本机生成密钥对,使用ssh-keygen命令生成密钥对
ssh-keygen -t rsa   // -t表示类型选项,这里采用rsa加密算法

// 执行结束以后会在 /home/当前用户 目录下生成一个 .ssh 文件夹,其中包含私钥文件 id_rsa 和公钥文件 id_rsa.pub

// 将公钥复制到远程主机中
// 使用ssh-copy-id命令将公钥复制到远程主机。ssh-copy-id会将公钥写到远程主机的 ~/ .ssh/authorized_key 文件中
ssh-copy-id ldz@192.168.0.1

4、SSH的高级应用  ——  使用远程主机不中断的跑程序

  当我们利用ssh在远程主机上跑程序的时候,只要关闭了终端就会中断ssh连接,然后远程主机上正在跑的程序或者服务就会自动停止运行。

  我们可以利用 nohup + 需要运行的程序 使运行的程序在切断ssh连接的时候仍然能够继续在远程主机中运行。nohup即no hang up(不挂起)。

三、中间人攻击及SSH的安全机制

  SSH之所以能够保证安全,原因在于它采用了公钥加密。整个过程是这样的:

(1)远程主机收到用户的登录请求,把自己的公钥发给用户。

(2)用户使用这个公钥,将登录密码加密后,发送回来。

(3)远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。

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

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

  SSH协议是如何应对的呢?

1、SSH 能够保证安全的原因在于它采用了非对称加密技术(RSA)加密了所有传输的数据。

2、传统的网络服务程序,如FTP、Pop和Telnet其本质上都是不安全的;因为它们在网络上用明文传送数据、用户帐号和用户口令,很容易受到中间人(man-in-the-middle)攻击方式的攻击。但并不是说SSH就是绝对安全的,因为它本身提供两种级别的验证方法:

(1)第一种级别:基于口令的安全验证 —— 依然会受“中间人攻击”这种方式的攻击

(2)第二种级别:基于密钥的安全验证 —— 安全性更高,可以有效防止中间人攻击

四、口令登录

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

$ ssh user@host

The authenticity of host 'host (12.18.429.21)' can't be established.
RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.
Are you sure you want to continue connecting (yes/no)?

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

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

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

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

Are you sure you want to continue connecting (yes/no)? yes

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

Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.

  然后,会要求输入密码。

Password: (enter password)

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

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

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

五、公钥登录

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

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

  公钥登录流程如下:

  • (1)Client将自己的公钥存放在Server上,追加在文件authorized_keys中。
  • (2)Server端接收到Client的连接请求后,会在authorized_keys中匹配到Client的公钥pubKey,并生成随机数R,用Client的公钥对该随机数进行加密得到pubKey(R),然后将加密后信息发送给Client。
  • (3)Client端通过私钥进行解密得到随机数R,然后对随机数R和本次会话的SessionKey利用MD5生成摘要Digest1,发送给Server端。
  • (4)Server端会也会对R和SessionKey利用同样摘要算法生成Digest2。
  • (5)Server端会最后比较Digest1和Digest2是否相同,完成认证过程。

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

$ ssh-keygen

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

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

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

$ ssh-copy-id user@host

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

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

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

  然后,重启远程主机的ssh服务:service ssh restart

六、authorized_keys文件

  远程主机将用户的公钥,保存在登录后的用户主目录的$HOME/.ssh/authorized_keys文件中。公钥就是一段字符串,只要把它追加在authorized_keys文件的末尾就行了。这里不使用上面的ssh-copy-id命令,改用下面的命令,解释公钥的保存过程:

$ ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub

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

(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文件后,公钥登录的设置就完成了。

七、远程操作

  SSH不仅可以用于远程主机登录,还可以直接在远程主机上执行操作。

  上一节的例子:单引号中间的部分,表示在远程主机上执行的操作;后面的输入重定向,表示数据通过SSH传向远程主机。这就是说,SSH可以在用户和远程主机之间,建立命令和数据的传输通道,因此很多事情都可以通过SSH来完成。

// 将$HOME/src/目录下面的所有文件,复制到远程主机的$HOME/src/目录。
$ cd && tar czv src | ssh user@host 'tar xz'

// 将远程主机$HOME/src/目录下面的所有文件,复制到用户的当前目录。
$ ssh user@host 'tar cz src' | tar xzv

// 查看远程主机是否运行进程httpd。
$ ssh user@host 'ps ax | grep [h]ttpd'

八、绑定本地端口

  既然SSH可以传送数据,那么我们可以让那些不加密的网络连接,全部改走SSH连接,从而提高安全性。

  假定我们要让8080端口的数据,都通过SSH传向远程主机,命令就这样写:

$ ssh -D 8080 user@host

  SSH会建立一个socket,去监听本地的8080端口。一旦有数据传向那个端口,就自动把它转移到SSH连接上面,发往远程主机。可以想象,如果8080端口原来是一个不加密端口,现在将变成一个加密端口。

九、本地端口转发

  有时,绑定本地端口还不够,还必须指定数据传送的目标主机,从而形成点对点的"端口转发"。为了区别后文的"远程端口转发",我们把这种情况称为"本地端口转发"(Local forwarding)。

  假定host1是本地主机,host2是远程主机。由于种种原因,这两台主机之间无法连通。但是,另外还有一台host3,可以同时连通前面两台主机。因此,很自然的想法就是,通过host3,将host1连上host2。

  我们在host1执行下面的命令:

$ ssh -L 2121:host2:21 host3

  命令中的L参数一共接受三个值,分别是"本地端口:目标主机:目标主机端口",它们之间用冒号分隔。这条命令的意思,就是指定SSH绑定本地端口2121,然后指定host3将所有的数据,转发到目标主机host2的21端口(假定host2运行FTP,默认端口为21)。

  这样一来,我们只要连接host1的2121端口,就等于连上了host2的21端口。

  "本地端口转发"使得host1和host3之间仿佛形成一个数据传输的秘密隧道,因此又被称为"SSH隧道"。

  下面是一个比较有趣的例子。

$ ssh -L 5900:localhost:5900 host3

  它表示将本机的5900端口绑定host3的5900端口(这里的localhost指的是host3,因为目标主机是相对host3而言的)。

  另一个例子是通过host3的端口转发,ssh登录host2。

$ ssh -L 9001:host2:22 host3

  这时,只要ssh登录本机的9001端口,就相当于登录host2了。

$ ssh -p 9001 localhost

  上面的-p参数表示指定登录端口。

十、远程端口转发

  既然"本地端口转发"是指绑定本地端口的转发,那么"远程端口转发"(remote forwarding)当然是指绑定远程端口的转发。

  还是接着看上面那个例子,host1与host2之间无法连通,必须借助host3转发。但是,特殊情况出现了,host3是一台内网机器,它可以连接外网的host1,但是反过来就不行,外网的host1连不上内网的host3。这时,"本地端口转发"就不能用了,怎么办?

  解决办法是,既然host3可以连host1,那么就从host3上建立与host1的SSH连接,然后在host1上使用这条连接就可以了。

  我们在host3执行下面的命令:

$ ssh -R 2121:host2:21 host1

  R参数也是接受三个值,分别是"远程主机端口:目标主机:目标主机端口"。这条命令的意思,就是让host1监听它自己的2121端口,然后将所有数据经由host3,转发到host2的21端口。由于对于host3来说,host1是远程主机,所以这种情况就被称为"远程端口绑定"。

  绑定之后,我们在host1就可以连接host2了:

$ ftp localhost:2121

  这里必须指出,"远程端口转发"的前提条件是,host1和host3两台主机都有sshD和ssh客户端。

十一、SSH的其他参数

1、N参数,表示只连接远程主机,不打开远程shell;T参数,表示不为这个连接分配TTY。这个两个参数可以放在一起用,代表这个SSH连接只用来传数据,不执行远程操作。

$ ssh -NT -D 8080 host

2、f 参数,表示SSH连接成功后,转入后台运行。这样一来,你就可以在不中断SSH连接的情况下,在本地shell中执行其他操作。

$ ssh -f -D 8080 host

  要关闭这个后台连接,就只有用kill命令去杀掉进程。

posted @ 2021-07-20 23:15  古兰精  阅读(628)  评论(0编辑  收藏  举报