跳转至

SSH

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

SSH概述

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

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上启动一个网络服务