9

As part of my effort to reduce noise in logs and slightly reducing discoverability (and on top of fail2ban, allowing only public key authentication etc.) I routinely change sshd-ports on servers I set up to a different port, let's say 5492. Currently I either append -p 5492 to my ssh command, or add the port for each specific server into my ssh_config.

Is there a way to configure ssh to try connecting to both port 22 and port 5492 if port 22 doesn't work?

  • 1
    I do prefer instead of having security through obscurity, setting up a VPN and not having open ssh ports to the Internet at large at all. – Rui F Ribeiro Feb 17 '18 at 9:55
  • 2
    @RuiFRibeiro I agree, that it is not more secure. It does, however, keep noise down in log files. One could also use port knocking to reduce login attempts which does increase security. – Ned64 Feb 17 '18 at 10:13
  • 2
    @RuiFRibeiro Is a VPN server more secure than an SSH server though? – Riley Feb 17 '18 at 10:55
  • It all depends on the implementation. In my former job, I defined 2 VPN entries for redundancy, and no whatsoever ssh presence for the outside. – Rui F Ribeiro Feb 17 '18 at 16:49
  • 2
    Security by obscurity is a good ADDITIONAL layer on top of a good setup, especially when it is about opportunistic attackers. – rackandboneman Feb 17 '18 at 20:51
11

You could wrap a shell script around ssh but ssh itself will not do it.

One way using a bash function is this (put into ~/.bashrc):

function ssh() { command ssh -p 22 "$@" || command ssh -p 5492 "$@"; }

By the way, it is recommended to use root-reserved ports for system services like ssh in order to avoid users from having a process that listens on, say, port 5492. They may otherwise play man in the middle and possibly capture login data. So, use a port < 1024.

  • 1
    That's a great solution. Also a great note on the ports! – Riley Feb 17 '18 at 10:57
  • 5
    Note that the second connection will be made even if the first one succeeds if the command executed by ssh returns non-zero. A trivial example would be ssh user@server false. – Kusalananda Feb 17 '18 at 14:44
  • 1
    @Kusalananda Thanks, I have written command now. Just wanted to avoid recursion, as you have guessed right. – Ned64 Feb 17 '18 at 14:52
  • The problem @Kusalananda mentions can be (mostly) avoided by testing the specific exit status of ssh -- if there's an ssh error (as opposed to the remote command failing), it'll exit with a status of 255. Thus, command ssh -p 22 "$@"; if [ "$?" -eq 255 ]; then command ssh -p 5492 "$@"; fi should work. – Gordon Davisson Feb 17 '18 at 22:15
10

ssh itself can do this via Match documented in ssh_config(5) though the documentation is somewhat sparse on examples. This form may be suitable if one wants to push the complexity into the SSH configuration though is restricted by the limitations of the ssh_config(5) syntax and may require some fiddling with for the desired outcome. Notably the custom port can either not be set or can be set wrongly from the previous Match attempt. This is why, below, it is set twice when tested for, or once for the default, and is not set when establishing the canonical defaults.

# here we set the defaults for the host (no port!)
Match !canonical host testhost
  CanonicalizeHostname yes
  Hostname 192.0.2.42
  IdentityFile ~/.ssh/id_blahblah
  ...
# port available?
Match canonical host 192.0.2.42 exec "is-ssh-up %h 2222"
  Port 2222
# or the default port
Match canonical host 192.0.2.42
  Port 22

is-ssh-up merely checks whether something responds on the given port and might look like

#!/usr/bin/env expect
package require Tcl 8.5
if {[llength $argv] < 2} {
   puts stderr "Usage: is-ssh-up host port"
   exit 1
}
puts stderr "is-ssh-up: DEBUG trying $argv"
set socket [socket -async [lindex $argv 0] [lindex $argv 1]]
chan event $socket readable [list exit 0]
after 3000 [list exit 1]
vwait godot
  • 1
    if-then-else in .ssh/config ? I wouldn't have believe it !! – Archemar Feb 18 '18 at 9:56
1

You can use the wildcard function of ~.ssh/config, putting this entry in your list:

Host *
Port 5492

But this won't fall back to 22 by itself.

If you put it at the end, you can still override it for those hosts were you need 22 by putting a different value above it. (And you can always override it on the command line.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.