SSH 隧道与端口转发

网络安全Beginner
立即练习

简介

Secure Shell (SSH) 不仅仅是一个远程终端访问工具,它还是一个功能强大的网络实用程序。SSH 隧道(SSH Tunneling),也称为 SSH 端口转发,允许你通过安全的 SSH 连接将本地网络流量路由到远程主机。

其核心思想是借用另一台机器的连接能力。隧道并不会凭空创造新的网络可达性,而是复用了远程主机的网络位置和访问权限。

这项技术被系统管理员、开发人员和安全专家广泛使用,用于绕过严格的企业防火墙、加密旧版应用程序流量,以及访问那些未直接暴露在公共互联网上的隐藏内部服务。

在本实验中,你将学习两种主要 SSH 端口转发类型的概念及其实际应用:

  • **本地端口转发 (-L)**:将端口从你的本地机器转发到远程目的地。
  • **远程端口转发 (-R)**:将端口从远程服务器转发回你的本地机器。

理解网络拓扑

在这一步中,我们将探索为你准备的模拟网络环境。

为了练习 SSH 隧道,我们需要一个涉及多台机器的场景。由于我们是在单个虚拟机环境中工作,我们通过本地系统 (127.0.0.1) 上的不同网络端口模拟了一个复杂的网络拓扑。

以下是我们模拟的概念映射:你的「本地机器」由当前的终端会话表示。「堡垒机」(或边缘服务器)通过一个 Docker 容器模拟,该容器在 127.0.0.1:2222 上暴露 SSH 服务。「内部服务」是一个运行在同一私有 Docker 网络 172.31.0.20:80 上的 Web 服务器。从概念上讲,可以将其想象为深藏在企业网络内部且被防火墙阻隔的服务,这意味着它只能从堡垒机访问。最后,「本地服务」是运行在 LabEx 虚拟机 8000 端口上的 Web 服务器。你可以将其视为运行在你个人笔记本电脑上,并希望与互联网上的某人共享的开发服务器。

让我们验证模拟的服务是否正在运行。我们将使用 curl 命令,这是一个用于通过 URL 传输数据的命令行工具。

首先,检查运行在 8000 端口上的「本地服务」:

curl http://127.0.0.1:8000

你应该会看到输出 Local Developer Machine Data。

内部服务特意没有直接暴露在 LabEx 虚拟机上。你将在下一步通过 SSH 隧道访问它。

在接下来的步骤中,我们将使用 SSH 隧道来操纵访问这些服务的方式,从而模拟现实世界中的防火墙绕过场景。

配置本地端口转发 (-L)

在这一步中,你将配置本地端口转发。

想象一下,你身处家中,需要访问一个内部企业仪表板(即我们位于 172.31.0.20:80 的服务)。防火墙阻止了从外部世界直接访问该内部地址。然而,防火墙允许与特定的边缘服务器(我们的堡垒机)建立 SSH 连接。

本地端口转发允许你在本地机器上打开一个端口,SSH 会将发送到该本地端口的所有流量通过 SSH 隧道安全地转发到目的地。

本地端口转发的语法为:ssh -L [local_port]:[destination_host]:[destination_port] [user]@[ssh_server]

本地转发最容易理解的方式是:「让远程服务看起来就像是在本地一样」。

我们将通过模拟的 SSH 堡垒机,将本地端口 8080 转发到内部服务 (172.31.0.20:80)。我们还将使用两个额外的标志:-N 标志告诉 SSH 不要执行远程命令,这在你只想转发端口时非常有用;-f 标志告诉 SSH 在后台运行,使我们可以继续使用终端。

执行以下命令来创建隧道:

ssh -N -f -L 8080:172.31.0.20:80 \
  -o StrictHostKeyChecking=no \
  -o UserKnownHostsFile=/dev/null \
  -i ~/project/pivot_key -p 2222 pivot@127.0.0.1

隧道现在正在后台静默运行。

现在,让我们测试一下隧道。你将访问新打开的本地端口 8080,而不是直接访问内部 Docker 地址。SSH 隧道会捕获此请求,对其进行加密,发送到堡垒机,然后由堡垒机将其转发到 172.31.0.20:80。

curl http://127.0.0.1:8080

你应该会看到 Secret Internal Corporate Data 的输出。你已经成功绕过了概念上的防火墙!

配置远程端口转发 (-R)

在这一步中,你将配置远程端口转发。

想象一下,你正在本地笔记本电脑上开发一个 Web 应用程序(即我们端口 8000 上的服务)。你想向客户展示你的进度,但你的笔记本电脑位于家用路由器(NAT)之后,没有公网 IP 地址。

远程端口转发通过允许你连接到公共 SSH 服务器并在「该远程服务器上」打开一个端口来解决这个问题。任何到达该远程端口的流量都会通过 SSH 隧道转发回你的本地机器。

远程端口转发的语法为:ssh -R [remote_port]:[local_host]:[local_port] [user]@[ssh_server]

远程转发转换了视角:「让我的本地服务看起来可以从远程端访问」。

我们将把本地服务 (127.0.0.1:8000) 暴露给堡垒机的 8081 端口。

执行以下命令来创建远程隧道:

ssh -N -f -R 8081:127.0.0.1:8000 \
  -o StrictHostKeyChecking=no \
  -o UserKnownHostsFile=/dev/null \
  -i ~/project/pivot_key -p 2222 pivot@127.0.0.1

隧道现在已在后台建立。堡垒机现在正在监听 8081 端口。当有人访问远程服务器上的 8081 端口时,流量会被发送回你的本地 8000 端口。

让我们通过堡垒机容器查询转发的服务来测试这一点:

docker exec bastion_host curl -s http://127.0.0.1:8081

你应该会看到 Local Developer Machine Data 的输出。你已经成功将本地服务暴露给了远程服务器!

访问内部 Web 服务

在最后一步中,我们将通过使用已创建的隧道下载数据并将其保存到项目目录中的文件中,来巩固我们的理解。

确保你位于默认的项目目录中:

cd ~/project

首先,使用本地端口转发隧道(端口 8080)获取内部企业数据,并将其保存到名为 internal_data.txt 的文件中。我们将使用 curl 的 -o 标志来指定输出文件。

curl http://127.0.0.1:8080 -o internal_data.txt

接下来,使用远程端口转发隧道(端口 8081)通过堡垒机获取本地开发数据,并将其保存到名为 remote_data.txt 的文件中。

docker exec bastion_host curl -s http://127.0.0.1:8081 > remote_data.txt

最后,使用 cat 命令验证你刚刚下载的文件内容:

cat internal_data.txt
cat remote_data.txt
Secret Internal Corporate Data
Local Developer Machine Data

通过成功地通过转发端口下载这些文件,你已经证明了 SSH 隧道正在端点之间安全地路由流量。

总结

恭喜!你已成功完成了 SSH 隧道与端口转发实验。

在本实验中,你学习了 SSH 隧道的概念以及如何利用它绕过网络限制。你配置了本地端口转发 (-L),通过堡垒机路由本地流量,从而安全地访问隐藏的内部服务。此外,你还配置了远程端口转发 (-R),将本地开发服务暴露给远程服务器,成功绕过了本地 NAT 和防火墙。最后,你学习了如何使用 -N 和 -f 标志在后台静默运行 SSH 隧道。

这些技能对于安全系统管理、远程开发以及安全地处理复杂的网络拓扑至关重要。