This shows you the differences between two versions of the page.
isc:labs:kernel:tasks:03 [2021/11/26 18:47] radu.mantu created |
— (current) | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | === 03. [??p] Extending the Linux firewall === | ||
- | <note tip> | ||
- | //Pro tip//: since you may want to consult the **man** pages at some point, add this to your //.bashrc// or //.zshrc//: | ||
- | <code bash> | ||
- | # color schemes for man pages | ||
- | man() { | ||
- | LESS_TERMCAP_mb=$'\e[1;34m' \ | ||
- | LESS_TERMCAP_md=$'\e[1;32m' \ | ||
- | LESS_TERMCAP_so=$'\e[1;33m' \ | ||
- | LESS_TERMCAP_us=$'\e[1;4;31m' \ | ||
- | LESS_TERMCAP_me=$'\e[0m' \ | ||
- | LESS_TERMCAP_se=$'\e[0m' \ | ||
- | LESS_TERMCAP_ue=$'\e[0m' \ | ||
- | command man "$@" | ||
- | } | ||
- | </code> | ||
- | |||
- | Now, source your file to load the new command. **man** will color certain keywords appropriately. | ||
- | |||
- | <code bash> | ||
- | # update your shell's environment with the man() wrapper | ||
- | [student@host]$ source ~/.bashrc | ||
- | |||
- | # check out the manual page for iptables | ||
- | [student@host]$ man iptables | ||
- | </code> | ||
- | </note> | ||
- | |||
- | **iptables** is a configuration tool for the kernel packet filter. | ||
- | |||
- | The system as a whole provides many functionalities that are grouped by **tables**: //filter, nat, mangle, raw, security//. If you want to alter a packet header, you place a rule in the //mangle// table. If you want to mask the private IP address of an internal host with the external IP address of the default gateway, you place a rule in the //nat// table. Depending on the table you choose, you will gain or lose access to some chains. If not specified, the default is the //filter// table. | ||
- | |||
- | **Chains** are basically lists of rules. The five built-in chains are //PREROUTING, FORWARD, POSTROUTING, INPUT, OUTPUT//. Each of these corresponds to certain locations in the network stack where packets trigger **Netfilter hooks** ([[https://elixir.bootlin.com/linux/latest/source/net/ipv4/ip_input.c#L540|here]] is the //PREROUTING// kernel hook as an example -- not that hard to add one, right?) For a selected chain, the order in which the rules are evaluated is determined primarily by the priority of their tables and secondarily by the user's discretionary arrangement (i.e.: order in which rules are inserted). | ||
- | |||
- | {{ :isc:labs:kernel:tasks:iptables_path.png?800 |}} | ||
- | |||
- | A **rule** consists of two entities: a sequence of match criteria and a jump target. | ||
- | |||
- | The **jump target** represents an action to be taken. You are most likely familiar with the built-in actions such as //ACCEPT// or //DROP//. These actions decide the ultimate fate of the packet and are final (i.e.: rule iteration stops when these are invoked). However, there are also extended actions (see ''man iptables-extensions(8)'') that are not terminal verdicts and can be used for various tasks such as auditing, forced checksum recalculation or removal of Explicit Congestion Notification (ECN) bits. | ||
- | |||
- | The **match criteria** of every rule are checked to determine if the jump target is applied. The way this is designed is very elegant: every type of feature (e.g.: layer 3 IP address vs layer 4 port) that you can check has a match callback function defined in the kernel. If you want, you can write your own such function in a Linux Kernel Module (LKM) and thus extend the functionality of **iptables** ([[https://inai.de/documents/Netfilter_Modules.pdf|Writing Netfilter Modules]] with code example). However, you will need to implement a userspace shared library counterpart. When you start an **iptables** process, it searches in ///usr/lib/xtables/ // and automatically loads certain shared libraries (note: this path can be overwritten or extended using the //XTABLES_LIBDIR// environment variable). Each library there must do three things: | ||
- | * define **iptables** flags for the new criteria that you want to include. | ||
- | * define help messages for when ''**iptables** %%--%%help'' is called (its help message is an amalgamation of each library's help snippet). | ||
- | * provide an initialization function for the structure containing the rule parameters; this structure will end up in the kernel's rule chain. | ||
- | So when you want to test the efficiency of the **iptables** rule evaluation process, keep in mind that each rule may imply the invocation of multiple callbacks such as [[https://elixir.bootlin.com/linux/latest/source/net/netfilter/xt_tcpudp.c#L66|this]]. | ||
- | |||
- | == [??p] Task A - Primer / Reminder == | ||
- | |||
- | Before writing our own match module, here's a small task to freshen your memory on how to use **iptables**. | ||
- | |||
- | Write an **iptables** rule according to the following specifications: | ||
- | * **chain:** OUTPUT | ||
- | * **match rule:** TCP packets originating from ephemeral ports bound to a socket created by //root// | ||
- | * **target:** enable kernel logging of matched packets with the //"TCP_LOG: "// prefix | ||
- | |||
- | How to test: | ||
- | <code bash> | ||
- | $ sudo curl www.google.com | ||
- | $ sudo dmesg | ||
- | </code> | ||
- | |||
- | <note tip> | ||
- | |||
- | **multiport**, **owner** modules | ||
- | |||
- | <code bash> | ||
- | $ man 8 iptables-extensions | ||
- | </code> | ||
- | </note> | ||
- | |||
- | <solution -hidden> | ||
- | <code bash> | ||
- | # "--log-prefix" must come after "-j LOG" | ||
- | $ sudo iptables \ | ||
- | -m multiport -m owner \ | ||
- | -I OUTPUT \ | ||
- | -p tcp \ | ||
- | --sports 1024:65535 \ | ||
- | --uid-owner root \ | ||
- | -j LOG \ | ||
- | --log-prefix 'TCP_LOG: ' | ||
- | </code> | ||
- | </solution> |