I'm admining an AWS cluster, and am currently planning to run ssh access exclusively through a single jump box rather than dealing with public keys or LDAP authentication for ever-changing access lists. Instead, the jump box's public key would be authorized on all other instances, and it manages which users can access which other instances. However, I don't want to expose the private key to normal users.

My initial solution was to write a simple shell in bash that executes ssh [myserver] and have users run ssh username@aws-jumpbox [myserver] to connect to myserver, or alternatively to have an interactive session that only accepts ssh as a command. However, I remembered belatedly that you can't spawn an interactive session from within a shell script.

Is there a simple way to achieve what I'm looking for? Am I going off on the wrong path completely?

  • Don't you have to manage access lists either way? You'll just be doing it for a different machine, no? Jul 8 '15 at 0:48
  • @user1794469 This approach keeps everything centralized, so I don't have to add a new sysadmin's public key to every server, or go through each server to see which a former employee had access to when they leave. Even with Puppet, managing public keys cluster-wide can be a pain. It also means that non-public-facing servers like databases don't need public IPs.
    – Mikkel
    Jul 8 '15 at 0:58

However, I remembered belatedly that you can't spawn an interactive session from within a shell script.

Yes you can, but you have to pass -t to the ssh command (the one that establishes the connection to the jump host, not the one from the jump jost). The reason is that if you specify a command when running ssh, by default it won't allocate a tty, which is needed for an interactive session. -t fixes that.

Some possible alternatives:

  1. Make the script on your jump host allow your users to select a hostname interactively, possibly using something like dialog. Downside of this method: you make it harder for them to run a noninteractive session.
  2. Create a user on the jump host per target machine, named after the target machine. Downside of this method: you need to maintain your users' ssh keys in many files. It may be best to use some config management system for this; e.g., puppet has support for dealing with authorized_keys files and ssh keys directly. Upside is that you can more easily define which user gets access to which host.

Note that if you don't want your users to be able to get the ssh private key, you should make sure that they also can't use scp or sftp to your jump host. This may make it more difficult for them to do their job.

All in all, personally I'm not sure if what you're trying to do is a good idea. Your jump host doesn't solve the problem of 'too many ssh keys', it only moves it, and introduces a lot of problems its own (no scp/sftp; you add a host which is a great target for an attacker trying to get access to all hosts on your network and hence a SPOF, security-wise; the issue with interactive sessions and specified commands).

Instead, I would suggest the following:

  • Use a config management system on your AWS hosts, and make sure it runs at startup before sshd has started. This is a good idea anyway for various reasons. I know puppet better than the alternatives, but there are other options.
  • if using puppet, create a file with your users' ssh keys, like so:

    $user_wouter_sshkey = 'ssh public key data'
    $user_john_sshkey = 'ssh public key data'


  • For every group of users that you want to give access to a resource, create a defined type:

    define dbassh ($username = $title) {
        ssh_authorized_key {"wouter_dba_$username":
            key => $user_wouter_sshkey,
            type => 'ssh-rsa',
            user => $username,
        ssh_authorized_key {"john_dba_$username":
            key => $user_john_sshkey,
            type => 'ssh-rsa',
            user => $username,


  • now, elsewhere in your puppet config, you can do things like:

    user {"postgres":
        ensure => present,
        purge_ssh_keys => true,
    dbassh {"postgres":}
  • True. Your observation about being unable to scp basically kills the idea dead in the water. I'll just manage keys with Puppet as you suggest.
    – Mikkel
    Jul 8 '15 at 17:14

What you describe is a single point of failure, and a fragile one at that. Personally I'd choose a different approach: two (or more) OpenBSD machines in front of your cluster, acting as routers, firewalls, and load balancers. Synchronize firewall states with CARP, and use authpf to control who can access what. This way you can distribute everybody's keys everywhere, and still manage access in a single place. It separates authentication from authorisation, and it eliminates the single point of failure.


1) Establish SSH security on the jump-host. Only allowing your business public IP Address or the block of IP Addresses that your ISP provides if you do not have static IPs. Then you can force users that might even work from home to VPN to your internal network first.


2) Lock down SSH logins to the other servers to only come from that jump-host server.


3) Create a functional account across the servers and push the SSH Key from that functional/admin account. Lock down using a series of security features like sudoers. MyCorporation.... mycorpsql, mycorpweb, mycorpdev, mycorpsys.

You could also effectively use a local security group to lock down su.


Effectively you can just remove users from the group and disable their account. You can create a script on the root home for this.

To delete/terminate users

#   title   : deladminusers.sh
#   syntax  : deladminusers.sh username
gpasswd -d $1 youradmingrouphere
userdel $1

To Disable Users

#   title   : disableadminusers.sh
#   syntax  : disableadminusers.sh username
gpasswd -d $1 youradmingrouphere
#makes password incomprehensible
sed -i "s/$1:/$1:!/g" /etc/shadow

To enable users

#   title   : enableadminusers.sh
#   syntax  : enableadminusers.sh username
gpasswd --add $1 youradmingrouphere
#makes password comprehensible again.
sed -i "s/$1:!/$1:/g" /etc/shadow

4) Push SSH keys to all of the servers from the jump-host. Then lockdown the ssh files on the functional account profiles so that they are read-execute only.

fiduser@jumphost ~: ssh-keygen -t rsa
fiduser@jumphost ~: for SERVER in `cat ~/serverlist`
    ssh-copy-id -i .ssh/rsa_id.pub fiduser@$SERVER

5) Lock Down users allowed to SU to the functional IDs and make sure the jump-host is a locked down tight. Disable normal binary access on the jumphost. Allow SU and SSH for ALL USERS - Even the functional accounts on that jump-host except for root. Reduce to the minimum requirements to SSH passwordlessly once they're logged in.

I am not familiar with the OS version you have for a jump-host. You'll have to investigate because locking down basic user commands by adding users to a group might be tough to explain for different distributions.

Use some brute force countermeasures. fail2ban maybe?

Just make sure its configured not to ban your business IP range. Also, don't forget to lock-down your inner-office Jump-host.

  • 1
    Unless I missed something in your explanation, you're just telling me what a jump box is for. I'm aware of that, but I would prefer to set up the infrastructure with only one public key needed on each server to simplify user management. However, that makes the private key sensitive information, and the account running ssh needs to be able to access the key file, so regular users can't be given shell access to the jump box.
    – Mikkel
    Jul 8 '15 at 4:25
  • I told you what you need to do to accomplish. If you don't understand these instructions, please be more specific in your questioning. I gave you a series of tasks, outlined a suggestive process to accomplishing your goal, and threw in a few scripts to make your admin work on It easier. Also, if you're unclear as to how to accomplish these tasks and this is for a business, I would definitely suggest seeking help from an insured Linux/Security professional/consulting firm. Jul 8 '15 at 8:00
  • 2
    I appreciate the very detailed response, but #5 is the only point that actually addresses my question, and it doesn't provide a solution to the core problem, which was preventing access to the private key to prevent any user on the jump box from accessing any host in the cluster. I don't need a how-to, although I'm sure someone else will find it helpful.
    – Mikkel
    Jul 8 '15 at 18:07
  • Chroot, Rbash, Lshell... I'm not sure what distribution you're working with so I can't give you a blanket solution that covers everything. I'm giving direction which is what you asked for. If you re-read your question. I've adequately answered your question plenty, the issue is you're not asking for an answer. You seem to be asking for a solution, but in security, there's no one answer to a security solution. You'll have to put in some of your own research on that item based on the OS you're working with as your jump host. Jul 8 '15 at 18:11

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.