Accessing a USB IO Module in a Network by using Linux and socat

The LucidControl USB IO Modules can be shared over a network by using a network device server running ser2net. The network device server can be any computer running Linux like e.g. the Raspberry Pi.

Network Device Server and Client Computer

Network Device Server and Client Computer

As it can be seen in the illustration, the application on the client computer is routing the data through the TCP socket. This kind of connection makes it necessary that the application running on the client supports socket connections. In our case the LucidIoCtrl command line tool and the dotNet library offer currently support of TCP socket connection in addition to the standard virtual serial port connection.

For client applications that rely on local serial devices there exists a a flexible method which creates virtual devices on the client computer that are connected to a remote device on a network device server. This allows e.g. using existing software working with local serial ports without adaption of the source code.

USB IO Module Network Device Server with socat and ser2net

USB IO Module Network Device Server with socat and ser2net

The picture shows the principle of this method. On the network device server there is no change necessary and ser2net is running with the same options explained in the last article.

On the client computer the Linux tool socat comes into the game. It is a powerful program that can redirect data streams in general. socat establishes bidirectional data streams between files, pipes, devices (serial line or a pseudo terminal) and different kind of sockets (UNIX, IP4, IP6 – raw, UDP, TCP and SSL).

More information on socat including many examples can be found here and here.

I concentrate in the following on using socat in order to create a virtual serial device on a client computer which is routed to a TCP socket created on the network device server by ser2net.

Installing and configuring socat

socat can be installed by

apt-get install socat

After installation, socat can be started on the client side and the complete configuration is done by command line parameters.

socat pty,link=/dev/lio0,nonblock,raw,echo=0,ignoreof,waitslave tcp:RPI-AZ-2:4001

This instruction creates a device /dev/lio0 which is connected to port 4001 of the network device server RPI-AZ-2. The option nonblock opens the device in non-blocking mode, raw instructs socat to send data unprocessed and echo=0 switches local echo off. In our tests these three options could be omitted without any influences. But, the option ignoreof is important and causes that socat stays active after the port was closed by the client application. Since e.g. the LucidIoCtrl command line tool closes the serial port when it returns, socat must not close the device in order to be responsive for further calls.

As a short form the following call of socat is working well:

socat pty,link=/dev/lio0,ignoreof,waitslave tcp:RPI-AZ-2:4001

Calling socat blocks the terminal and it is also not useful to start socat in a script this way because it does not return.

(socat pty,link=/dev/lio0,ignoreof,waitslave tcp:RPI-AZ-2:4001) &

By calling socat this way a background process is started. The prompt returns immediately after the process has been installed and a script running this line does also not block anymore.

Note: It might be necessary to run socat as root. In this case socat assigns the root user as owner of the created device what prevents other users from accessing the device. This is not desired as it would require all applications accessing the created virtual port need to have root permissions.

(socat pty,link=/dev/lio0,user=klaus,group=dialout,mode=660,ignoreof,waitslave tcp:RPI-AZ-2:4001) &

The parameters user, group and mode make it possible to specify the privileges of the created device. In this example the device /dev/lio0 belongs to the user klaus, the group dialout and can be accessed by the user and the group. All users accessing any serial port must be member of the group dialout, so it makes sense to create also the virtual device with this group assigned.

When socat is running, the virtual device is accessible and LucidIoCtrl can communicate with the remote device like this:

Accessing a remote USB Analog Input Module connected to a Network Device Server

Accessing a remote USB Analog Input Module connected to a Network Device Server

This instruction runs the LucidIoCtrl command line tool on the client. It connects through the remote network device server to the USB IO module and requests device information of the USB analog input module.

socat as ser2net Alternative on the Network Device Server

Since socat is a bidirectional relay for data streams it can also be used on the network device server as a substitution for ser2net. While ser2net is a quick and convenient solution which is easy to setup, socat offers more options and supports SSL encryption.

socat tcp-l:4001,fork,keepalive,nodelay,reuseaddr /dev/ttyACM0,b115200,raw

This call uses the local device /dev/ttyACM0 and listens to TCP port 4001. It routes all data for this port to the device like ser2net does. The parameter fork creates a child process, the parameter keepalive supports TCP keepalive packets, nodelay opens the port with non-delay options and reuseaddr allows reusing an address even if it is already used by socat. Raw data transmission is used and the baudrate is set to 115200bps. Since the USB IO modules are virtual serial devices, which do not need an initialization of the serial port parameters, some parameters can be omitted.

I use a reduced parameter set which works without any implications, and we start a background process listening on TCP port 4001.

(socat tcp-l:4001,keepalive,reuseaddr /dev/ttyACM0) &

Note: If ser2net is already running on the system it must be disabled before socat is used by calling:

/etc/init.c/ser2net stop

Encrypting Data Streams with socat

Opening a TCP port that is routed to a device can become a security leak and there is a potential risk that data are eavesdropped, intercepted or injected from a manipulating communication partner. This could result e.g. in wrong temperatures being transmitted or unintentional changes of the state of a digital output by some fraudulent computer.

If security aspects are important for a relayed port, socat supports encryption based SSL certificates that can be created by using OpenSSL. Beside of the data encryption this method allows also to grant different access rights to some USB IO modules connected to a network device server. These access rights can be granted on module level what means that e.g. an USB analog output module and a USB analog input module, both connected to the same computer, can have different access privileges.

USB IO Module Network Device Server with socat and SSL Data Encryption

USB IO Module Network Device Server with socat and SSL Data Encryption

The picture shows the principle how the data encryption works. All configuration for the data encryption is done by socat parameters and it is not necessary to change the application running on the client computer when adding secure data encryption.

SSL is consists of a private key and trust certificates that can be distributed on any computer that is trustworthy.

OpenSSL is used in order to create private keys and trust certificates for the network device server and all client computers. A good tutorial for this can be found here.

The created trust certificates can be exchanged between all communication partners. The generated private key files and the merged PEM files must be securely saved on the related computer.

After the certificates have been distributed, socat is ready for SSL encryption.

(sudo socat openssl-listen:4001,keepalive,reuseaddr,cert=$HOME/server.pem,cafile=$HOME/client.crt /dev/ttyACM0)&

This command starts the network device server listening on SSL port 4001. It encrypts the data with the server private key stored in server.pem and it trusts all clients whose trust certificates are stored in the file client.crt.

(sudo socat pty,link=/dev/lio0,user=klaus,group=dialout,mode=660,nonblock,raw,ignoreof, waitslave openssl-connect:RPI-AZ-1:4001,cert/$HOME/client.pem,cafile=$HOME/server.crt) &

This command creates a virtual device /dev/lio0 on the client computer. All data sent to this device are encrypted with the client private key stored in client.pem.

Compared to the calls of socat explained earlier, the last two calls are only extended by the parameters cert and cafile. The parameter cert refers to the PEM file which contains the private key and the public certificate of the communication partner. The parameter cafile links to a file which contains all trusted certificates.

Conclussion

In this article I have shown how a USB IO module can be shared within a network as a device having an entity in the /dev folder. The advantage of this method over the TCP port sharing is that existing software, which is using device names, can be used without adaption.

socat is a powerful tool that can create bidirectional redirections of data streams. In the first part of the article I have shown how a client running socat can connect to a network device server running ser2net what is a very convenient way.

In the second part of this article I explained how to use socat on the client computer as well as on the network device server replacing ser2net on the network device server. The reason for this was that employing socat on the network device server offers more functionality such as data encryption.

The SSL encryption supported by socat adds more security to the transmitted data and is the foundation of the further work.

Accessing USB IO Modules remotely by SSH (Secure Shell)

The LucidControl USB IO modules operate with Windows and Linux operating systems and they are the perfect solution turning your computer into a data acquisition and control center.

The USB IO modules are able to acquire and control analog and digital signals. They can for example measure temperatures, switch analog as well as digital lines and generate analog voltages and currents. The USB analog output module can be used in order to build 0-10V or 4-20mA interfaces.

Raspberry Pi 2 B Network Device Server with 4 USB IO Modules connected

Raspberry Pi 2 B Network Device Server with 4 USB IO Modules connected

Since the Raspberry Pi B+ and Raspberry Pi 2 B have overcome some issues regarding the USB function and provide now 4 reliable USB ports, these devices are very interesting for building network device servers. Network devices servers allow to access the LucidControl USB IO modules remotely and to forward measured values or control some electronic consumers via a network.

There are several ways how to make a USB IO module available via a network. One solution is e.g. to install a web server like Tomcat on the Raspberry Pi and develop a web interface controlling the USB IO module. Another very handy solution is the secure shell (SSH) which is available for Linux since ages.

The secure shell is a network client-server protocol which provides a remote command-line login and allows the execution of applications on the remote system.

LucidIoCtrl is the command-line tool which is a simple but convenient interface that is able to run all commands of a LucidControl USB IO module. LucidIoCtrl is a console based application that is available for Windows and Linux including a version for the Raspberry Pi and the Beagle Bone Black. It does not need any libraries and runs out of the box on all systems.

In the following I describe how to setup the secure shell and how to use the USB IO modules remotely.

Setting up the Secure Shell

SSH Server makes USB IO Modules accessible via a network

SSH Server makes USB IO Modules accessible via a network

Check in advance if SSH is available on your system by executing the ssh command. If the tool is not presently installed it can be done by:

apt-get install ssh

After the installation has finished the secure shell package is ready to use on your computer, and a connection to a remote computer can be started by:

ssh user@remote

In order to log in the user needs to enter the password for authentication.

SSH console Raspberry Pi login

SSH console Raspberry Pi login

In this example the user klaus logged in on the client computer DEC-VBOX-1 connects to the remote computer RPI-AZ-1.

Since in the example no explicit user name has been passed to the SSH command, the user name of the user already logged in on the client computer is used on the remote server, too. A user account for the remote login user must be set up in advance.

After the password has been entered, the command prompt of the remote system appears and commands can be executed on the remote system.

SSH console request USB IO Module Device Info

SSH console request USB IO Module Device Info

In this example the device information of the LucidControl USB IO module connected to /dev/ttyACM0 are queried by the LucidIoCtrl tool.

Key based automated Secure Shell Calls with Key Pairs

A drawback of the explained method is that a password is needed for authentication and it must be entered in order to log in to the remote system.

ssh user@remote ./LucidIoCtrl –d/dev/ttyACM0 –i

This SSH command is running on the client and is executing the LucidIoCtrl command on the remote computer. But for authentication the password must be entered and the attention of the user is needed every time the command is executed what prevents automation of SSH calls.

Automated calls to remote systems can be achieved by using a key pair which consists of a public key which can be published to any remote system the computer needs to connect to. The private key remains securely stored on the client computer.

A key pair can be created on the client system by:

ssh-keygen –t rsa –C user@remote

The command asks for a directory and a passphrase which are both optional. The passphrase is a password that protects access to the private key. The explained method is also secure if the passphrase is skipped. The generated key pair is stored in ~/.ssh where id_rsa and id_rsa.pub can be found.

Note: When a passphrase was entered it protects accessing the private key what makes it necessary to enter the passphrase at least once when the private key is accessed the first time. Using the ssh-agent can do this for you. The ssh-agent service sends the passphrase to the SSH on request.

Once the public key (id_rsa.pub) and the private key (id_rsa) have been generated, the public key can be distributed to the remote system.

ssh-copy-id –i ~/.sha/id_rsa.pub user@remote

The program ssh-copy-id copies the key to a remote system. The distribution of the key needs the password of the user before the key can be copied to the remote system.

SSH connection with automated login

SSH connection with automated login

In this example the LucidIoCtrl application is executed on the remote computer RPI-AZ-1. The LucidIoCtrl command queries the device information from the USB IO module connected to /dev/ttyACM0 and returns that a USB analog input module with the voltage range 0-10V is connected to the port.

Using SSH with a Windows Client Computer

Linux provides SSH as a set of standard tools which are not available on Windows computers. PuTTY is an open source tool that extends Windows with several useful programs in order to interact with Linux systems. A download can be found here.

PuTTY Configuration Window

PuTTY Configuration Window

The screenshot shows the main window of the PuTTY application. PuTTY is a client application for several protocols like Telnet and Rlogin and also SSH. In the main window of PuTTY settings for a connection can be made and saved as a session name. Session names are names that relates to the remote computer connection and bring more explanation to the user. The session names are used by the command line tool plink.

Clicking on the open button connects to the remote system and asks for a user password.

putty_1

The procedure shown here is the same as we saw earlier with the Linux SSH client. After entering the password for the specified user name, access is granted by the SSH server and e.g. applications can be started on the remote server system.

putty_2

As you can see we opened now with PuTTY a SSH connection to RPI-AZ-1 and queried the device information of the USB analog input module.

In the next steps I will explain how to automate SSH calls with the PuTTY client. The principle is the same as we did earlier with the Linux SSH client and is based on a public and private key pair.

Note: During the first SSH connection a security breach message appears. The reason for this is that the client does not know the host key of the server. This message can be confirmed the very first time but if it appears again it is possible that a security breach occurred.

PuTTY comes with the PuTTY Key Generator which is able to create SSH key pairs. The keys generated by ssh-keygen cannot be used with PuTTY or at least I found no easy way to reuse the previously generated key pair with PuTTY.

PuTTY Key Generator

PuTTY Key Generator

It is useful to specify a comment related to the key as well as a passphrase protecting the private key, but both is optional and can be skipped for a test. Especially when automated calls without user interaction are what you want to do, keys without passphrase should be considered. Otherwise, the system will ask for the passphrase at least once in order to give access to the private key.

In our case we work with the default settings and generate a SSH-2 RSA 2048 bit key. It is up to you to decide if this is sufficient for your application.

Clicking onto the Generate button starts the creation of the key pair. During the generation of the keys it is necessary to move the mouse what creates some kind of randomness.

The generated keys are stored in separate files by the save key buttons. You should save both keys securely. Especially the private key should not be made accessible to others and must not be distributed to any other system.

The stored public key must now be appended to the authorized_keys file of the SSH server. Using a Linux client ssh-copy-id takes care on this and distributes the public key to the remote system. For Windows such a tool is not available and it must be done manually.

Login with PuTTY to your SSH server with the account for that you intend to copy the public key.

Check if the ~/.ssh directory is present in your home directory. If not create it and grant read/write access to the user.

mkdir ~/.ssh
chmod 700 .ssh

Change into the ~/.ssh directory and create the file authorized_keys by opening it with e.g. nano

nano authorized_keys

Select the public key in the PuTTY key generator windows edit control and copy it to the clipboard. Select the PuTTY Window with the authorized_keys file opened and insert the public key to the file by a right mouse click. Save the authorized_keys file when leaving nano with CTRL+X.

chmod 600 authorized_keys

Finally, the permissions of the authorized_keys file must be set.

PuTTY SSH Private Key Configuration

PuTTY SSH Private Key Configuration

In the last step the private key must be linked to the PuTTY session and the changes have to be saved for the current session name.

SSH Login with PuTTY using Key Pairs

SSH Login with PuTTY using Key Pairs

When you connect to the remote server the next time you will get a command prompt immediately without the need of a password.

Now we want to realize automated calls. PuTTY comes with the Plink application which is the actual replacement of the SSH command under Linux. For automatic calls it is not necessary to start the graphical user interface but Plink in the command line instead.

Executing LucidIoCtrl on a remote System with plink

Executing LucidIoCtrl on a remote System with plink

In the example above we connected to RPI-AZ-1 and executed the LucidIoCtrl command which requests device information form the analog input module connected to /dev/ttyACM0.

Summary

In this article I described how a SSH connection can be set up and automated requests can be sent to our LucidControl USB IO modules. On Linux computers the SSH tools are available and I show how to install and how to use them on the client and server computers. In a next step I described how to establish a SSH connection with a Windows client and PuTTY.

The final goal of the article is to show how to login to a remote system by using key pairs which grant secure access to the remote system without the need of entering a password. This makes automatic requests possible executing a program on a remote computer.

By accessing the LucidIoCtrl command on the remote server extends it with device server functions. In our case the Raspberry Pi is used as a device server making the USB IO modules available e.g. over the Internet. For this it only needs the standard SSH software package installed and the LucidIoCtrl command line tool.

In the next articles I will describe how a device server can be realized without any third party program installed on the remote server. Linux has standard tools which allow sharing devices by directing traffic over the network directly to a Linux device like our USB IO modules.