Home Resources

SSH Tunnel

Table of Contents

概述

当我们可以访问一台主机的 ssh 服务时,我们可以通过 ssh 隧道

  1. 将 ssh 主机所在网络的服务映射到本地网络1(包括该 ssh 主机自身启动的服务)
  2. 也可以将本地网络服务映射到 ssh 主机本地(包括本地主机自身的服务)

更详细的介绍参见 A Visual Guide to SSH Tunnels: Local and Remote Port Forwarding.

场景 1 - 将远程服务映射到本地

服务器集群中,你能访问一台服务器的 ssh 服务 (如 user@bastion),其它服务器和 bastion 在一个内部网络中,其中服务 server 的 80 服务你希望能够访问。

可以通过如下指令将该服务暴露到你本地(localhost)的 8080 端口:

ssh -L localhost:8080:server:80 user@bastion

若希望将服务暴露给本地所有网卡,将 localhost:8080 替换成 0.0.0.0:8080:

ssh -L 0.0.0.0:8080:server:80 user@bastion

若希望访问的服务就在 bastion 机器上(而不是它同一网络中的另一台机器),将 server:80 替换成 localhost:80:

ssh -L localhost:8080:localhost:80 user@bastion

场景 2 - 将本地服务映射到远程

内网服务器 (如 server) 上有一个 80 端口服务,你希望从外网访问该服务。

若有一台架设了 ssh 服务且暴露在公网的服务器 (如 user@gateway),你可以在内网某台电脑上通过如下指令将 server:80 的服务暴露到 gateway:8080

ssh -R 0.0.0.0:8080:server:80 user@gateway

如果你在 server 上执行该命令, server:80 可直接替换成 localhost:80:

ssh -R 0.0.0.0:8080:localhost:80 user@gateway

静默执行

上面的命令执行完后,默认会启动一个远程 shell,对于隧道的场景并不必要,可以添加如下选项2

  • 使用 -N 防止 ssh 启动 shell
  • 使用 -f 让这个 tunnel 进程后台执行

autossh

如果你想维持一个稳定持久的隧道连接3,可以使用 autossh,选项和 ssh 基本一致。

例如你可以通过如下 systemd 配置来创建一个稳定的 ssh 隧道服务,将本机的 ssh 服务暴露给 remote 机器的 1212 端口:

[Unit]
Description=SSH Tunnel
After=network.target

[Service]
Type=simple
ExecStart=autossh -N -R 0.0.0.0:1212:localhost:22 user@remote
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
Alias=ssh-tunnel.service

socks 服务

另外,你可以通过如下命令在本地 7890 端口开启一个 socks 服务,从而得到一个应用层代理:

ssh -D 7890 user@gateway

Footnotes:

Author: lotuc, Published at: 2023-08-06 Sun 00:00, Modified At: 2023-08-06 Sun 23:38 (orgmode - Publishing)