A Visual Guide to SSH Tunnels (with labs)

本文涉及的产品
运维安全中心(堡垒机),企业双擎版|50资产|一周时长
运维安全中心(堡垒机),免费版 6个月
简介: Hello folks,Today I bring you an article from a buddy who is engaged in Cloud Native in the Netherlands. The highlights are as follows.

Hello folks,Today I bring you an article from a buddy who is engaged in Cloud Native in the Netherlands. The highlights are as follows.

SSH is yet another example of an ancient technology that is still in wide use today. It may very well be that learning a couple of SSH tricks is more profitable in the long run than mastering a dozen Cloud Native tools destined to become deprecated next quarter.

One of my favorite parts of this technology is SSH Tunnels. With nothing but standard tools and often using just a single command, you can achieve the following:

  • Access internal VPC endpoints through a public-facing EC2 instance.
  • Open a port from the localhost of a development VM in the host's browser.
  • Expose any local server from a home/private network to the outside world.

And more ~

But despite the fact that I use SSH Tunnels daily, it always takes me a while to figure out the right command. Should it be a Local or a Remote tunnel? What are the flags? Is it a local_port:remote_port or the other way around? So, I decided to finally wrap my head around it, and it resulted in a series of labs and a visual cheat sheet :

Prerequisites

SSH Tunnels are about connecting hosts over the network, so every lab below expectedly involves multiple "machines". However, I'm too lazy to spin up full-blown instances, especially when containers can be used instead. That's why I ended up using just a single vagrant VM with Docker on it.

In theory, any Linux box with Docker Engine on it should do. However, running the below examples as-is with Docker Desktop won't be possible because the ability to access the machines containers by their IPs is assumed.

Alternatively, the labs can be done with Lima (QEMU + nerdctl + containerd + BuildKit), but don't forget to limactl shell bash first.

Every example requires a valid passphrase-less key pair on the host that is then mounted into the containers to simplify access management. If you don't have one, generating it is as simple as just ssh-keygen on the host.

Important: SSH daemons in the containers here are solely for educational purposes - containers in this post are meant to represent full-blown "machines" with SSH clients and servers on them. Beware that it's rarely a good idea to have SSH stuff in real-world containers!

Local Port Forwarding

Starting from the one that I use the most. Oftentimes, there might be a service listening on localhost or a private interface of a machine that I can only SSH to via its public IP. And I desperately need to access this port from the outside. A few typical examples:

  • Accessing a database (MySQL, Postgres, Redis, etc) using a fancy UI tool from your laptop.
  • Using your browser to access a web application exposed only to a private network.
  • Accessing a container's port from your laptop without publishing it on the server's public interface.

All of the above use cases can be solved with a single ssh command:

ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr

The -L flag indicates we're starting a local port forwarding. What it actually means is:

  • On your machine, the SSH client will start listening on local_port (likely, on localhost, but it depends - check the GatewayPorts setting).
  • Any traffic to this port will be forwarded to the remote_private_addr:remote_port on the machine you SSH-ed to.

Here is how it looks on a diagram:

Local Port Forwarding with a Bastion Host

It might not be obvious at first, but the ssh -L command allows forwarding a local port to a remote port on any machine, not only on the SSH server itself. Notice how the remote_addr and sshd_addr may or may not have the same value:

ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr

Not sure how legitimate the use of the term bastion host is here, but that's how I visualize this scenario for myself:

I often use the above trick to call endpoints that are accessible from the bastion host but not from my laptop (e.g., using an EC2 instance with private and public interfaces to connect to an OpenSearch cluster deployed fully within a VPC).

Remote Port Forwarding

Another popular (but rather inverse) scenario is when you want to momentarily expose a local service to the outside world. Of course, for that, you'll need a public-facing ingress gateway server. But fear not! Any public-facing server with an SSH daemon on it can be used as such a gateway:

ssh -R [remote_addr:]remote_port:local_addr:local_port [user@]gateway_addr

The above command looks no more complicated than its ssh -L counterpart. But there is a pitfall...

By default, the above SSH tunnel will allow using only the gateway's localhost as the remote address. In other words, your local port will become accessible only from the inside of the gateway server itself, and highly likely it's not something you actually need. For instance, I typically want to use the gateway's public address as the remote address to expose my local services to the public Internet. For that, the SSH server needs to be configured with the GatewayPorts yes setting.

Here is what remote port forwarding can be used for:

  • Exposing a dev service from your laptop to the public Internet for a demo.
  • Hmm... I can think of a few esoteric examples, but I doubt it's worth sharing them here. Curious to hear what other people may use remote port forwarding for!

Here is how the remote port forwarding looks on a diagram:

Remote Port Forwarding from a Home/Private Network

Much like local port forwarding, remote port forwarding has its own bastion host mode. But this time, the machine with the SSH client (e.g., your dev laptop) plays the role of the bastion. In particular, it allows exposing ports from a home (or a private) network your laptop has the access to to the outside world through the ingress gateway:

ssh -R [remote_addr:]remote_port:local_addr:local_port [user@]gateway_addr

Looks almost identical to the simple remote SSH tunnel, but the local_addr:local_port pair becomes the address of a device in the home network. Here is how it can be depicted on a diagram:

Since I typically use my laptop as a thin client and the actual development happens on a home server, I rely on such a remote port forwarding when I need to expose a dev service from a home server to the public Internet, and the only machine with the gateway access is my thin laptop.

Summarizing

After doing all these labs and drawings, I noticed that:

  • The word "local" can mean either the SSH client machine or an upstream host accessible from this machine.
  • The word "remote" can mean either the SSH server machine (sshd) of an upstream host accessible from it.
  • Local port forwarding (ssh -L) implies it's the ssh client that starts listening on a new port.
  • Remote port forwarding (ssh -R) implies it's the sshd server that starts listening on an extra port.
  • The mnemonics are "ssh -L local:remote" and "ssh -R remote:local" and it's always the left-hand side that opens a new port.

Happy reading!

相关文章
|
Oracle 关系型数据库 数据库
使用ssh tunnels加密连接oracle数据库
前一阵子,与一位高手聊天,正好遇到对方的系统有一些问题,要远程连接数据库,我看他使用putty连上后,连接数据库使用的IP是127.0.0.1(localhost),端口也是1521,但是觉得很纳闷,这样怎么能连接远程的数据库能?按照他的说法,使用隧道技术,问对方如何实现的,对方也没有告知。
1470 0
|
15天前
|
监控 Ubuntu Linux
使用VSCode通过SSH远程登录阿里云Linux服务器异常崩溃
通过 VSCode 的 Remote - SSH 插件远程连接阿里云 Ubuntu 22 服务器时,会因高 CPU 使用率导致连接断开。经排查发现,VSCode 连接根目录 ".." 时会频繁调用"rg"(ripgrep)进行文件搜索,导致 CPU 负载过高。解决方法是将连接目录改为"root"(或其他具体的路径),避免不必要的文件检索,从而恢复正常连接。
|
5月前
|
安全 Linux Shell
Linux中SSH命令介绍
Linux中SSH命令介绍
138 2
|
3月前
|
安全 Linux 网络安全
在Linux中,如何配置SSH以确保远程连接的安全?
在Linux中,如何配置SSH以确保远程连接的安全?
|
3月前
|
安全 Linux Shell
SSH 命令完整实用指南 | Linux SSH 服务
【8月更文挑战第20天】
424 0
|
3月前
|
安全 Linux Shell
如何在 Linux 服务器上配置基于 SSH 密钥的身份验证
如何在 Linux 服务器上配置基于 SSH 密钥的身份验证
192 0
|
3月前
|
Linux 网络安全 数据安全/隐私保护
Linux——配置SSH免密登录
Linux——配置SSH免密登录
97 0
|
4月前
|
安全 Ubuntu Linux
记录一次Linux服务器被人使用SSH字典爆破
曾经我以为互联网到至今应该是很和平的状态,但是经历了这次ssh字典爆破攻击后我才意识到网络攻击无处不在,建议系统密码使用比较复杂的随机字符组合,七八十位都没问题,数据可贵,电脑该装杀毒软件的就装上,别因为那占用那点内存而舍弃杀毒软件,防网络攻击于未然 !
|
5月前
|
Shell Linux 网络安全
Linux怎样在使用ssh 链接时就指定gcc 的版本
Linux怎样在使用ssh 链接时就指定gcc 的版本
60 7
|
5月前
|
安全 Linux Shell
【Linux基础】SSH登录
安全外壳协议(Secure Shell Protocol,简称SSH)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。 SSH通过在网络中建立安全隧道来实现SSH客户端与服务器之间的连接。 SSH最常见的用途是远程登录系统,人们通常利用SSH来传输命令行界面和远程执行命令。
87 6