SSH-forwarding vs. normal DNAT?

Hi,

can someone clarify what is the difference between: IP → SSH → Forwarding and the normal IP → Filter → NAT DNAT-forwarding?

Also the MT does not help:

forwarding-enabled (both | local | no | remote; Default: no) Allows to control which SSH forwarding method to allow:

no - SSH forwarding is disabled;
local - Allow SSH clients to originate connections from the server(router), this setting controls also dynamic forwarding;
remote - Allow SSH clients to listen on the server(router) and forward incoming connections;
both - Allow both local and remote forwarding methods.

“local” does “dynamic forwarding” mean, it controls somehow the normal ‘dynamic’ DNAT (IP → Filter → NAT)?
And does this steer how the router itself (output-chan) behaves?

“remote” how does a client “listen” on the router? And how is the contex here to the input, output and dstnat-chains?
How does the the router “know” from which WAN connection it should forward to which LAN-host/“listening”-client? If I want external port 22 should be fordwarded to internal host 192.168.0.123:12345? Or is this a 1:1 like-NAT and external port 12345 gets 1:1 forwarded to internal port 12345 (but to which host)?

Difference it that SSH forwarding creates encrypted connection tunnel between ssh client and server which tunnels connection to remote host, while DNAT it is just packet forwarding to host/port and it doesn’t care about L7 protocol.


SSH forwarding doesn’t open port on SSH server side, server is just used as “jump” host for connection tunnel, can be useful for eg. to establish connection between client from unsecure network and server in secure/trusted network with some unsecure L7 protocol (or to add additional layer of security) for avoiding protocol inspection / sniffing on unsecure network.
See more about SSH forwarding types: https://www.ssh.com/academy/ssh/tunneling-example, https://phoenixnap.com/kb/ssh-port-forwarding.

For SSH forwarding there is no need for DNAT rules (in common cases), just proper firewall filter rules depending on use case, like accept input for SSH port if needs to be accessed from WAN.

From ssh client point of view:

local means that port X on client side is forwarded via ssh tunnel to 3rd party address and port … and 3rd party means anywhere, can be e.g. 8.8.8.8 port 53 (this doesn’t correlate to ssh tunnel endpoint). So traffic break out will be ssh server side.

remote means that port on ssh server side is forwarded via ssh tunnel to 3rd party address and port … it’s simikar but port from ssh server side will be forwarded to remote dite. Traffic break out will be ssh client side.

How it compares to normal DNAT? When using normal DNAT, traffic is handled by single router/site … so port on router is forwarded to 3rd party and traffic breakout is the same router as listening on a port. With ssh forwarding things are similar but traffic breakout is the other end of ssh tunnel.

It would seem that the idea of SSH is to reach a spot on the LAN securely ( and possibly to config the router ).
So to compare the two SSH is safer.
However why use SSH when you can use wireguard which has better security protocols…

Using ssh is often much simpler without too much of compromise on security:

  • no special packet handling is needed (no NAT no nothing, ssh does it automatically)
  • no routing setup needed
  • no escalated permissions needed for port forwarding on either side
  • etc.

And I’m not sure if wireguard really has better security protocols than modern implementations of ssh …

Also it can be used just to change source IP (hide actual client IP) for connection to remote host where remote host is not controlled by client connection initiator. For eg. when creating SSH dynamic forwarding to some WAN remote host, then SSH client side creates local SOCKS proxy to remote host, any local connection over such proxy will create connection with SSH server (router) IP to remote host.

Wait is this the one where one has to publish a set of keys and then use PMK files or something,in other words a PITA and imho worse than wireguard.

On SSH server only client public key must be imported for certificate based authentication, also just password can be used. OpenSSH (not in ROS) server also supports PAM module which supports various authentication mechanisms.
If you want it to compare with P2P Wireguard connection between 2 hosts, yes, it is less secure because SSH encryption is only between client and server, but from SSH server to remote host is not, still, remote host doesn’t need to have VPN and it doesn’t need to be under control, so it is for different use cases.

If you open the SSH port to the outside, even if you’ve changed it from the standard TCP 22 port, you expose the presence of the SSH server to the internet and a simple port scan with fingerprinting is enough to know that you have SSH running and accepting incoming connections on which port. The attacker will then be able to move to the next phase, brute forcing or maybe trying to exploit some vulnerability. Even if there are no known active vulnerabilities to exploit, because it’s TCP, the open port, not blocked by the firewall, can be used for TCP SYN attack for example.

With WireGuard, which use UDP, and which, in absence of a valid public key from the side that initiates a handshake, will produce no responses to the incoming UDP packet. Which means you cannot run a port scan and discover that WireGuard is running on this or that port. No response packets are sent means from the outside it’s indistinguishable from anything blocked by a regular drop all incoming from WAN rule. The attacker cannot isolate the port used by WireGuard for targeted attacks (DoS for instance).

Thank you guys!

This SSH remote/local tunneling stuff seems to me quite complicated and not really good controlable.
In a sense “which SSH-user is allowed to reach which server in my LAN” and I think I cannot control this via firewall/filter either.

I will let it disabled, seems safest to me. The “normal DNAT” is enough.