"Iptables " is a command line utility that is the standard management interface of the Netfilter firewall for Linux kernels. It can be used to create and modify rules that control filtering and redirection of packets. Iptables requires superuser (root)* privileges.

The key concepts of iptables are:

Rules - consists of a criterion, an action, and a counter. If a packet meets the criterion, the action is applied to it and it is counted by the counter. There can be no criterion - then "all packets" criterion is implicitly assumed. You don't have to specify an action, either - if there is no action, the rule will only act as a counter. The rules for each chain are triggered in order, so the order is important.

  • Criterion is a logical expression which analyzes the properties of a packet and/or connection, and determines whether the given packet is covered by the current rule. Criteria are joined by a logical "AND".

  • Action - A description of the action to be performed on a packet and/or connection if they are matched by this rule. The actions are described in more detail below.

  • Counter - A component of a rule which counts the number of packets matching the criteria of this rule. It also counts the total volume of such packets in bytes.

A Chain** is an ordered sequence of rules. Chains can be divided into user chains and basic chains.

  • A basic chain is a chain created by default during table initialization. Every packet, depending on whether it is destined to the host itself, generated by it or is a transit packet, has to go through a set of base chains of different tables. Furthermore, the base chain differs from the user chain in having a "default policy". This action is applied to packets that have not been processed by other rules in this chain or in chains called from it. Base chain names are always written in upper case (PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING).

  • A user-defined chain is a chain created by the user. It may only be used within its own table. It is recommended not to use uppercase names for such chains to avoid confusion with basic chains and built-in actions.

Table - a set of base and user chains united by a common functional purpose. The names of tables (as well as criterion modules) are written in lower case, as in principle they cannot conflict with the names of user chains. When calling the iptables command, the table is specified in the format -t table_name. If there is no explicit indication, filter table is used.

Restriction of number of connections

To protect against brute force, you can limit the number of connections on port 22 from one ip address to a few times a minute, then block attempts to connect for that ip.

## Creating a chain of sshguard rules
# Max 2 new requests per minute per ip
/sbin/iptables -N sshguard
# Include log at will
#/sbin/iptables -A sshguard -m state --state NEW -m recent --name SSH --rcheck --seconds 60 --hitcount 2 -j LOG --log-prefix "SSH-shield: "
/sbin/iptables -A sshguard -m state --state NEW -m recent --name SSH --update --seconds 60 --hitcount 2 -j DROP
/sbin/iptables -A sshguard -m state --state NEW -m recent --name SSH --set -j ACCEPT
/sbin/iptables -A sshguard -j ACCEPT

## Use sshguard chain for ssh traffic
/sbin/iptables -A INPUT -p tcp --dport 22 -j sshguard

recent is a kernel module (Core Netfilter Configuration) that allows you to create dynamic IP address lists. The module supports a number of options

  • --name name - name of the list the command works with. The default name for the list is DEFAULT

  • --rcheck - the option will check if the address of the sender of the packet is present in the list If the address is absent in the list then false is returned.

  • --update - the option will check if the sender address of the packet is present in the list. If the address is present, the corresponding entry will be updated. If there is no address in the list it returns false.

  • --hitcount hits - the counter returns true if the address is present in the list, when the number of packets received from the address is greater than or equal to the specified value. Used in conjunction with rcheck or update

  • --seconds seconds - specifies the period (from the moment the address is entered into the list) during which the address can be in the list

  • --set - used to add the sender address to the list. If this address is already in the list, the entry will be updated

  • -remove - removes the address from the list. If the address is not found it will return false.

Using update instead of rcheck forces you to wait an interval before trying to connect again. Failure to wait the interval will cause you to have to wait 60 seconds from the last connection attempt again.

Dynamic open/close ssh port

A small rule for iptables to help you to not keep ports open unnecessarily.

Example for SSH access, but as you can imagine you can use it any way you want.

In order to open shell access, you need to first bang on 1500 port:
telnet for example:

telnet myserver 1500  

Or via a browser:  

Accordingly, if you knock on 1499 - the port is closed

iptables -N sshguard  
# If the address is in the list, then the connection is allowed
iptables -A sshguard -m state --state NEW -m recent --rcheck --name SSH -j ACCEPT  
# Allow packets for already established connections
iptables -A sshguard -m state --state ESTABLISHED,RELATED -j ACCEPT  
iptables -A sshguard -j DROP  

# Adds the address to the list
#iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 1500 -j LOG --log-prefix "SSH-open: "
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 1500 -m recent --name SSH --set -j DROP  
# Deletes the address from the list
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 1499 -m recent --name SSH --remove -j DROP  

# use sshguard chain for ssh traffic
iptables -A INPUT -p tcp --dport 22 -j sshguard  

The port is only opened for the ip from which it was opened

Open ssh port for a specified time

Another example demonstrates a way to open an ssh port for a specific ip at a given time.

## determine the chain for SSH traffic
iptables -N sshguard  
iptables -F sshguard  
# Allow connection if ip is listed and if connection was last made within 108000 seconds (30 hours) 
iptables -A sshguard -m state --state NEW -m recent --update --seconds 108000 --name SSH -j ACCEPT  
# Allow packets for already installed connections
iptables -A sshguard -m state --state ESTABLISHED,RELATED -j ACCEPT  
# block if not on the list
iptables -A sshguard -j DROP  

## Open SSH
iptables -A INPUT -m state --state NEW -p tcp --dport 222 -m recent -name SSH --set  
## Filtering ssh traffic through the sshguard chain
iptables -A INPUT -p tcp --dport 22 -j sshguard  

Now to get ssh access you first need to knock on port 222, for example like this:

ssh user@server.name -p 222  

After that your ip access to port 22 will be allowed for the specified time and every new connection to ssh will lengthen that time. If you don't want to prolong the time then replace --update --seconds 108000 with --rcheck.

The port opens only for the ip from which it was opened

It is also possible to know which ip addresses are allowed to ssh:

cat /proc/net/ipt_recent/SSH  
Updated Dec. 14, 2018