<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: dpm_bush</title>
    <description>The latest articles on DEV Community by dpm_bush (@__3381495fd2b).</description>
    <link>https://dev.to/__3381495fd2b</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4107233%2Fb8ff0436-9096-443b-b82c-de3dce98950a.png</url>
      <title>DEV Community: dpm_bush</title>
      <link>https://dev.to/__3381495fd2b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/__3381495fd2b"/>
    <language>en</language>
    <item>
      <title>SSH Port Forwarding Explained: Local, Remote, and Dynamic Tunnels</title>
      <dc:creator>dpm_bush</dc:creator>
      <pubDate>Thu, 03 Sep 2026 04:39:35 +0000</pubDate>
      <link>https://dev.to/__3381495fd2b/ssh-port-forwarding-explained-local-remote-and-dynamic-tunnels-57p7</link>
      <guid>https://dev.to/__3381495fd2b/ssh-port-forwarding-explained-local-remote-and-dynamic-tunnels-57p7</guid>
      <description>&lt;p&gt;SSH port forwarding — also called SSH tunneling — forwards traffic for another service through an already-encrypted SSH connection.&lt;/p&gt;

&lt;p&gt;If you've ever needed to access a database that only listens on &lt;code&gt;localhost&lt;/code&gt;, expose a local development server through a remote machine, or route an application's traffic through an SSH host, port forwarding is usually the simplest way to do it.&lt;/p&gt;

&lt;p&gt;There are three types:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Local forwarding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-L&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Forwards a port on your machine through the SSH server to another destination&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote forwarding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-R&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Forwards a port on the SSH server back to your machine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic forwarding&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-D&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Turns the SSH connection into a SOCKS proxy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Let's look at each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SSH port forwarding?
&lt;/h2&gt;

&lt;p&gt;A normal SSH connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh user@host
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;opens an interactive shell on the remote machine.&lt;/p&gt;

&lt;p&gt;But SSH can carry more than terminal traffic over the same encrypted connection.&lt;/p&gt;

&lt;p&gt;Port forwarding uses that connection to carry traffic from another service — for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a database connection&lt;/li&gt;
&lt;li&gt;an internal web dashboard&lt;/li&gt;
&lt;li&gt;a development server&lt;/li&gt;
&lt;li&gt;application traffic through a SOCKS proxy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the application's point of view, it usually connects to an ordinary local port. SSH handles transporting that traffic through the encrypted connection to its actual destination.&lt;/p&gt;

&lt;p&gt;This is different from &lt;strong&gt;router port forwarding&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Router-level port forwarding changes NAT or firewall rules so incoming internet traffic reaches a device on a network.&lt;/p&gt;

&lt;p&gt;SSH port forwarding happens entirely inside an existing SSH connection.&lt;/p&gt;




&lt;h2&gt;
  
  
  Local port forwarding with &lt;code&gt;-L&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Local forwarding is probably the most common type of SSH tunnel.&lt;/p&gt;

&lt;p&gt;The syntax is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-L&lt;/span&gt; local_port:destination_host:destination_port user@ssh_server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;local_port&lt;/code&gt; is the port opened on your machine&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;destination_host:destination_port&lt;/code&gt; is the destination as seen from the SSH server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;user@ssh_server&lt;/code&gt; is the server carrying the tunnel&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: connect to a remote MySQL database
&lt;/h3&gt;

&lt;p&gt;Imagine MySQL is running on a server but only listening on &lt;code&gt;localhost:3306&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead of exposing MySQL directly to the internet, create a tunnel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-L&lt;/span&gt; 3306:localhost:3306 deploy@db-host.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now point your local MySQL client at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;localhost:3306
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your client behaves as if MySQL were running locally.&lt;/p&gt;

&lt;p&gt;In reality the path looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your MySQL client
      |
localhost:3306
      |
      | SSH tunnel
      v
db-host.example.com
      |
localhost:3306
      |
     MySQL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database port never needs to be publicly exposed. Only SSH does.&lt;/p&gt;

&lt;p&gt;The same pattern works for Redis, internal dashboards, monitoring tools, and other services that aren't supposed to listen on a public interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  A &lt;code&gt;localhost&lt;/code&gt; gotcha
&lt;/h3&gt;

&lt;p&gt;If the tunnel appears to work but your application hangs or gets refused, try &lt;code&gt;127.0.0.1&lt;/code&gt; instead of &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On some systems, &lt;code&gt;localhost&lt;/code&gt; may resolve to the IPv6 loopback address &lt;code&gt;::1&lt;/code&gt; first while the forward or destination service is listening only on IPv4.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;127.0.0.1&lt;/code&gt; explicitly can avoid that mismatch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Remote port forwarding with &lt;code&gt;-R&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Remote forwarding works in the opposite direction.&lt;/p&gt;

&lt;p&gt;Instead of opening a port on your machine, it opens a port on the SSH server and forwards connections back through SSH to your local machine.&lt;/p&gt;

&lt;p&gt;Syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-R&lt;/span&gt; remote_port:local_host:local_port user@ssh_server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example: expose a local development server
&lt;/h3&gt;

&lt;p&gt;Suppose you're running an application locally on port &lt;code&gt;3000&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create this tunnel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-R&lt;/span&gt; 8080:localhost:3000 user@ssh_server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connections to port &lt;code&gt;8080&lt;/code&gt; on the SSH server are now forwarded through the SSH connection to port &lt;code&gt;3000&lt;/code&gt; on your machine.&lt;/p&gt;

&lt;p&gt;The path is essentially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SSH server :8080
      |
      | SSH tunnel
      v
Your machine :3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the remotely forwarded port is typically bound to loopback on the SSH server, meaning it can be reached from the server itself rather than automatically being exposed to the wider network.&lt;/p&gt;

&lt;p&gt;This direction is also the foundation of an &lt;strong&gt;SSH reverse tunnel&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's particularly useful when a machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;has no public IP&lt;/li&gt;
&lt;li&gt;sits behind NAT&lt;/li&gt;
&lt;li&gt;sits behind a firewall&lt;/li&gt;
&lt;li&gt;can make outbound SSH connections but can't accept inbound ones&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For persistent reverse tunnels, there are additional things to consider such as &lt;code&gt;GatewayPorts&lt;/code&gt;, restricted SSH keys, and automatic reconnection.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dynamic port forwarding with &lt;code&gt;-D&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Local and remote forwarding both map a specific port to a specific destination.&lt;/p&gt;

&lt;p&gt;Dynamic forwarding is different.&lt;/p&gt;

&lt;p&gt;It turns SSH into a &lt;strong&gt;SOCKS proxy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Start one with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-D&lt;/span&gt; 1080 user@ssh_server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SSH now exposes a SOCKS proxy on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;localhost:1080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applications that support SOCKS can use that proxy and route their traffic through the SSH server.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-x&lt;/span&gt; socks5h://localhost:1080 https://example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike &lt;code&gt;-L&lt;/code&gt;, you don't specify one destination when creating the tunnel.&lt;/p&gt;

&lt;p&gt;The application decides where it wants to connect, and the SSH server makes the outbound connection on its behalf.&lt;/p&gt;

&lt;p&gt;This is useful when you want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;access multiple internal services through a jump host&lt;/li&gt;
&lt;li&gt;route one application's traffic through a remote server&lt;/li&gt;
&lt;li&gt;make requests originate from a trusted network location&lt;/li&gt;
&lt;li&gt;avoid creating a separate forward for every service&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Keeping an SSH tunnel alive
&lt;/h2&gt;

&lt;p&gt;A tunnel only exists while its SSH connection is alive.&lt;/p&gt;

&lt;p&gt;A few options make tunnel-only connections more practical.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;-N&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Don't execute a remote command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; 3306:localhost:3306 user@server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful when the connection exists only for forwarding.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;-f&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Background SSH after authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; 3306:localhost:3306 user@server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SSH keepalives
&lt;/h3&gt;

&lt;p&gt;You can also make SSH detect dead connections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-L&lt;/span&gt; 3306:localhost:3306 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;ServerAliveInterval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;ServerAliveCountMax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="se"&gt;\&lt;/span&gt;
  deploy@db-host.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ServerAliveInterval=30&lt;/code&gt; makes the client periodically send a message through the encrypted SSH connection.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ServerAliveCountMax=3&lt;/code&gt; makes SSH exit after several unanswered messages.&lt;/p&gt;

&lt;p&gt;One important distinction: &lt;strong&gt;this detects a dead connection. It does not reconnect automatically.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need an unattended tunnel that reconnects after failure, a tool such as &lt;code&gt;autossh&lt;/code&gt; can handle the reconnect loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  Put frequently used tunnels in &lt;code&gt;~/.ssh/config&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If you use the same tunnel regularly, you don't need to remember a giant command.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Host db-tunnel
  HostName db-host.example.com
  User deploy
  LocalForward 3306 localhost:3306
  ServerAliveInterval 30
  ServerAliveCountMax 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh db-tunnel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;opens the configured connection and forward.&lt;/p&gt;

&lt;p&gt;The same SSH config can also contain options such as &lt;code&gt;IdentityFile&lt;/code&gt;, &lt;code&gt;ProxyJump&lt;/code&gt;, ports, usernames, and other per-host settings.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is SSH tunneling secure?
&lt;/h2&gt;

&lt;p&gt;The traffic inside an SSH tunnel inherits the encryption and authentication of the SSH connection.&lt;/p&gt;

&lt;p&gt;But the way you expose the ends of the tunnel still matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Be careful with &lt;code&gt;GatewayPorts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A remote forward created with &lt;code&gt;-R&lt;/code&gt; normally isn't automatically exposed to everyone on the network.&lt;/p&gt;

&lt;p&gt;Changing &lt;code&gt;GatewayPorts&lt;/code&gt; can allow remotely forwarded ports to bind beyond loopback.&lt;/p&gt;

&lt;p&gt;That can be intentional, but it can also expose a service much further than expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prefer loopback when possible
&lt;/h3&gt;

&lt;p&gt;There's an important difference between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.0.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A forwarded port bound to &lt;code&gt;127.0.0.1&lt;/code&gt; is reachable only from the same machine.&lt;/p&gt;

&lt;p&gt;Binding to &lt;code&gt;0.0.0.0&lt;/code&gt; can make it reachable from other machines on the network as well.&lt;/p&gt;

&lt;p&gt;Don't broaden the bind address unless you actually need to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Close tunnels you no longer need
&lt;/h3&gt;

&lt;p&gt;It's easy to create a tunnel for a quick task and forget about it.&lt;/p&gt;

&lt;p&gt;A forgotten tunnel to a production database is still an access path.&lt;/p&gt;

&lt;p&gt;Treat tunnels like any other connection to a sensitive service: know why they're running and close them when they're no longer needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  SSH tunnel vs VPN vs exposing a port
&lt;/h2&gt;

&lt;p&gt;These solve related problems, but they're not interchangeable.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;SSH tunnel&lt;/th&gt;
&lt;th&gt;VPN&lt;/th&gt;
&lt;th&gt;Public port&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scope&lt;/td&gt;
&lt;td&gt;Usually one service, or selected app traffic with &lt;code&gt;-D&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Entire network&lt;/td&gt;
&lt;td&gt;One publicly reachable service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setup&lt;/td&gt;
&lt;td&gt;Usually one SSH command&lt;/td&gt;
&lt;td&gt;VPN server + client configuration&lt;/td&gt;
&lt;td&gt;Firewall/NAT configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Reaching a few services through an SSH host&lt;/td&gt;
&lt;td&gt;Ongoing access to a private network&lt;/td&gt;
&lt;td&gt;Services intentionally designed to be public&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you're already SSHing into a server and just need access to one internal service, an SSH tunnel is often the fastest option.&lt;/p&gt;

&lt;p&gt;If you need transparent access to an entire private network across multiple applications and devices, a VPN is usually the better tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  The three commands worth remembering
&lt;/h2&gt;

&lt;p&gt;If you forget everything else, remember these patterns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local forwarding:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-L&lt;/span&gt; local_port:destination:port user@server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Remote forwarding:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-R&lt;/span&gt; remote_port:local_destination:port user@server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Dynamic forwarding:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-D&lt;/span&gt; local_port user@server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-L&lt;/code&gt; brings something reachable from the remote side to you.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-R&lt;/code&gt; makes something on your side reachable from the remote side.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-D&lt;/code&gt; gives applications a SOCKS proxy through the remote server.&lt;/p&gt;

&lt;p&gt;Those three patterns cover most everyday SSH tunneling use cases.&lt;/p&gt;




&lt;p&gt;I originally published a more detailed version of this guide on the &lt;a href="https://sshflow.com/blog/ssh-tunneling/" rel="noopener noreferrer"&gt;SSHFlow blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm also building &lt;a href="https://sshflow.com/" rel="noopener noreferrer"&gt;SSHFlow&lt;/a&gt; — an SSH client where every server gets its own workspace for terminals, SFTP, code, and databases.&lt;/p&gt;

</description>
      <category>ssh</category>
      <category>devops</category>
      <category>linux</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
