External ssh to host then to vm


I was wondering if anyone has any experience with connecting to a virtual machine, externally.
My goal is to be able to directly ssh into my vm, instead of for example ssh to my host machine, then ssh to the vm from there.

I was thinking it would have to be something to do with port forwarding traffic on a specific port to my vm from my host, but I can’t seem to understand how to do that properly.

I am using a virtual NATed network card, so it’s on its own subnet, therefore my router won’t do the portforward directly, so I would probably have to do some form of port forwarding on my host machine.

Heres what I tried to do but I get connection refused, when trying to connect through my host machine.

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 22 -j DNAT --to nattedIPofmyvm:2222
iptables -A FORWARD -p tcp -d nattedIPofmyvm --dport 2222 -j ACCEPT

I’m using port 2222 as an example here so it doesn’t redirect ALL ssh traffic to my virtual machine.

If anyone has any experience with this, or suggestions as of how to solve this, please let me know.

A simpler solution might be use ProxyCommand with ssh. Something like this maybe:

Host    vm
        User            vmuser
        ProxyCommand    ssh -q hostuser@host nc vm-ip 2222
        ForwardAgent    yes

It’s possible ssh sets a bare-bones PATH, then you might need the full path: /usr/bin/nc

The ProxyCommand might be a bit overkill. I have a rasperry pi set up as an ssh jump box for all my VMs. Here’s my ~/.ssh/config:

Host pi
  User pi
  Hostname <TLD pointing to my router>

Host VM
  User myUser
  Hostname 192.168.0.whatever
  ProxyJump pi

Then I just forward whatever port I’m using for SSH to port 22 on my pi. Now I can just type ssh VM and it will connect directly to my VM, with the pi proxying the connection.

EDIT: I do have to set up the keys between my laptop & pi, and between pi & VM. I also recommend turning off passwords once that’s done.

1 Like

Thanks a lot for your help. I will make some attempts to see what solution will be best for me.


I’m using OpenSSH on an arch based distro… I can’t seem to find anything that looks like your config anywhere. Also, i don’t really understand what you mean by setting up keys between your devices?

Sorry for being so new to this.

My goal is that a remote user needs access to my VM using ssh. My original thought was having him just connecting directly to the VM using port forwarding this way, but this seems to not be working. So I am not considering making a super restricted user to allow him to just ssh into the VM. My attempts at this has also not worked…
So if what you’re suggesting for a solution requires him to have account of his own then let me know. But for now I’m not grasping the config you’re referring to, and how to set up my own.

Are you using keys for authentication or passwords?

Passwords… Have never used keys, don’t know how to yet

Well if your gonna expose this vm ssh port to the outside world for someone to be able to ssh in than you may want to look into key authentication, fail2ban , and more security stuff. Also may want this vm to be on its own vlan network in case someone got in they have a lower chance of getting into anything else on your network.

Is there a particular reason someone needs to ssh into this VM?

1 Like

Thanks a lot!

I will have a look at this

I have tried to implement this, but for some reason, it doesn’t accept my keys. It no matter what i do it seems, keeps giving me “Server refused our key” whenever I log in. Anything you can think of to fix this?

I have followed this EXACT format, and also tried to change the sshd config to specifically point to the authorized keys folder.

PuTTY Server Refused Our Key | How to Troubleshoot (Step-by-step Guide)

Heres my sshd config

#   $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Port 22
#AddressFamily any
#ListenAddress ::

Protocol 2

HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

LoginGraceTime 2m
PermitRootLogin prohibit-password
StrictModes yes
MaxAuthTries 6
MaxSessions 10

#PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no

# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
ClientAliveInterval 300
ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# pass locale information
AcceptEnv LANG LC_*

# no default banner path
#Banner none

# override default of no subsystems
Subsystem   sftp    /usr/libexec/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#   X11Forwarding no
#   AllowTcpForwarding no
#   PermitTTY no
#   ForceCommand cvs server

Heres the how the key looks like in my “~/.ssh/authorized_keys” file

ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAnur/IL0/oQRsSbJq+psj9mcV5qWeoZTMHPE6C7SQidpgB/C/kmEo6w2pZM3x7yA9TBPw/Hdcp8w5PPL4jgvdddKgVQswJ8K4l3+mmo+oEod9pW+yU77BCRC3B9HB3LGvfwMw1hkg+Cg2uFOlLgLzyAN5zKE7qMkPCb/f8fbebu24SEodY588ktOefMYc+d7a66QvVjhCLbKjux3G51e5gDXlazfGvMoHxprtHwNYNah8+MK1NcbpOekfOzCjr3slUtJBX+5WmqxWJ+I2MglewEM6Dqqz86vJrIA5qmDFzzcgpVIrFjyp/71/B7qRmRe20iUTITycoxf7JPjdFbBINw== example key

So you followed the guide I linked?
Did you use the ssh-copy-id command?
Did you generate the key on your personal machine or whatever machine you are wanting to ssh from to the vm?

1 Like

I figured out the problem, I’m so used to using sudo when dealing with configs… but for changing the authorized keys file, i have to not do that. Stupid mistake, but it works as intended now!


Now you need to figure out what level of security you are gonna use for exposing this ssh port to the world.

thro’s short short version on ssh keys

on your CLIENT machine run ssh-keygen and use a passphrase when prompted to protect your PRIVATE key in case of theft

this will give you two keys in ~/.ssh/

id_rsa (the private key)
id_rsa.pub (the public key)

or similar, depending on the type of key generated

the .pub key you can give to anyone or copy to anything you want to log into from your client machine.

stick it in ~/.ssh/authorized_keys (on the remote machine)

(copy/paste it into that file, you can copy paste multiple public keys one after the other in that file) and ssh should use it for login.

once you confirm you can log in using your key/passphrase you can turn off password authentication on the remote ssh server.

the private key ideally never leaves the machine you generated the keypair on! this way if your box gets stolen you just remove the key from places you added it to and those machines can’t be used to connect even if they have your passphrase.

you can technically copy your private key around but if you use the same key everywhere then theft of a machine means they’ve got your only key.

to do ssh properly, keys are always generated on the CLIENT and the .pub is the only one you copy around.

Bonus points: you can use ssh-agent to keep your key unlocked on your client, so you can log in without continually typing your passphrase every time. :slight_smile:

1 Like

Sorry for not being clear earlier. This configuration goes in the user home: $HOME/.ssh/config. If the file does not exist, just create it. You can look at man ssh_config to explore options; e.g. you might want to use the HostName option to specify the full hostname/ip so that name provided with Host can actually be an alias. You can also use it do hostname matching using globs.

1 Like