Skip to content

A SSH library based on JSch which includes support to wrap SSH-connected components

License

Notifications You must be signed in to change notification settings

ExpediaGroup/hcommon-ssh

Repository files navigation

Hcommon-ssh

This library provides common functionality which allows network-connected components to route traffic through SSH tunnels.

Start using

You can obtain this library from Maven Central:

Maven Central Build Status Coverage Status GitHub license

Overview

Components can be proxied to use a SSH tunnel. A SshSettings object provides the basic configuration required to establish the SSH connection and the SSH tunnel.

This library uses Java Proxies to handle the SSH tunneling logic so components must implement the marker interface Tunnelable.

An out-of-the-box factory is provided to handle the component wrapping: TunnelableFactory. The factory uses a MethodChecker to verify whether the method being invoked must ensure the SSH tunnel is open or whether the method must close the SSH tunnel. In order to proxy a component the wrap method of this factory class must be invoked passing the component to wrap, an instance of MethodChecker and the remote host and port to which the component will be connecting.

Example:

// Mark the client as tunnelable
public class MyClient implements Tunnelable, ... {
  ...
}
...
public class MyClientSupplier implements TunnelableSupplier<MyClient> {
  ...
}
...
MyClientSupplier myClientSupplier = new MyClientSupplier();
...
SshSettings sshSettings = SshSettings
  .builder()
  .withRoute("hop1 -> hop2")
  .withKnownHosts("/home/user/.ssh/known_hosts")
  .withPrivateKeys("/home/user/.ssh/id_rsa_common")
  .build();
TunnelableFactory factory = new TunnelableFactory(sshSettings);
Tunnelable wrapped = factory.wrap(myClientSupplier, MethodCheck.DEFAULT, "my-remote-service", 8080);

SSH tunnel syntax

The tunnel route expression is described with the following EBNF:

path = path part, {"->", path part}
path part = {user, "@"}, hostname
user = ? user name ?
hostname = ? hostname ?

For example, if the remote service runs on the host remote-server-box:1024 which can only be reached first via bastion-host and then jump-box then the SSH tunnel route expression in SshSettings will be bastion-host -> jump-box and host remote-server-box and port 1024 will be provided as method parameters in the factory. If bastion-host is only accessible by user ec2-user and jump-box by user user-a then the expression above becomes ec2-user@bastion-host -> user-a@jump-box.

Once the tunnel is established the library will set up port forwarding from the local machine specified to the remote machine. The last node in the tunnel expression doesn't need to be the target server, the only requirement is that this last node must be able to communicate with the remote-server-box. Sometimes this is not possible due to firewall restrictions so in these cases they must be the same.

All the machines in the tunnel expression can be included in the known___hosts file and in this case the keys required to access each box should be set in the SshSettings privateKkeys property. For example, if bastion-host is authenticated with bastion.pem and both jump-box and remote-server-box are authenticated with emr.pem then the property must be set as"<path-to-ssh-keys>/bastion.pem, <path-to-ssh-keys>/emr.pem".

If all machines in the tunnel expression are not included in the known___hosts file then the SshSettings property strictHostKeyChecking should be set to no.

To add the fingerprint of remote-box in to the known___hosts file the following command can be used:

ssh-keyscan -t rsa remote-box >> .ssh/known_hosts

Legal

This project is available under the Apache 2.0 License.

Copyright 2019 Expedia, Inc.

About

A SSH library based on JSch which includes support to wrap SSH-connected components

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages