Elasticsearch api secure using SSH tunneling
SSH is a method for secure remote login (encrypted secure shell connection) from one machine to another machine. There are several alternative strong authentications for SSH. SSH protects the communication also with encryption.
SSH operates on TCP port 22(Default ssh assigned port) by default. The server listens on port 22 for incoming connections. If the authentication is successfully completed , open the correct shell.
There are three different encryption methods using SSH.
- Symmetric encryption
In here, symmetric encryption is using one secret key for both encryption and decryption of a message by the both the client and the server.
2. Asymmetric encryption
This is using two secret keys for encryption and decryption. one is private key and other one is public key. The public key is distributed and shared with the client and the server. The relation between private key and public key is highly complex.
3. Hashing
Now we consider how we can elasticsearch securing using ssh tunneling.
I used fr.janalyse library to create SSH session.
"fr.janalyse" %% "janalyse-ssh" % "0.10.3
- Create a ssh tunnel between service and elasticsearch cluster.
- Local port binding for 9200 and 9300. After that we can call elasticsearch REST api using localhost as well as we can add transport addresses using localhost as host. We should use binding ports.
- localhost:34586 -> elasticsearch:9300 (9300 is node communication port. when we use java elasticsearch client , we should connect to that port in elasticsearch)
- localhost:45123 -> elasticsearch:9200 (9200 is elasticsearch REST api port)
- SshOpts class is used to set all the configurations and settings. Here I am using private key (pramod_id_rsa) to authentication to create SSH session.
Important - We should include those private key in resource package in project.
- openSSH method is used to create the SSH session.
- createClient method is used to create elasticsearch client. we call openSSH method within that method. after connection is success, we can do local port binding for 9300 and 9200 using remote2Local method.
- After we added transport address to the client. host is localhost and port is binding port for 9300.
Restart SSH sessions
Most probably there is a chance to disconnect that ssh tunnel. Some times elasticsearch cluster may be down. There are lots of reasons for SSH tunnel down.
So what we can do, when SSH tunnel is down. We can restart the SSH tunnel after checking SSH connection is live or not.
There are two configurations in elasticsearch java transportclient. One is client.transport.nodes_sampler_interval and other one is client.transport.ping_timeout (Default value is 5 seconds). Elasticsearch client checks whether remote nodes (added transport addresses) are still accessible by pinging to each nodes every 5 seconds.
So we can use hostFailureListener to listen the node connection failures. By default, when node connection is failed due to SSH tunneling down, that listener is called onNodeDisconnected method every 5 seconds.
This is the way how to add HostFailureListener ,
val hostFailureListener = new DefaultHostFailureListener()
val client = new PreBuiltTransportClient(settings, hostFailureListener.PRE_INSTALLED_PLUGINS, hostFailureListener)
How it works,
- When we start the service,
SSH tunnel is created with local port forwarding for 9200 and 9300.
2. Check whether SSH tunnel is exist or not.
3. After SSH tunnel is disconnected and restart the SSH tunnel.