To run containers securely, you should consider how the rest of your environment, including the host and the operating system, are configured and hardened. An out-of-the box install of just about any Linux distribution can run the Docker daemon and Docker containers, but it might leave your host exposed any number of security and performance concerns. This post presents a starting point for configuring a production-grade host.
There are three main steps:
- Strip the operating system of any extra services and software so that only the tools and services required to run Docker are up and running.
- Install and configure the Docker daemon to run your containers. This includes both performance and security settings that configure Docker to be more suitable for a production environment rather than a development environment.
- Configure the firewall to only allow incoming traffic for SSH by default and open ports on-demand that are required by the containers for external communication.
The more software you have installed, the larger the attack surface. Install a minimal version of the host OS from the official image. If you have previously installed the OS, then consider:
- Removing all development tools (compilers, etc.).
- Removing all services listening so that only port 22 is exposed for SSH access. Your firewall configuration (see below) should block traffic intended for any other running services, but it is best practice to stop and remove any unnecessary additional services.
Keep your system updated
Linux distributions frequently release updated packages to address vulnerabilities as soon as possible. Updating your system reduces potential security risks by ensuring that the latest versions of libraries and programs are running. Package managers, such as Yum, let you list and install just the security updates:
$ sudo yum update --security
Create a new user
You don’t want to run everything on your host using the root user, so add a new user and administer your machine as that user.
Configure the SSH daemon
You don’t want people to be able to login to your system using the root user. You also don’t want people to login using a password either. In your SSH daemon configuration file, sshd_config, disable root login and password-based authentication. This protects you from brute force attacks against your users’ passwords. For each user with access to the machine, generate a public/private key pair, and add the public key to ~/.ssh/authorized_keys in their home directory.
Stop all services other than the SSH daemon
Ideally, you only want sshd listening on your host (your running containers might also be listening on various ports). Since host is dedicated to running containers, it should not be running any additional services, although exceptions exists. To further enhance security through obfuscation, you could also change the port on which sshd listens.
The CIS Docker Benchmark provides a number of guidelines that show best practices for configuring and securing the Docker daemon. This section highlights some of the more important options.
By default, all containers on a host that are connected to the default network bridge can communicate with each other. A compromised container, therefore, could listen to packets from other containers, leading to unwanted disclosure of information. The –icc=false option explicitly disables inter-container communication and forces you to properly segment apps using dedicated networks.
--tlsverify --tlscacert --tlscert --tlskey
By default, the Docker daemon listens to connections on a local UNIX docket only. However, if you expose the Docker daemon to the network, configure TLS authentication for the daemon API. Otherwise, anyone with access to that port will have full access to Docker daemon and, in turn, to the host system.
This option disables all operations on v1 registries. The latest v2 registries have many security improvements over the legacy v1 registries.
Set default ulimits for your containers. This option lets you set up hard and soft limits on the number of processes and files. This helps ensure that a container cannot consume all of the host’s resources in a denial-of-service attack, which would render the machine and other containers inaccessible. The following example shows sensible defaults.
--default-ulimit nproc=1024:2048 --default-ulimit nofile=1020:2048
Iptables is a popular firewall available on all Linux distros. At a high level, your firewall configuration should drop all input and forwarding traffic, and whitelist all ssh traffic.
1. Configure the iptables rules. In the final rule replace
$ sudo iptables -P INPUT DROP $ sudo iptables -P FORWARD DROP $ sudo iptables -A INPUT \ -p tcp \ -s 0/0 \ -d <serverip> \ --sport 513:65535 \ --dport 22 \ -m state \ --state NEW,ESTABLISHED \ -j ACCEPT 2. Save the iptables rules $ sudo service iptables save 3. Verify iptables rules $ sudo iptables --list
Get a downloadable deep dive on this topic in Twistlock resources.
- Container Security
Follow us on Twitter
Follow us on Twitter for real time updates on the cloud native ecosystem, Twistlock product, and cloud native security threats.
5 Questions to Ask When Choosing a Cloud Native Security Platform for DevOpsRead the Blog
CVE-2018-1002105: Critical K8s VulnerabilityRead the Blog
Advanced runc Debugging for Fun and ProfitRead the Blog
Introducing Twistlock Support for AWS Lambda LayersRead the Blog
Cloud Native Security Intelligence: Integrating with AWS Security HubRead the Blog