SSH(Secure Shell 的缩写)是一种网络协议,用于加密两台计算机之间的通信,并且支持各种身份验证机制。主要用于保证远程登录和远程通信的安全。
SSH 的软件架构是服务器-客户端模式(Server - Client)。在这个架构中,SSH 软件分成两个部分:向服务器发出请求的部分,称为客户端(client),OpenSSH 的实现为 ssh;接收客户端发出的请求的部分,称为服务器(server),OpenSSH 的实现为 sshd。
客户端安装ssh
Linux 系统一般都自带 ssh,如果没有就需要安装。
1 | Ubuntu |
连接远程机器
1 | p 指定端口号 默认22 user为用户名 hostname为连接的主机 |
- 首次登录会出现提醒。表示不认识这台机器,提醒用户确认是否需要连接。
1 | The authenticity of host 'foo.com (192.168.121.111)' can't be established. |
服务器指纹,指的是 SSH 服务器公钥的哈希值。每台 SSH 服务器都有唯一一对密钥,用于跟客户端通信,其中公钥的哈希值就可以用来识别服务器。
ssh 会将本机连接过的所有服务器公钥的指纹,都储存在本机的
~/.ssh/known_hosts
文件中。每次连接服务器时,通过该文件判断是否为陌生主机(陌生公钥)。然后,客户端就会跟服务器建立连接。接着,ssh 就会要求用户输入所要登录账户的密码。用户输入并验证密码正确以后,就能登录远程服务器的 Shell 了。
客户端配置文件
SSH 客户端的全局配置文件是/etc/ssh/ssh_config
,用户个人的配置文件在~/.ssh/config
,优先级高于全局配置文件。
- 按照不同服务器,列出各自的连接参数,从而不必每一次登录都输入重复的参数
1 | Host remoteserver |
- 登录
remote.example.com
时,只要执行ssh remoteserver
命令,就会自动套用 config 文件里面指定的参数。
1 | ssh remoteserver |
SSH 密钥登录
SSH 默认采用密码登录,这种方法有很多缺点,简单的密码不安全,复杂的密码不容易记忆,每次手动输入也很麻烦。密钥登录是比密码登录更好的解决方案。
密钥(key)是一个非常大的数字,通过加密算法得到。对称加密只需要一个密钥,非对称加密需要两个密钥成对使用,分为公钥(public key)和私钥(private key)。
密钥登录的过程
客户端通过
ssh-keygen
生成自己的公钥和私钥。ssh-key
生成密钥
1
2
3
4
5ssh-keygen -t rsa -b 4096 -C "your_email@domain.com"
生成的密钥文件默认就会是~/.ssh/id_rsa(私钥)和~/.ssh/id_rsa.pub(公钥)。
-t 指定加密算法
-b 参数指定密钥的二进制位数。这个参数值越大,密钥就越不容易破解,但是加密解密的计算开销也会加大。
-C 参数可以为密钥文件指定新的注释,格式为username@host。手动将客户端的公钥放入远程服务器的指定位置。
- OpenSSH 规定,用户公钥保存在服务器的
~/.ssh/authorized_keys
文件。你要以哪个用户的身份登录到服务器,密钥就必须保存在该用户主目录的~/.ssh/authorized_keys
文件。
- OpenSSH 规定,用户公钥保存在服务器的
客户端向服务器发起 SSH 登录的请求。
服务器收到用户 SSH 登录的请求,发送一些随机数据给用户,要求用户证明自己的身份。
客户端收到服务器发来的数据,使用私钥对数据进行签名,然后再发还给服务器。
服务器收到客户端发来的加密签名后,使用对应的公钥解密,然后跟原始数据比较。如果一致,就允许用户登录。
服务器安装sshd
如果没有安装 sshd,可以用下面的命令安装。
1 | Ubuntu |
1 | 启动 默认启动 |
1 | 通过 Systemd 管理 sshd |
sshd 配置文件
- sshd 的配置文件在
/etc/ssh
目录,主配置文件是sshd_config
。
1 | sshd 配置项 |
1 | 修改配置文件以后,可以使用下面的命令验证,配置文件是否有语法错误 |
SSH 端口转发
SSH 除了登录服务器,还有一大用途,就是作为加密通信的中介,充当两台服务器之间的通信加密跳板,使得原本不加密的通信变成加密通信。这个功能称为端口转发(port forwarding),又称 SSH 隧道(tunnel)。
端口转发有两个主要作用:
- 将不加密的数据放在 SSH 安全连接里面传输,使得原本不安全的网络服务增加了安全性,比如通过端口转发访问 Telnet、FTP 等明文服务,数据传输就都会加密。
- 作为数据通信的加密跳板,绕过网络防火墙。
端口转发有三种使用方法:动态转发,本地转发,远程转发。
动态转发
- 本机与 SSH 服务器之间创建了一个加密连接,然后本机内部针对某个端口的通信,都通过这个加密连接转发。它的一个使用场景就是,访问所有外部网站,都通过 SSH 转发。
- 动态转发需要把本地端口绑定到 SSH 服务器。至于 SSH 服务器要去访问哪一个网站,完全是动态的,取决于原始通信,所以叫做动态转发。
1 | ssh -D local-port tunnel-host -N |
1 | ssh -D 2121 tunnel-host -N |
本地转发
- SSH 服务器作为中介的跳板机,建立本地计算机与特定目标网站之间的加密连接。本地转发是在本地计算机的 SSH 客户端建立的转发规则。
- 它会指定一个本地端口(local-port),所有发向那个端口的请求,都会转发到 SSH 跳板机(tunnel-host),然后 SSH 跳板机作为中介,将收到的请求发到目标服务器(target-host)的目标端口(target-port)。
1 | ssh -L local-port:target-host:target-port tunnel-host |
1 | ssh -L 2121:www.example.com:80 tunnel-host -N -f |
远程转发
- 这种场景比较特殊,主要针对内网的情况。本地计算机在外网,SSH 跳板机和目标服务器都在内网,而且本地计算机无法访问内网之中的 SSH 跳板机,但是 SSH 跳板机可以访问本机计算机。
- 由于本机无法访问内网 SSH 跳板机,就无法从外网发起 SSH 隧道,建立端口转发。必须反过来,从 SSH 跳板机发起隧道,建立端口转发,这时就形成了远程端口转发。
1 | ssh -R local-port:target-host:target-port local -N |
1 | ssh -R 2121:www.example.com:80 local -N |