DEV Community

Paweł bbkr Pabian
Paweł bbkr Pabian

Posted on

1

SSH port forwarding from within code

Intro

Port forwarding is a common technique used to access some service behind jump host from your local machine. It is a daily bread of many administrative tasks. In this post I'll show how to create such connections on demand from within Raku or Rust code (without relying on ssh -L system command).

Theory

Before jumping to implementation let me go briefly through operating principle.

There is service host that exposes something on port 7878. However you cannot access it directly from local machine because it is in different network.

ssh-1

Luckily there is jump host in that network that exposes SSH service on port 22, which you can connect to (1).

ssh-2

It is time to open any free port on your local machine (2), let's say 8080, and start listening for incoming connections. Note that those connections can be made from different thread of the same program, which is case we are interested in here.

ssh-3

Whenever connection arrives to local machine (3) we ask jump host using SSH connection (1) to create SSH channel (4) that will pass TCP packets with source port 8080 to jump machine to port 7878.

ssh-4

To complete puzzle we must pass traffic (5) between connection made to our local port 8080 (3) and SSH channel (4) in both ways using existing SSH connection (1).

Image description

Now to connect to service:7878 you actually connect to local:8080 and your data goes like this.

Image description

Important! You need another set of yellow arrows (4) and (5) for every forwarded connection you want to make, you cannot push packets from two connections through single SSH channel. Channel only knows that it should pass TCP packet with source port 8080, it has no knowledge that it came from specific connection (3) on local machine.

SSH key based authentication setup

In pretty much every case where SSH port forwarding is used SSH keys are preferred over interactive user/password login. If your local to jump connection is not already configured please perform following steps.

Generate new key on local machine:

ssh-keygen -t ed25519 -C "me@example.com"
Enter fullscreen mode Exit fullscreen mode

When asked for location choose some meaningful file name and remember the path, in my case it will be /home/me/.ssh/jump.

Enter key password and remember it - in my case it will be s3cret!.

Append content of generated public key /home/me/.ssh/jump.pub to ./ssh/authorized_keys file on jump host in your home directory there. Create file if needed. You can do it manually or you can use ssh-copy-id -i /home/me/.ssh/jump me@jump if you can already login to jump using login/password method and have ssh-copy-id installed on your local machine.

Test your setup by invoking ssh -i /home/me/.ssh/jump me@jump, enter your key password and if it connects you are good to go.

Security concerns

  • You should never store SSH key password directly in your code. I'll do it here purely for demonstration purposes, but in real life scenario I recommend storing and fetching it from remote vault. Just to have manageable "lockdown" procedure in case of security breach.
  • You should always confirm your jump host identity in case of man-in-the-middle attack, when someone redirects your DNS to a fake jump host. I'll explain later how to do it in Raku and Rust.

Let's start coding

Jump to:

Image of AssemblyAI

Automatic Speech Recognition with AssemblyAI

Experience near-human accuracy, low-latency performance, and advanced Speech AI capabilities with AssemblyAI's Speech-to-Text API. Sign up today and get $50 in API credit. No credit card required.

Try the API

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay