SSH(Secure Shell,安全外壳)是一种网络安全协议,通过加密和认证机制实现安全的访问和文件传输等业务。传统远程登录和文件传输方式,例如 Telnet、FTP,使用明文传输数据,存在很多的安全隐患。随着人们对网络安全的重视,这些方式已经慢慢不被接受。SSH 协议通过对网络数据进行加密和验证,在不安全的网络环境中提供了安全的网络服务。
SSH 实现安全的基础是非对称加密(如:RSA)。SSH 支持三种认证方式:password(密码)、publickey(公钥)、password+publick。所有这些认证方式的基础都是非对称加密,后面会详细说明。
SSH 是一种协议和规范,我们真正使用的是具体的实现了这套协议规范的软件,最常见的就是 OpenSSH、PuTTY 等。本文涉及到的使用技巧等都是基于 OpenSSH。
SSH之所以能够保证安全,原因在于它采用了公钥加密。
整个过程是这样的:(1)远程主机收到用户的登录请求,把自己的公钥发给用户。(2)用户使用这个公钥,将登录密码加密后,发送回来。(3)远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。
这个过程本身是安全的,但是实施的时候存在一个风险:如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。因为不像 https 协议,SSH 协议的公钥是没有证书中心(CA)公证的,也就是说,都是自己签发的。
可以设想,如果攻击者插在用户与远程主机之间(比如在公共的wifi区域),用伪造的公钥,获取用户的登录密码。再用这个密码登录远程主机,那么 SSH 的安全机制就荡然无存了。这种风险就是著名的"中间人攻击"(Man-in-the-middle attack)。
为了应对这种风险,每次在第一次登录远程主机时,软件会把对方的公钥信息展示出来,让用户根据这些信息决定是否继续登录。
$ 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)?
如果用户选择“yes”,那么这个证书就被认为是安全的,并且会被放到 $HOME/.ssh/known_hosts
,后面再次登录时,软件会自动完成证书校验。
参考:
这种认证方式流程如上图所示。客户端使用公钥把密码加密后发送给服务端,服务端使用自己的私钥解密后对密码进行验证,验证成功,则建立链接,并进行后续操作。
要使用这种方式,首先需要修改服务端配置 /etc/ssh/sshd_config
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
然后把客户端的公钥添加到服务端的列表中,一般有两种方式。一种是使用 ssh-copy-id user@host
;另外一种方式是直接把客户端公钥添加到服务端的 authorized_keys
中。authorized_keys
的默认路径为 $HOME/.ssh/authorized_keys
。
所谓"公钥登录",原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。
用于生成本地的认证信息,最常用的是生成 RSA 密钥对。
# -b bits 指定要创建的秘钥中的位数,默认 2048 位。值越大,密码越复杂
# -C comment 注释,在 id_rsa.pub 中末尾
# -t rsa/dsa等 指定要创建的秘钥类型,默认为 RSA
# -f filename 指定公私钥的名称,会在 $HOME/.ssh 目录下生产私钥 filename 和公钥 filename.pub
# -N password 指定使用秘钥的密码,使得多人使用同一台机器时更安全
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
用于把本地公钥复制到服务端。需要注意的是,这个命令会附加到 $HOME/.ssh/authorized_keys
中,$HOME
是 user@host
中指定的用户
ssh-copy-id user@host
autossh 用于自动重启 ssh 命令。比如用 ssh 做端口转发时,要在 ssh 因某些原因退出后自动重新建立链接,就可以使用 autossh
usage: autossh [-V] [-M monitor_port[:echo_port]] [-f] [SSH_OPTIONS]
autossh -M 0 -f user@127.0.0.1 -N -D 0.0.0.0:8080
上面的命令等同于 ssh -Nf -D 0.0.0.0:8080 user@127.0.0.1
,但是会自动重连。
参考 SSH 教程