Security is always a major concern in an application. But when an application attempts data communication over a network, it becomes even tougher ordeal to keep the connection secure. In this post we will discuss about Secure Shell (SSH) to add an extra security edge to your application when it communicates over a network.
What is SSH Tunnel?
SSH is an encrypted network protocol generally used for remote shell service, secure data communication, command execution etc. In SSH tunneling, a payload protocol is wrapped around the SSH protocol (the delivery protocol) and sent over the network.
When is SSH tunneling useful?
SSH tunneling is great if you don’t want any changes on the server, say when creating an agent-less monitoring tool or as a replacement for VPN. As SSH is the hub for remote system login, you can assume that a SSH daemon is running in the remote server, if not it can be easily installed or the communication can be routed from any other SSH host. You need not try to build your own encryption protocol as the public-key cryptography used by SSH protocol for authentication is an industry standard.
How to SSH tunnel?
A very good use case for SSH tunneling is MONyog, an agent-less MySQL monitoring tool. In MONyog, an embedded MySQL client collects data from MySQL servers in regular intervals. But again the connection between MONyog and MySQL server can be insecure. On a Linux host SSH tunnel can be created using this following command.
ssh -L <listening port>:<REMOTE_MYSQL_HOST>:<REMOTE_MYSQL_PORT> <SSH_USER>@<SSH_HOST>
On windows you can use PUTTY or PLINK (a PUTTY variant). In the above example, every time MONyog’s MySQL client connects to localhost:<listening port>, MONyog in turn connects to the MySQL server over a secure connection. As MONyog monitors hundreds of MySQL servers, it becomes a tedious job to create that many tunnels manually. For usability, a native SSH tunnel support is necessary inside an application like MONyog. Here is where the SSH client library comes in. MONyog uses libssh for this. Why? Immediate answer will be it is richer command syntax, cross-platform support and licensing is great.
How does it work?
The work flow diagram of MONyog’s SSH Tunnel looks something like this.
Creating a SSH session
First we create a SSH session with ssh_new function, connect to the SSH server with ssh_connect and then authenticate the connection.
ssh_session my_ssh_session = ssh_new(); // Create new session ... // Set host and user ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, <SSH_HOST>); ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, <SSH_USER>); ... ssh_connect(my_ssh_session); // Connect to server ... if(ssh_userauth_password(my_ssh_session, NULL, <SSH_PASSWORD>) != SSH_AUTH_SUCCESS) { // Try authentication ...
For simplicity we have used password based connection. SSH library also supports key based authentication.
Creating a local socket
In a separate thread we create a socket and bind it to the loop back address and a listening port say XYZ. This socket connects the MySQL client with the SSH tunnel. Any request to this port is written into a SSH channel (creation of which is discussed in next section) which in turn is forwarded to the MySQL server. The response from the MySQL server, received on the SSH channel is written back to the socket. This is how MySQL client gets its result set.
Creating a SSH Channel
Whenever the local socket receives a request from the MySQL client, we create a SSH channel with ssh_channel_new function, then open the channel for TCP/IP forwarding with channel_open_forward function.
ssh_channel channel = ssh_channel_new(session); // Create a ssh channel ... if(channel_open_forward(channel, <REMOTE_MYSQL_HOST>, <REMOTE_MYSQL_PORT>, "localhost", 0) != SSH_OK) { // Forward connection ...
Creating a MySQL connection
mysql_real_connect function creates a MySQL connection. Instead of connecting to the remote server we connect to the local socket. The MySQL connection is now ready to execute queries.
MYSQL *mysql; ... if (mysql_real_connect (mysql, "localhost", <SOME_MYSQL_USER>,<SOME_MYSQL_PASSWORD>, NULL, XYZ, NULL, 0) == NULL) { // Try connecting the local socket ...
For your reference, you can download a sample where we have demonstrated a generic example related to SSH tunneling .This technique works like a charm. You can either use libssh the way we mentioned in this post, or you can also try other client implementations for SSH2 protocol like libssh2 and Paramiko for Python.
Hoping this post has answered all your questions regarding securing your application using SSH tunneling. We always have our commenting area below open for your questions regarding the same.
PlanetMySQL Voting: Vote UP / Vote DOWN