Improving security for network-connected, Linux-based systems
March 04, 2015
Embedded systems' ability to access devices over the Internet or local networks facilitates a wide range of convenient interactions. The evolution of...
Embedded systems’ ability to access devices over the Internet or local networks facilitates a wide range of convenient interactions. The evolution of the Internet of Things (IoT) means fast growth of embedded networks. For these applications, network security has become a great issue. The resources of embedded systems are too limited and may hardly provide reliable protection against cyber attacks. High-performance devices with Linux may have advantages for secure network access.
Scripts and techniques can improve the security level of network access for these Linux-based devices. The goal is to access a device as a server for remote control and administration. This can be conducted in two levels: the SSH-level for secure remote shell access and SFTP file transfer, and IP-level protection.
Remote access over SSH shell and SFTP presents the greatest opportunity of controlling the target embedded system with Linux. Enabling this function is a convenient way for administrating the device. The SSH protocol performs a high level of security and cryptography. There are several possible configurations of the “sshd” utility associated with the SSH shell and SFTP server services to improve SSH-level security.
Among popular Linux distributions for embedded systems (such as Angstrom or Arago-project), the “Dropbear” utility is a default SSH server. Unfortunately, it provides a limited set of configuration options. Important configuration possibilities such as users’ permissions are disabled in this utility. So if the target device is going to have remote access, installing “OpenSSH” server would be a better idea. To change the SSH servers, remove the Dropbear starting script (or move it, like in the example below) and install the OpenSSH package:
mv /etc/init.d/dropbear /dropbear_script_backup
opkg install openssh
Using a non-standard SSH port
Using a non-standard SSH port is the easiest way to protect against “coincidental” discovery. It may help avoid many attacks over the Internet or LAN based on scanning the most-used TCP ports to find specified services on different IP addresses in the network. The simple way to lower this risk for the SSH protocol is to change the standard port 22 to a non-standard one. This option works for any SSH server. The only note is the need to open the specified port on the firewall on the client side.
The SSH port number is configured in the “/etc/init.d/sshd_config” file like this:
Configuring user permissions for SSH access
The SSH server options include a number of methods to limit user permissions. For both secured shell and SFTP services, the options “PermitRootLogin”, “AllowUsers”, or “DenyUsers” limit the logins able to connect to the device over SSH. For SFTP, more parameters are available to change the root directory paths. This method is important to protect the system parts that include critical and confidential data. This option allows the configured users to operate only inside their directories and sub-directories, so you can leave them in their “sandbox.” The option “Subsystem SFTP internal-SFTP” combined with “ChrootDirectory” allow to change the root directory for specified users. The “ChrootDirectory” section for all configured logins should be placed at the end of the configuration file. When setting up the directories for different users, the owner of that directories should be a root user.
To configure the users SSH permissions, edit the file /etc/init.d/sshd_config as in the example:
#list of allowed users:
AllowUsers root user1 user2 user3
Subsystem SFTP internal-SFTP
#changing the root directory for user1 and user2:
Match user user1 user2
#changing the root directory for user3:
Match user user3
Remote access to your application over SSH
For performing non-standard user access to your application in the embedded system, it is convenient to use the SSH protocol as a secure layer for network communication.
A common way is to run your service as a server listening to the specified TCP port. To provide the SSH connection, you may use “libssh” – an open-source project licensed under the LGPL. The project has several examples including the sshd source code that provides a great basis to build your server application. Note: this solution is not connected to the OpenSSH server and requires its own port number and user management.
Another option is to use the existing running OpenSSH server for your service. The idea is to replace the shell utility with your own application for specified users. This time users would interact with the remote system over the standard input/output interface like a terminal. This solution is a more efficient way to organize secure remote access with the exact functionality you need. To replace the shell for users, edit their parameters in the “/etc/passwd” file by replacing the last option with the path to your application:
“Iptables” is a powerful tool for protecting remote access to the target Linux system at the IP level. Iptables allows the system to filter the traffic independently of the application-level network protocol. It is the most universal option that may work for almost every platform.
Iptables support should be turned on during the Linux kernel configuration. Pay attention that some necessary iptables options like “conntrack” or “connlimit” may be turned off in the kernel by default so turn them on to use more iptables possibilities.
Launching iptables script on system start
The iptables utility works as a network traffic filter. The filter is performed as chains of rules applied by running the “iptables” command with different parameters. The rules are set together in a script file. To put the iptables to the initial state, begin the script with the example rules below:
iptables -F #flush all chains
iptables -X #delete all chains
#accept network traffic by default:
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -A INPUT -p icmp -j DROP
To enable iptable protection at system start-up, write the desired rules to the script file and execute:
sudo chmod +x
sudo update-rc.d defaults
Prevent brute force attacks
Brute force is the biggest security problem when using the SSH protocol. A simple firewall can be set up using iptables to prevent brute force attacks. The idea is to block the IP addresses that flood the SSH port and limit the maximum number of opened connections. The script below serves this purpose:
#create the chain to check the number of tries to connect the port:
iptables -N SSH_brute_check
#if during last 300 seconds any IP address opens more than 20 new connections – block it
iptables -A SSH_brute_check -m conntrack --ctstate NEW -m recent --update --seconds 300 --hitcount 20 -j DROP
#else – allow and add to the checking chain
iptables -A SSH_brute_check -m recent --set -j ACCEPT
iptables -F INPUT #flush input chain
#allow established connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
#send all tries to open new connections on port 22 to the checking chain
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j SSH_brute_check
Whitelist/blacklist IP addresses
If the clients’ IP addresses are static, the best way to perform network security is to allow access for certain IP addresses only. That means no other user except the specified ones would be able to access the target embedded system remotely. This may be done by creating a whitelist of legal IP addresses. For the example script below, the admitted IP addresses are written down in the
The iptables script to make this work is described below:
while read VAR; do
iptables -A INPUT -s $VAR -j ACCEPT
You may use the opposite strategy – forbid specified IP addresses by adding them to the blacklist. The example of blocking the IP addresses from the blacklist is performed below:
while read VAR; do
iptables -A INPUT -s $VAR -j DROP
Turn off IPv6 support
The described services and methods use the IPv4 protocol. The secure configuration of the IPv6 protocol is ignored, which makes it unsafe to keep enabled. If IPv6 support is turned on in the kernel, then it should have additional protection. Or, if you don’t need it, you may just turn it off by adding this line in the /etc/sysctl.conf file:
net.ipv6.conf.eth0.disable_ipv6 = 1