Linux 下使用 SSH 实现安全远程访问

CompTIABeginner
立即练习

介绍

在本实验中,你将学习使用 Secure Shell (SSH) 协议保护 Linux 系统远程访问的基础知识。你将获得 SSH 核心功能的实践经验,包括设置基于密钥的认证以增强安全性、在系统间安全地传输文件以及创建 SSH 隧道进行端口转发。

你将首先设置一个 Docker 容器来模拟远程服务器环境,使实验更具真实性。然后,你将在你的主机上安装 OpenSSH 客户端,并使用 ssh-keygen 工具生成一个新的 RSA 密钥对。接下来,你将配置 Docker 服务器以接受此密钥进行认证,从而在你的主机和容器化服务器之间建立安全的、无需密码的连接。最后,你将练习使用 scp 命令进行安全文件传输,以及使用 ssh -L 命令将本地端口转发到远程服务,从而有效地创建一个安全隧道。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 81%。获得了学习者 96% 的好评率。

设置 Docker SSH 服务器并生成密钥对

在此步骤中,你将设置一个 Docker 容器来模拟远程 SSH 服务器,并在你的主机上生成一个安全的密钥对。这种方法通过将客户端(你的主机)与服务器(Docker 容器)分离,提供了一个更真实的环境。

由于此环境中已安装 Docker 和 OpenSSH 客户端,你可以直接进行服务器配置。

首先,确保 Docker 服务正在运行:

sudo systemctl start docker
sudo systemctl enable docker

现在,让我们创建一个将作为我们 SSH 服务器的 Docker 容器。我们将使用 Ubuntu 作为基础镜像,并为其配置 SSH 服务器功能。创建一个 Dockerfile:

cat > Dockerfile << 'EOF'
FROM ubuntu:22.04

## 安装 OpenSSH 服务器和其他实用工具
RUN apt-get update && \
    apt-get install -y openssh-server nginx sudo && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

## 创建一个用于 SSH 访问的用户
RUN useradd -m -s /bin/bash sshuser && \
    echo 'sshuser:password123' | chpasswd && \
    usermod -aG sudo sshuser

## 配置 SSH
RUN mkdir /var/run/sshd && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config && \
    sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
    sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config

## 为用户创建 SSH 目录
RUN mkdir -p /home/sshuser/.ssh && \
    chown sshuser:sshuser /home/sshuser/.ssh && \
    chmod 700 /home/sshuser/.ssh

## 暴露 SSH 端口
EXPOSE 22 80

## 启动 SSH 服务
CMD ["/usr/sbin/sshd", "-D"]
EOF

构建 Docker 镜像:

sudo docker build -t ssh-server .

运行 Docker 容器,将你的主机的端口 2222 映射到容器的端口 22:

sudo docker run -d --name ssh-lab-server -p 2222:22 -p 8080:80 ssh-server

验证容器是否正在运行:

sudo docker ps

你应该会看到显示正在运行的容器的输出:

CONTAINER ID   IMAGE        COMMAND               CREATED         STATUS         PORTS                                        NAMES
...            ssh-server   "/usr/sbin/sshd -D"   ...             Up ...         0.0.0.0:2222->22/tcp, 0.0.0.0:8080->80/tcp   ssh-lab-server

接下来,你将生成一个 SSH 密钥对。SSH 密钥提供了一种比仅使用密码更安全的通过 SSH 登录服务器的方式。密钥对包含一个必须保密的 私钥 (private key) 和一个可以共享的 公钥 (public key)。

我们将使用 ssh-keygen 命令创建新的密钥对。我们将密钥类型指定为 rsa,密钥大小指定为 2048 位以获得强大的安全性。-f 标志允许我们为密钥指定文件名,这有助于组织它们。我们将密钥命名为 ~/.ssh/id_rsa_lab_ssh

运行以下命令。当提示输入密码短语 (passphrase) 时,只需按两次 Enter 键即可继续,无需设置密码短语。在本实验中,为简化起见,我们将省略密码短语,但在实际场景中,你应该始终使用强密码短语来保护你的私钥。

ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa_lab_ssh

该命令将生成密钥对,并显示文件保存位置。

Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/labex/.ssh/id_rsa_lab_ssh
Your public key has been saved in /home/labex/.ssh/id_rsa_lab_ssh.pub
The key fingerprint is:
SHA256:... labex@...
The key's randomart image is:
+---[RSA 2048]----+
|        .o*+..   |
|       . =.o. .  |
|      . o o. .   |
|       o .  .    |
|      . S        |
|     . . .       |
|      o .        |
|     o .         |
|    E .          |
+----[SHA256]-----+

为了确认密钥文件已创建,你可以列出 ~/.ssh 目录的内容。你应该会看到你的新私钥 (id_rsa_lab_ssh) 和公钥 (id_rsa_lab_ssh.pub)。

ls -l ~/.ssh/id_rsa_lab_ssh*

输出将类似于此,显示两个新文件:

-rw------- 1 labex labex 1876 ... /home/labex/.ssh/id_rsa_lab_ssh
-rw-r--r-- 1 labex labex  401 ... /home/labex/.ssh/id_rsa_lab_ssh.pub

你现在已成功安装了 SSH 服务器并创建了密钥对,你将在后续步骤中使用它们来配置和测试安全认证。

配置并测试 SSH 基于密钥的认证

在此步骤中,你将配置 Docker SSH 服务器以识别你的公钥,从而允许你无需密码即可登录。此过程包括将你的公钥复制到 Docker 容器,然后测试连接。

为了让 SSH 服务器使用你的密钥进行身份验证,你的公钥必须放在服务器上的 ~/.ssh/authorized_keys 文件中。由于我们的服务器运行在 Docker 容器中,我们需要将公钥从你的主机复制到容器。

首先,使用 docker cp 命令将你的公钥复制到 Docker 容器:

sudo docker cp ~/.ssh/id_rsa_lab_ssh.pub ssh-lab-server:/home/sshuser/.ssh/authorized_keys

接下来,我们需要在容器内设置正确的文件权限。SSH 对安全性非常敏感,如果权限过于开放,它将拒绝使用密钥。执行以下命令来设置正确的权限:

sudo docker exec ssh-lab-server chown sshuser:sshuser /home/sshuser/.ssh/authorized_keys
sudo docker exec ssh-lab-server chmod 600 /home/sshuser/.ssh/authorized_keys

添加公钥并设置权限后,你就可以测试基于密钥的认证了。你将尝试使用端口 2222(我们已将其映射到容器的端口 22)以 sshuser 用户身份 SSH 进入 Docker 容器,并指定你创建的私钥。

使用带有 -i 标志指向你的私钥文件,以及 -p 指定端口的 ssh 命令:

ssh -i ~/.ssh/id_rsa_lab_ssh -p 2222 sshuser@localhost

由于这是你第一次连接到新主机,系统可能会要求你验证主机的真实性。输入 yes 并按 Enter

The authenticity of host '[localhost]:2222 ([127.0.0.1]:2222)' can't be established.
ED25519 key fingerprint is SHA256:....
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:2222' (ED25519) to the list of known hosts.

如果一切配置正确,你将立即登录,而不会被要求输入密码。你将看到欢迎消息,并且你的命令提示符会发生变化,显示你现在位于 Docker 容器内:

Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-88-generic x86_64)
...
sshuser@containerid:~$

要退出 SSH 会话并返回到你的主机终端提示符,只需键入 exit 并按 Enter

exit

成功无需密码登录,证实了你的基于密钥的认证在你的主机和 Docker 容器之间正常工作。这种方法比传统的密码认证更安全。

使用 scp 安全地传输文件

在此步骤中,你将学习如何使用 安全拷贝协议 (scp) 在主机之间安全地传输文件。scp 利用底层的 SSH 协议,这意味着它受益于你已配置的相同加密和认证机制,包括基于密钥的认证。

首先,让我们在当前工作目录 ~/project 中创建一个示例文件,用于传输。我们将文件命名为 source_file.txt

echo "This is a test file for scp." > source_file.txt

你可以通过列出文件来验证文件是否已创建:

ls -l source_file.txt

输出应显示你新创建的文件:

-rw-r--r-- 1 labex labex 29 ... source_file.txt

现在,你将使用 scpsource_file.txt 复制到 Docker 容器的 /tmp 目录,演示如何安全地将文件传输到远程服务器。scp 的基本语法是 scp -i [private_key] -P [port] [source_file] [user]@[host]:[destination_path]

你将使用 -i 标志指定你的私钥,-P 指定端口 2222(我们的 Docker 容器的 SSH 端口),并将文件传输到容器上的 sshuser 账户:

scp -i ~/.ssh/id_rsa_lab_ssh -P 2222 source_file.txt sshuser@localhost:/tmp/destination_file.txt

你将看到指示文件传输进度的输出,对于小文件来说,这应该是瞬时的。

source_file.txt                                   100%   29     6.7KB/s   00:00

为了确认文件已成功复制,请连接到 Docker 容器并列出目标文件:

sudo docker exec ssh-lab-server ls -l /tmp/destination_file.txt

输出将确认已复制文件的存在和详细信息:

-rw-r--r-- 1 sshuser sshuser 29 ... /tmp/destination_file.txt

你还可以验证文件内容是否已正确传输:

sudo docker exec ssh-lab-server cat /tmp/destination_file.txt

这应该会显示:

This is a test file for scp.

你现在已成功使用 scp 传输了文件,演示了一种在网络上安全地移动系统之间数据的方法。

使用 ssh -L 创建 SSH 隧道进行端口转发

在此步骤中,你将学习 SSH 最强大的功能之一:隧道(tunneling),也称为端口转发(port forwarding)。这允许你将本地机器上的端口的网络流量安全地转发到远程服务器上的端口,有效地将未加密的协议封装在安全的 SSH 连接中。我们将练习本地端口转发

为了演示这一点,我们需要一个运行在某个端口上的服务,以便连接。幸运的是,我们的 Docker 容器已经安装并配置了 Nginx。我们需要在容器内启动 Nginx 服务。

首先,在 Docker 容器内启动 Nginx 服务:

sudo docker exec ssh-lab-server service nginx start

你可以验证 Nginx 是否在容器内正常运行:

sudo docker exec ssh-lab-server service nginx status

输出应显示服务正在运行:

 * nginx is running

现在,让我们创建 SSH 隧道。我们将使用带有 -L 标志的 ssh 命令,该标志代表本地端口转发。语法是 ssh -L [LOCAL_PORT]:[DESTINATION_HOST]:[DESTINATION_PORT] [USER]@[SERVER]

我们将把本地机器上的端口 9090 的流量转发到 Docker 容器内的端口 80-N 标志告诉 SSH 不执行远程命令,这对于仅转发端口非常理想。请注意,我们使用端口 2222 来连接我们的 Docker 容器的 SSH 服务。

执行此命令。此命令将占用你当前的终端,并且不会返回提示符。 你需要打开一个新的终端来测试隧道。

ssh -i ~/.ssh/id_rsa_lab_ssh -N -L 9090:localhost:80 -p 2222 sshuser@localhost

现在,打开一个新的终端,方法是点击终端标签栏中的 + 图标。在这个新终端中,你可以使用 curl 来测试隧道。通过访问 localhost:9090,你的请求将通过 SSH 安全地隧道传输到 Docker 容器内的端口 80

curl http://localhost:9090

你应该会看到默认 Nginx 欢迎页面的 HTML 内容,这证实了隧道正在工作。

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

你已成功创建了一个安全隧道,将流量从你的主机转发到 Docker 容器内运行的服务。要关闭连接,请返回第一个终端(运行 ssh 命令的终端)并按 Ctrl+C。然后你可以关闭第二个终端。

总结

在本实验中,你学习了使用安全 Shell (SSH) 协议在 Linux 系统上保护远程访问的基本技能。涵盖的关键目标包括设置和测试基于密钥的认证、使用 scp 安全地传输文件以及创建用于端口转发的 SSH 隧道。

你首先准备了环境,包括更新系统的软件包列表并安装 openssh-serveropenssh-client 软件包。在验证 SSH 服务处于活动状态后,你使用 ssh-keygen 命令生成了一个安全的 2048 位 RSA 密钥对。这一基础步骤创建了后续步骤中建立安全、无密码连接所需的公钥和私钥。