📜 ⬆️ ⬇️

Configuring iptables with ferm

Ferm is a low-level add-on over iptables, which allows you to organize some kind of cycles according to the iptables parameter lists. This turns out to be especially useful when setting up complex firewall rules, to write which using only iptables, you have to repeat to insanity -t filter -A INPUT -p tcp --state NEW ..., then do the same for -p udp, who swam - knows.

Ferm is wonderful because, while retaining all the flexibility of iptables, it allows you to achieve the same effects with less effort. So, for example, to allow new connections to the ports ftp, ssh and http and to prohibit everything else (except the connected ones), you can write the following config:
chain INPUT {
policy DROP;
mod state state (RELATED ESTABLISHED) ACCEPT;
proto tcp dport (http ftp ssh) ACCEPT;
}


Surprisingly, the search gives on request ferm only one article, which has nothing to do with ferm itself. Whether everyone already knows everything and is obvious to everyone, then vice versa. Based on the latter, I decided to write this topic.


')

Why is it necessary?


For simple cases - no need at all. But here I have, for example, a software router with two uplinks. The firewall configuration consists of 102 rules. Many of them are repeated with a difference of one parameter. If, God forbid, I want to change something in it - pain in my eyes is waiting for me and at least 20 minutes trying to remember what, where and how. Agree, unpleasant.

Ferm in this case saves not only a more readable, but also somewhat more compact syntax. For example, on the same server, ferm.conf (minus comments and blank lines), it is 84 lines, while configuring ip6tables. Each individual point is shorter. 8960 characters iptables vs 2998 characters ferm.

Considering that when using ferm, there are practically no restrictions imposed on iptables capabilities, the gain is obvious.

Among other things, ferm offers quite advanced possibilities for writing script rules, incl. call external programs and conditional statements. But this is a bit beyond the topic.

How it works?


Ferm is, if you look at the root, a perl script that converts the ferm-config format into iptables calls (or iptables-save / restore format). Accordingly, it works very simply: it reads the config in predefined agreements and calls iptables with the appropriate parameters. In general, no particular magic is present.

Config format (in brief)

In general, the config is a listing of lists in a form slightly reminiscent of C. The instruction separator is a semicolon. Nested lists are organized using curly braces. Simple listing - round. Not clear yet? Consider an example.

Let's say we have an iptables rule
iptables --protocol tcp -j ACCEPT
In ferm it will be broadcast as
protocol tcp ACCEPT;
Line breaks are not important here, only a semicolon is important.

The table and chain in this case is the default (-t filter -A INPUT).

Tables and chains are defined using the table and chain keywords. For example,
table nat chain PREROUTING protocol tcp dport 12345 DNAT to 1.2.3.4;

In general, a rule consists of a place (table, chain), the rule itself (protocol tcp, dport 12345) and an action (DNAT to 1.2.3.4). The rule itself is subject to the same restrictions as using clean iptables. Here, table, chain, protocol, dport and DNAT are keywords. What comes after them is the parameters.

Now add some magic. As parameters for keywords, you can specify not only the actual values, but also lists of values ​​(either functions or variables, but this again goes beyond the topic):
table nat chain PREROUTING protocol (tcp udp) dport (12345 54321) DNAT to 1.2.3.4;

And now a little more magic - since not everything can be achieved with parameter lists, you can define a list of keywords:
table nat chain PREROUTING {protocol tcp dport 12345 DNAT to 1.2.3.4; protocol udp dport 54321 DNAT to 1.2.3.4; }

Where to begin?


If I managed to interest you, then the purpose of the topic is fulfilled. You can start from the project site: ferm.foo-projects.org
In Debian, Gentoo and Fedora, ferm comes from repositories.

It is worth reading man ferm, it is very detailed, which is an undoubted advantage.

It is worth looking at examples (for me they went to / usr / share / doc / ferm - * / examples, it could be different for you)

Among other things, there are two more things worth knowing about: importing an existing configuration and command line parameters.

Import

ferm comes with the import-ferm utility, which takes iptables-save output and writes its output in ferm format. If this utility submits something to the standard input, then it interprets this something as iptables-save output, and will not cause anything. If you do not, then it will itself cause iptables-save.

On the standard output we get the ferm-config, which later can be downloaded back. In general, everything is very friendly.

Command line parameters

Which can be very useful.
--noexec
Does not cause iptables. Makes sense with --lines
--lines
Shows the generated iptables config (and executes it! To just see, use with --noexec)
--interactive
Applies config and asks for user input. If there is no input within 30 seconds, it returns the old settings. VERY helpful when editing the rules on a remote machine at three in the morning :)
--fast / --slow
The first includes the operation mode via iptables-restore, the second - the operation mode via the iptables call. Since version 2.0, the default is fast, respectively, to - slow. There are some reservations about escaping characters in iptables-restore, so in rare cases - slow can be more stable. --slow --lines will output the line immediately before the call, which is extremely convenient for debugging.

Well, the required parameter is the path to the config file.

The rest are described in the manual.

PS



If the topic is interesting, I can delve further into the format of the ferm config. However, it must be borne in mind that this will be largely a free translation / retelling of man ferm and examples.

Source: https://habr.com/ru/post/127184/


All Articles