跳转至

SSH

约 1499 个字 2 行代码 2 张图片 预计阅读时间 5 分钟

SSH 概述

SSH 是一种加密的网络协议,用于安全地访问远程计算机。一般来说,服务器物理机往往位于机房中,我们在服务器上进行开发时通常使用 SSH 远程连接到服务器上进行开发。

SSH 基于 TCP 协议,其默认端口为 22

SSH 认证原理

当你要通过 SSH 连接到服务器上时,需要认证你的身份。 常见的认证方式有两种:

  • 口令认证(password)
    • 当尝试连接到目标主机时,会要求你输入当前主机上你要连接的用户的密码,输入成功即可成功连接

在生产环境中请不要开启 ssh 的口令登录

  • 公私钥认证(publickey)
    • 在连接时,主机和你的电脑将会进行多次交互以验证你当前使用的私钥是否与其允许连接的公钥中(一般储存在 ~/.ssh/authorized_keys 中)的某一个相匹配,如果匹配则连接成功

如何配置公私钥认证登录(极简版)

  1. 在本机上运行 ssh-keygen 生成一对公私钥
  2. 将公钥(.pub)拷贝到服务器的 ~/.ssh/authorized_keys

公私钥认证登录详细教程

不要通过网络传输私钥

公钥可以公开,但是私钥不能泄露。 获取私钥相当于获取了你在服务器上的所有权限,不要通过网络传递明文私钥文件

中间人攻击

SSH 协议可以被中间人攻击。

即你在连接服务器时,中间人劫持你的请求并冒充服务器与你交互,同时冒充连接者利用你的交互信息尝试连接服务器。这样攻击者就可以成功连接到服务器以你的权限进行任意操作。同时,如果攻击者在自己的计算机上转发你的请求到服务器并将服务器的回复转发给你,便可成功监听你们的会话,并且难以被发现。

为了避免中间人攻击,ssh 客户端会在 ~/.ssh/known_hosts 中存储连接过的主机及其指纹(一个哈希值,可以认为这个哈希值唯一确认了目标主机)。当尝试连接时,ssh 客户端会获取对方的指纹并在 ~/.ssh/known_hosts 查找是否已经记录过该指纹。

  1. 已经记录过该指纹且与当前连接的服务器指纹相匹配
    • 此时认为对端主机即为我们希望连接的主机,认证通过。
  2. 已经记录过该指纹但与当前连接的服务器指纹不匹配

    • 此时认为发生了中间人攻击,弹出警告并中断连接
  3. 未记录过该指纹

    • 弹出提示给出对端主机的指纹,让用户确认是否要继续连接。(如果输入 yes,继续连接的同时会将此指纹与目标主机绑定记录在 known_hosts 中)
可能并不是中间人攻击?

在上述列举情况的第二种情况出现时仅仅代表当前连接的服务器的指纹不与我们之前记录的指纹相匹配,并不能断定我们的会话被劫持了。

事实上,如果服务器的 sshd 服务被重装了也会导致指纹发生改变(通常发生在系统重装时)。如果我们在重装前连接过此主机,在重装后再次连接时也会弹出对应的警告。

无视警告,继续连接!

如果已经确认我们的会话并未被劫持,而是对端主机的指纹被修改后,我们可以进入 known_hosts 文件中删除原来的记录,并再次尝试连接,此时将出现第三种情况。

无视风险,不验证指纹

在一些场景中如 MPI,我们需要通过 SSH 来控制多机共同运行程序,此时如果连接的主机的指纹未被记录将会被上述认证机制所阻塞。如果需要控制的机器较多,无法逐一手动记录指纹,可以在 ~/.ssh/config 中添加如下配置忽略所有指纹的认证:

Host *
    StrictHostKeyChecking no

启用此配置时请确保当前的网络环境是足够安全的,在不安全的网络环境下上述配置可以让攻击者成功完成中间人攻击

常用的 ssh 命令

在命令行中我们使用 ssh 来进行连接等操作,常用的 ssh 的命令可参考:

常用 ssh 命令

使用 IDE 基于 SSH 连接远程服务器

常见的 IDE 如 VSCode(推荐), jetbrains 系列等均有远程连接功能。

参考链接:

练习题

  1. 在 Linux 主机中查看主机 IP 地址。配置 sshd 服务设置,打开密码登录和公私钥验证登录
  2. 在自己的电脑上使用命令行命令分别通过密码登录和公私钥验证登录的方式登录到服务器
  3. 配置自己的电脑 .ssh/config 文件,从而可以通过 ssh <hostname> 直接连接到 Linux 主机
  4. 尝试使用 IDE 中的远程连接功能连接到服务器并进行代码开发(编写 hello.c 并编译运行)

  5. (选做)使用 ssh -L 进行端口转发,将 Linux 主机上的本地网络服务转发到自己的电脑上并在浏览器中成功访问

在 Linux 主机上启动测试网络服务的方法
  1. 使用 Linux 系统自带的包管理器安装 nginx,如 ubuntu 中可以使用 sudo apt install nginx 安装。如果你使用了我们配置好的标准开发环境,nginx 已经预装好了,无需安装。
  2. 运行 systemctl start nginx 即会在 localhost:80 上启动一个网络服务