[LINUX] How to use iptables

Introduction

iptables is a firewall built into the Linux kernel. It is used to limit or transfer communication on that host. Although IPv4 is assumed here, IPv6 also has ip6tables that can be used in almost the same way.

Setting Example

A detailed explanation will be given later with an example of the iptables configuration file.

/etc/iptables/iptables.rules


#As a general rule, all input and transfer are prohibited
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

#All connections from loopback are allowed
-A INPUT -i lo -j ACCEPT

#Allows pings to be received, but limits the frequency to about once per second per client
-A INPUT -p icmp --icmp-type echo-request -m hashlimit --hashlimit-name t_echo --hashlimit-mode srcip --hashlimit-upto 1/s --hashlimit-burst 5 --hashlimit-htable-expire 10000 -j ACCEPT

#Already established communication is allowed regardless of port number
-A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT

#Allow SSH connection but limit the frequency to about once per minute per client
-A INPUT -m state --state NEW -m tcp -p tcp --syn --dport 22 -m hashlimit --hashlimit-name t_sshd --hashlimit-mode srcip --hashlimit-upto 1/m --hashlimit-burst 5 --hashlimit-htable-expire 600000 -j ACCEPT

#Allow response reception from DNS server
-A INPUT -p udp --sport 53 -j ACCEPT

COMMIT

Commentary

policy

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

As a general rule, all packet reception and forwarding are prohibited, and transmission is allowed. Of course, I don't want to receive packets at all, so I'll set an exception for this policy after this.

Loopback

#All connections from loopback are allowed
-A INPUT -i lo -j ACCEPT

Linux may use sockets for interprocess communication as well as for communication with other hosts. Communication closed to such a host is called loopback. If you limit the loopback communication, there is a high possibility that various programs will not operate normally, so we allow it entirely.

Ping

#Allows pings to be received, but limits the frequency to about once per second per client
-A INPUT -p icmp --icmp-type echo-request -m hashlimit --hashlimit-name t_echo --hashlimit-mode srcip --hashlimit-upto 1/s --hashlimit-burst 5 --hashlimit-htable-expire 10000 -j ACCEPT

Allows the host to respond to pings. However, the frequency is limited as a countermeasure against ICMP Flood (Ping Flood), which puts a load on the system by sending a large number of Pings. Use the hashlimit module to limit the frequency with which packets are received (or forwarded or sent).

--hashlimit-name is the name of the hash table. Since it is necessary to record the packet reception history etc. in order to use this module, set the file name of the save destination so that it does not overlap with other rules.

--hashlimit-mode specifies in what units the frequency of receiving packets is limited. Since srcip is set here, the reception of packets is restricted for each source IP address. There are other flags such as dstip`` srcport dstport. You can also combine multiple flags. If you omit this option, the system as a whole limits the frequency with which packets are received, regardless of the source or destination.

--hashlimit-upto and --hashlimit-burst specifically set how often packets are allowed to be received. To understand the meaning of these two settings, it is helpful to compare the frequency with which packets are allowed to be received to the capacity of a bucket. Imagine that you need to remove a liter of water from a bucket to receive a single packet. The system boots when the bucket is full, but when there is not enough water it will not be able to receive packets. --hashlimit-upto 1 / s means that you are pouring 1 liter of water into the bucket per second. However, --hashlimit-burst 5 means that the bucket has only 5 liters of capacity. This means that no matter how short the packet arrives, you can receive it up to 5 times without any problems, but you have to wait until the bucket is filled with water again in order to receive more packets in a row.

--hashlimit-htable-expire specifies the expiration date of records in the hash table in milliseconds. If you do not set a value larger than $ \ frac {hashlimit-burst} {hashlimit-upto} $, the reception frequency will not be limited as expected. Here, we set it to 10000 milliseconds, which is twice the calculation result (5 seconds) with a margin.

TCP

#Already established communication is allowed regardless of port number
-A INPUT -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT

After establishing a connection with TCP once, allow any packet to be received on that port. The SSH server settings described below only allow connections to the server, but this setting also allows communication after a successful connection to pass through the firewall.

Also, I'm allowed to connect to the server as a client with the : OUTPUT ACCEPT [0: 0] mentioned above, but it's this setting that allows me to receive packets after a successful connection.

SSH server

#Allow SSH connection but limit the frequency to about once per minute per client
-A INPUT -m state --state NEW -m tcp -p tcp --syn --dport 22 -m hashlimit --hashlimit-name t_sshd --hashlimit-mode srcip --hashlimit-upto 1/m --hashlimit-burst 5 --hashlimit-htable-expire 600000 -j ACCEPT

Allows connections to TCP port 22. Like Ping, it uses the hashlimit module to limit the frequency of connections. You can apply it for other purposes by changing --dport 22 to another port number. For example, allow communication on port 80 for HTTP and port 443 for HTTPS. However, for HTTP and HTTPS, the hashlimit limit should be set a little looser.

DNS client

#Allow response reception from DNS server
-A INPUT -p udp --sport 53 -j ACCEPT

DNS uses TCP / UDP or both. For TCP, : OUTPUT ACCEPT [0: 0] -A INPUT -p tcp -m state --state ESTABLISHED, RELATED -j ACCEPT is already allowed. There is no concept of connectivity for UDP, so you need to explicitly allow packets sent from port 53 to be received.

Reflection of settings

Please restart iptables. If you are using systemd such as Arch Linux:

# systemctl restart iptables

Recommended Posts

How to use iptables
How to use Python-shell
How to use tf.data
How to use virtualenv
How to use Seaboan
How to use shogun
How to use Pandas 2
How to use Virtualenv
How to use numpy.vectorize
How to use pytest_report_header
How to use partial
How to use Bio.Phylo
How to use SymPy
How to use x-means
How to use IPython
How to use virtualenv
How to use Matplotlib
How to use numpy
How to use TokyoTechFes2015
How to use venv
How to use dictionary {}
How to use Pyenv
How to use list []
How to use python-kabusapi
How to use OptParse
How to use return
How to use dotenv
How to use pyenv-virtualenv
How to use Go.mod
How to use imutils
How to use import
How to use Qt Designer
How to use search sorted
[gensim] How to use Doc2Vec
python3: How to use bottle (2)
Understand how to use django-filter
How to use the generator
[Python] How to use list 1
How to use FastAPI ③ OpenAPI
How to use Python argparse
How to use IPython Notebook
How to use Pandas Rolling
How to use redis-py Dictionaries
Python: How to use pydub
[Python] How to use checkio
[Go] How to use "... (3 periods)"
How to use Django's GeoIp2
[Python] How to use input ()
How to use the decorator
[Introduction] How to use open3d
How to use Python lambda
How to use Jupyter Notebook
[Python] How to use virtualenv
python3: How to use bottle (3)
python3: How to use bottle
How to use Google Colaboratory
How to use Python bytes
How to use cron (personal memo)
Python: How to use async with
How to use the optparse module
How to use SWIG from waf