深入理解SSH

Mar 13, 2015   #Linux  #SSH 

ssh命令使用过很多年了,一直没有深入理解。最近配置免密码登陆认证的时候碰到了很多问题,觉得还是要好好学习一下。下面是我整理的一些资料和自己的理解,主要参考了《SSH权威指南》和一些blog(文末给出)。本文假设你已经有了SSH最基础的使用经验以及对RSA加密系统最基础的了解(会使用ssh登陆远程主机、知道公钥私钥就行了)。

SSH基础

SSH分为密码认证和公钥认证两种认证方式,下面是各自的流程。

密码认证

  1. 客户端请求SSH服务器,服务器发送其公钥给客户端。
  2. 客户端使用服务器返回的公钥,加密自己的通讯密钥(客户端产生的密钥,不是用户的公钥或私钥),而后发给服务器。
  3. 服务器使用自己的私钥解密通讯密钥,至此,双方建立起了安全的通讯信道。
  4. 客户端将用户名和密码加密后发送给服务器进行验证

公钥认证

  1. 客户生成密钥对后,将公钥上传到服务器上(一般存放在~/.ssh/authorized_keys文件中)
  2. 登陆时,客户端发送包含用户名、公共密钥和公共密钥算法的 认证请求给服务器端。
  3. 服务器对认证请求进行检查。

中间人攻击

在密码认证过程中,如何确定连接上的主机就是自己要连接的呢?(比如登陆请求被劫持,冒充远程主机,骗取用户的账户和密码)

为了解决这个问题,SSH使用了一个首次验证的解决方案,第一次登陆某个主机时,客户端将提示是否将服务器的公钥指纹将如可信列表(一般是~/.ssh/known_hosts)。

这样,之后若登陆时,服务器返回的公钥指纹与可信列表中不同,则有可能被劫持了。

ssh-keygen

ssh-keygen是用来生成密钥的,具体用法请参考man或者其他博客。 这里要说的是,ssh-keygen生成密钥的过程中,会提示用户输入passphrase(口令),一般为了方便就直接为空了。

这样是有很大风险的。在公钥认证的时候,客户端仍会提示用户输入口令。(设想没有口令,任何人使用你的机器都能登陆到远程主机)。

因此,建议配置口令。

ssh-copy-id

生成密钥对之后,可以使用此命令将本地的公钥添加到远程主机中。

ssh-agent

前面说了,虽然使用了公钥认证,不用输入密码了,但仍需要输入密钥口令。ssh-agent将私钥保存在内存中,ssh客户端开始会话的时候,相ssh-agent请求私钥。一般而言ssh-agent会在~/.login或者 ~/.Xsession 自启动,之后打开的终端都是ssh-agent的客户端。

这也是我们很少使用这个命令的原因。值得注意的是,ssh-agent中保存的私钥都在内存中,故重启后,需要重新添加私钥。

ssh-add

ssh-agent用来把私钥保存到内存中,而ssh-add用来将管理ssh-agent中的密钥。初始时,ssh-agent中并没有私钥。默认情况下,ssh-ad将~/.ssh/id_rsa~/.ssh/id_dsa~/.ssh/id_ecdsa~/.ssh/identity 都添加到ssh-agent中去。

ssh-add也可以将ssh-agent中的私钥清除。

如何配置免密码、口令登陆

  1. 选择公钥认证且将密钥口令设为空。(不安全,任何人使用你的机器都可以登录到远程主机)
  2. 将私钥添加到ssh-agent中,不需要时再删去(推荐)。

SSH转发

SSH登陆之后,本地和远程主机都运行着SSH的进程。因此,可以完成一些好玩的功能。

本地转发

假如我想访问一个网站(http://p.nju.edu.cn),但是我的本地主机不能访问,而远程主机却可以访问。此时,我就希望远程主机可以代替我访问此网站。具体流程如下:

  1. 本地的SSHH客户端建立一个监听端口,如8989
  2. 我访问本地的监听端口,如在浏览器里访问 http://localhost:8989
  3. 本地的SSH客户端将监听到我的HTTP请求,将其转发给远程SSH服务器。
  4. 远程SSH服务器,将我的请求转发给 p.nju.edu.cn 的 80端口。
  5. 远程SSH服务器将转发后收到的数据,传回给本地SSH客户端。

由上述流程可以看出,需要的参数有:本地SSH客户端的监听端口,远程SSH服务器的转发地址转发端口

因此,命令可以写为

 ssh -L 8989:p.nju.edu.cn:80 user@sshserver

远程转发

本地转发即SSH客户端将数据转发给SSH服务器,如果反过来,即SSH服务器将其上的数据,发给SSH客户端,即变成了远程转发。

假设,现在远程主机不能访问(http://p.nju.edu.cn),而本地服务器可以。建立远程转发,使远程服务器能访问网站。流程如下:

  1. 远程SSH服务器建立一个监听端口,如8989。
  2. 当SSH服务器接收到监听端口中的数据后,发送给本地SSH客户端。
  3. SSH客户端收到数据后,转发给 p.nju.edu.cn 的 80端口。
  4. SSH客户端将转发后收到的数据,传回给远程SSH服务器。

上述流程需要的参数有:SSH服务器的监听端口,远本地SSH客户端的转发地址转发端口

命令可以写为

ssh -R 8989:p.nju.edu.cn:80 user@sshserver

动态转发

上述转发,只能将数据转发给特定和主机和端口,而动态转发是应用层的端口转发,能根据请求的协议类型,将其转发至正确的主机和端口。此时,ssh相当于一个SOCKS代理。

ssh -D 8989 user@sshserver

动态转发只需要一个本地监听端口,此端口收到的数据,将由SSH服务器转发给相应的主机和端口。

参考资料

  1. 《SSH权威指南》
  2. http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html
  3. http://blog.sina.com.cn/s/blog_66474b1601016ium.html
  4. http://blog.csdn.net/macrossdzh/article/details/5691924

Written with StackEdit.