DEV Community

Cover image for SSH keeps dying after 2 minutes? It’s not the firewall, it’s idleness.
Aditya Anil
Aditya Anil

Posted on

SSH keeps dying after 2 minutes? It’s not the firewall, it’s idleness.

You spin up a Linux machine, and the next thing you want is SSH access from anywhere.

Then the connection dies after about two minutes of silence.

If you were like me, your first hypothesis would always be “the campus/network firewall is blocking SSH.” Well, more often that’s the case if you are working in a public/corporate network.

However, on the other side, it isn’t the firewall that is blocking the protocol, but it is complacency: evicting idle connections.

What’s the difference? A blocked protocol needs a different transport. An idle timeout just needs you to never go silent.

In this post, I will guide you on a quick way to keep the SSH connection alive.

I. The setup

The solution presented below uses no public ports and no outbound SSH filtering.

The solution is this: relay SSH over HTTPS using Cloudflare’s free Quick Tunnel.

This setup does not require you to have an account.

1. Install cloudflared on the server

Pick the method that matches your distro:

Debian / Ubuntu

sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt-get update && sudo apt-get install cloudflared
Enter fullscreen mode Exit fullscreen mode

Fedora / RHEL / CentOS

curl -fsSL https://pkg.cloudflare.com/cloudflared.repo | sudo tee /etc/yum.repos.d/cloudflared.repo
sudo dnf install cloudflared   # or yum
Enter fullscreen mode Exit fullscreen mode

Arch Linux

sudo pacman -Syu cloudflared
Enter fullscreen mode Exit fullscreen mode

Any other distro

Download the binary from the official downloads page.

2. Start the tunnel on the server

cloudflared tunnel --url ssh://localhost:22 --protocol http2
Enter fullscreen mode Exit fullscreen mode

It prints a temporary *.trycloudflare.com URL. Keep that terminal open.

3. Connect from another Linux machine

Install cloudflared on the client the same way (or just grab the binary), then:

ssh -o ProxyCommand="cloudflared access ssh --hostname %h" $USER@YOUR-LINK.trycloudflare.com
Enter fullscreen mode Exit fullscreen mode

And if everything goes well, you notice that it works… until you stop typing for about a minute. Then it vanishes.

II. But why does it drop?

Stateful packet filters (and Cloudflare’s edge) treat silent connections as stale and reap them.

To overcome this, there are two fixes that have worked for me:

Fix 1: Client side

We want the client to never be idle.

Add this helper to ~/.bashrc (or ~/.zshrc) on the client:

cf-ssh() {
  local host="${1%.trycloudflare.com}"
  host="${host//[^[:alnum:]-]/}"
  ssh -o ServerAliveInterval=15 \
      -o ServerAliveCountMax=3 \
      -o ProxyCommand="cloudflared access ssh --hostname %h" \
      "$USER@${host}.trycloudflare.com"
}
Enter fullscreen mode Exit fullscreen mode

Usage:

cf-ssh some-random-words.trycloudflare.com
# or just
cf-ssh some-random-words
Enter fullscreen mode Exit fullscreen mode
  • ServerAliveInterval 15 sends a small encrypted packet every 15 seconds of silence.
  • ServerAliveCountMax 3 gives up only after three missed replies.

To the filter, the session now looks busy.

Fix 2: Server side

If the server is not at fault, let’s make the client busy. The other end can time out too.

Edit /etc/ssh/sshd_config on the server:

ClientAliveInterval 15
ClientAliveCountMax 3
Enter fullscreen mode Exit fullscreen mode

Then reload:

sudo systemctl restart sshd
# or on systems without systemd:
sudo service ssh restart
Enter fullscreen mode Exit fullscreen mode

Both sides now communicate with each other. Both of them are now busy. The network does not filter, nor does the tunnel ever see a dead link.

And there you go, the problem is solved.

NOTE:

Caution: trycloudflare.com URLs are semi-public and change every time you restart the tunnel. Use key-based authentication only, never passwords, and shut the tunnel down when you’re finished.

Top comments (0)