Server security is one of the tiny elements in application development that cannot be ignored. It can make or mar you. As such, giving adequate attention to it cannot be overemphasised.
In today’s world where hackers derive delight in taking down full service or data centres, it becomes important to keep this bit at the top of the list when provisioning a new server or deploying to an existent one. While patches and security updates are just as important, they wouldn’t do so much in some cases—especially around coordinated attacks like DDoS.
For a very long time, setting up application firewalls has been one of the ways of securing servers. IPTables, a program that defines a set of rule showing what packet can go through what port in a server, has been favoured.
According to Wikipedia, IPtables is a user-space application program that allows a system administrator to configure the tables provided by the Linux kernel firewall (implemented as different Netfilter modules) and the chains and rules it stores.
IPTables exist in many flavours of Linux. Among all of the open-source firewalls available today, it’s the standard firewall bundled with most Linux distribution such as Ubuntu, CentOS and Fedora.
A standard IPTables is generally broken down into 3 units otherwise known as chains. These chains are INPUT, FORWARD and OUTPUT.
Chains INPUT - This chain controls the behaviour of incoming traffic. If a user is accessing a website on a server, the IPTables will try to match the incoming request to a rule that has been defined in the INPUT chain. This rule will typically check what the destination port, port 80, says about web traffic.
0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:http
OUTPUT - This chain manages every outgoing connection. Typically, all traffic generated by the host server e.g a
FORWARD - This chain controls all network packets routed through the server.
Before we go any further, it’s important to highlight the 3Ps of IPTables: Packet, Port and Protocol. Packet - A block of data transmitted across a network. Think about a packet like the mail delivered by a mailman. Port - A port is a logical connection place. It has a numerical designation; 80, 22, 443, etc. Protocol - A set of rules governing the exchange or transmission of data between devices. E.g: TCP, UDP.
To setup a rule, we run the following:
sudo iptables -A INPUT -i lo -j ACCEPT
The command above reads “ACCEPT traffic on the loopback interface on the INPUT chain. Loopback interface here is a virtual networking interface that a computer uses in communicating with itself, hence the term, loopback.
To check the loopback interface on a Linux machine, run
To set up iptables rules for HTTP traffic we will run
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT 3 -p tcp --dport 80 -j ACCEPT
“ACCEPT all HTTP(tcp) traffic which is going to a destination port 80 where
-p is protocol,
-j is jump and
--dport is destination port and
-A is append.
The second rule above looks almost exactly like the first rule, the only difference here is that the second rule specifies the location the rule should be added in the rule chain. This is important especially when you want your rules to be matched sequentially.
So far, we have seen how to accept traffic to a particular port. While this is great, it’s also important that we set rules to drop unwanted traffic.
sudo iptables -A INPUT -p tcp --dport 443 -j DROP
The rule above says drop every HTTPS traffic hitting our servers. If you pay attention closely, the rules for accepting and dropping traffic closely resembles themselves, the only exception here is that while accepting traffic uses ACCEPT, dropping traffic uses DROP.
While DROP works quite well, in most cases, it helps to give feedback to the user on what’s happening. REJECT on the other hands drops the traffic and also provide useful feedback. To set up a reject rule, we run
sudo iptables -A INPUT -p tcp --dport 3306 -j REJECT
When a client tries to access this port, they will get a message saying that connection to port 3306 was refused. This particular rule prevents an external client from connecting to the MySQL database.
Viewing and deleting rules To view existing IPTables rules, we will run
sudo iptables -L -n or
sudo iptables -L -v where
-v means verbose.
Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination
While setting up rules could be all fun and great, there comes a time where you need to delete an existing rule; either because you don’t need the said rule again or it was configured wrongly. There are two ways to deleting a rule:
sudo iptables -D INPUT 3
Delete the 3rd rule from the input chain. The numbering here isn’t 0 based, but it starts from 1.
sudo iptables -D INPUT -P tcp --dport 3306 -J ACCEPT
Delete the exact same rule by its parameters.
While the two methods achieve a common goal– deleting a rule–it’s important to pay attention to the difference. Method 1 deletes just about any rule that’s on the third chain. In a case where the index does not exist, an error message is returned. Method 2 is a lot more specific, albeit verbose. it targets only a particular rule and the risk of deleting another rule by mistake is minimal.
Automating IPTables with Ansible When it comes to configuration management, ability to build systems in an idempotent and a repeatable fashion cannot be overemphasised.
Ansible is one of the few tools out there that simplifies configuration management, orchestration and deployment. It allows you to build and configure servers in a predictable manner. After taking the time to learn the basis of firewalls via IPtables, we will attempt to automate the entire process.
Let’s create an Ansible playbook to automate our IPtables configuration. In this playbook, we are going accept connections to the following port 22(ssh), 80(http), 443(https) and 3306(mysql) and we drop every other request that does not match this rule.
If you’re new to Ansible and configuration management, there’s an excellent primer here - http://docs.ansible.com/
*** - name: Install iptables Persistent apt: name=netfilter-persistent state=present update_cache=true - name: Set Loop Back Rule iptables: chain=INPUT action=append in_interface=lo jump=ACCEPT comment='Accept all loop back traffic' - name: Set Established Connection Rule iptables: chain=INPUT ctstate='ESTABLISHED,RELATED' jump=ACCEPT comment='Let all established connection stay' - name: Set SSH Port 22 SSH Rule iptables: chain=INPUT jump=ACCEPT protocol=tcp destination_port=22 comment='Accept all SSH traffic' - name: Set HTTP Port 80 HTTP Rule iptables: chain=INPUT jump=ACCEPT protocol=tcp destination_port=80 comment='Accept all HTTP traffic' - name: Set HTTP Port 443 SSL Rule iptables: chain=INPUT jump=ACCEPT protocol=tcp destination_port=443 comment='Accept all SSL traffic' - name: Set HTTP Port 3306 SSL Rule iptables: chain=INPUT jump=ACCEPT protocol=tcp destination_port=3306 comment='Accept all MySQL traffic' - name: Drop Any Traffic Without Rule iptables: chain=INPUT jump=DROP comment='Drop traffic for rules that did not match'
This post was originally published on cyberomin.github.io