Linux iptables ============================================================================ Iptables is a linux firewall. See `iptables(8)` and `iptables-extensions(8)`. Iptables uses the Netfilter framework. The Netfilter framework provides an interface to the stages of the Linux kernel's networking stack. Netfilter exposes each stage to iptables with a **hook**. Iptables pre-defines five **chains**, each chain corresponding to one of the hooks: - `PREROUTING` (packets first hit PREROUTING before any routing decision) - `INPUT` (packets destined for the local system hit INPUT) - `OUTPUT` (packets that originate from the local system hit OUTPUT) - `FORWARD` (packets _not_ destined for the local system hit FORWARD) - `POSTROUTING` (packets leaving the systems hit POSTROUTING after the routing decision) This diagram represents packet flow through the hooks: ``` Local process ^ | .-----------. .-----------. | | | Routing | | |---> INPUT / \---> | Decision |---> OUTPUT \ PREROUTING --->| Routing | .-----------. \ | Decision | --> POSTROUTING | | / | |-------------> FORWARD -------------------------- .-----------. ``` In addition to the built-in chains, users may define custom chains. **Rules** attach to chains. A chain holds a list of rules to test packets against. Each rule specifies a criteria and a **target**. A target can be a verdict like `ACCEPT` or `DROP`, or one of the special targets described in `iptables-extensions(8)` like `CT` or `LOG`. Iptables tests a packet against each rule in a chain, from top to bottom, until a rule matches with a final verdict. Note that one or more rules with non-final targets might match the packet before it hits a rule with a final verdict. A rule match may cause a "jump" to another chain, for example. Iptables is a first-match-wins firewall (unlike PF where the last matching rule applies). Evaluation of rules ends once a packet matches a rule with a target like `ACCEPT` or `DROP`. The default policy applies if the packet doesn't match any earlier rule. Tables group rules according to the type of decisions they make. E.g., a rule that deals with network address translation goes in the `nat` table. Each tables may contain several built-in or user-defined chains. A chain may be included in multiple tables. Not every table has a chain for every hook. Systems often predefined these five tables, depending on kernel configuration and loaded modules: * `filter` is the default table. It includes the `INPUT`, `FORWARD`, and `OUPUT` chains. * `nat` for NATing * `mangle` for specialized packet alteration * `raw` for packet marking and connection tracking * `security` for MAC (mandatory access control). Used by modules like SELinux. When dealing with an individual box, rather than a firewall or router, most rules fall into the `filter` table. Basic Commands ---------------------------------------------------------------------------- ``` # iptables -t nat -vL ``` Where a chain is not specified, the `filter` chain is generally shown by default. To see all chains, run `iptables-save`. Where iptables mentions "in" or "in-interface", it means the interface on which a packet was received. Where iptables mentions "out" or "out-interface", it means the interface from which a packet will depart. List all chains, or the rules in the named chain: `iptables -L, --list [chain]` Delete all the rules, or all the rules in the named chain: `iptables -F, --flush [chain]` Zero-out counters: `iptables -Z, --zero [chain [rulenum]]` Create chain "chain": `iptables -N, --new-chain chain` Delete all user-defined chains or named chain: `iptables -X, --delete-chain [chain]` Examples ---------------------------------------------------------------------------- `-n` is numeric output, without DNS lookups: `sudo iptables -nvL` Line numbers can be used to delete rules or insert new rules: `sudo iptables -nvL --line-numbers` Delete rule four from INPUT chain: `iptables -D INPUT 4` Change default policy to DROP: `sudo iptables --policy INPUT DROP` Allow return traffic from connection we establish: `sudo iptables -I INPUT 1 -m state --state ESTABLISHED,RELATED -j ACCEPT` Allow incoming HTTPS connections: `sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT` Allow responses for mtr: `sudo iptables -A INPUT -p icmp --icmp-type 11 -m state --state ESTABLISHED,RELATED -j ACCEPT` ALLOW pings: `sudo iptables -A INPUT -p icmp --icmp-type 8 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT` Allow all localhost connections (on interface lo): `sudo iptables -A INPUT -i lo -j ACCEPT` Otherwise, we can open localhost ports one at a time, like: `sudo iptables -A INPUT -p tcp -i lo --dport 631 -j ACCEPT` Allow local connections to CUPS: `sudo iptables -A INPUT -p udp -i lo --dport 631 -j ACCEPT` COMMENTS!! It's easy to comment rules, and the comments appear in `iptables -L` output: ``` sudo iptables -A INPUT -p tcp --dport 8888 -j ACCEPT -m comment --comment "Allow my dumb web app." ``` (Use double-quotes for comments; single-quotes don't work.) Safe Rules Testing ---------------------------------------------------------------------------- Use iptables-apply(8) to test a rule set without risk to accidental lockout: $ sudo iptables-apply -t 90 test_rules.v4 If we fail to respond to the confirmation prompt by the timeout, iptables-apply rolls back to the previous (working) rules. Making Rules Persist ---------------------------------------------------------------------------- ``` # mkdir /etc/iptables # iptables-save > /etc/iptables/rules.v4 # iptables-restore < /etc/iptables/rules.v4 # ip6tables-save > /etc/iptables/rules.v6 # ip6tables-restore < /etc/iptables/rules.v6 # cat << 'EOF' > /etc/network/if-pre-up.d/iptables #!/bin/bash /usr/sbin/iptables-restore < /etc/iptables/rules.v4 /usr/sbin/ip6tables-restore < /etc/iptables/rules.v6 EOF # chmod 0755 /etc/network/if-pre-up.d/iptables # cat << 'EOF' > /etc/iptables/rules.v6 *filter :INPUT DROP [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [700:49000] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT COMMIT EOF ``` Or, instead of the above shell script, install the Debian package "iptables-persistent", which will handle loading any rules found in `/etc/iptables/rules.v4` and `/etc/iptables/rules.v6`. I think the package does basically the same as the above, but it might be more future-proof. Check the validity of the config file: # iptables-restore --test /etc/iptables/rules.v4 Examples: ``` --- dev !80 ~ % cat /etc/iptables/rules.v4 *filter :INPUT DROP [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p udp --dport 60000:61000 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p icmp --icmp-type any -j ACCEPT -A INPUT -p udp --dport 67:68 --sport 67:68 -j ACCEPT COMMIT --- dev !81 ~ % cat /etc/iptables/rules.v6 *filter :INPUT DROP [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [2:144] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p udp --dport 60000:61000 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p ipv6-icmp -j ACCEPT COMMIT ``` State ---------------------------------------------------------------------------- Not sure if there's a better way than this, but view current states with: % sudo cat /proc/net/nf_conntrack The output: - First column: The network layer protocol name (eg. ipv4). - Second column: The network layer protocol number. - Third column: The transmission layer protocol name (eg. tcp). - Fourth column: The transmission layer protocol number. - Fifth column: The seconds until the entry is invalidated. - Sixth column (Not all protocols): The connection state. If available, the `conntrack` utility allows us to manually add and delete state entries (and tail changes in real time). If we want to flush the state table for some reason: % sudo conntrack -F Packet Flow ---------------------------------------------------------------------------- See the diagram at http://www.iptables.info/files/tables_traverse.jpg (from the page http://www.iptables.info/en/structure-of-iptables.html). INPUT, FORWARD, and OUTPUT are separate. A packet only hits one of the three hooks. A packet destined for this box hits INPUT. A packet sourced from this box hits OUTPUT. A packet with a source _and_ destination that are _not_ this box hits FORWARD (i.e. this box routes the packet from an outside address to an outside address). A packet hits each rule on each chain on the appropriate hook until it matches a verdict. So, because the chains on a hook may be grouped into multiple tables, the packet may cross multiple tables. E.g., a packet may well hit the `raw` then `mangle` then `nat` tables, probably followed by the `filter` table. The short and somewhat simplified version: - A packet arrives from the network. - It's evaluated against the raw table PREROUTING chain rules. - It's evaluated against the mangle table PREROUTING chain rules. - It's evaluated against the nat table PREROUTING chain rules. - A "routing decision" happens: the packet either goes to INPUT or FORWARD or OUTPUT. - For FORWARD (generally traffic that uses this host as a router), the packet goes to: - evaluation against the mangle table FORWARD chain rules - evaluation against the filter table FORWARD chain rules - A routing decision. If ACCEPT: - evaluation against the mangle table POSTROUTING chain rules - evaluation against the nat table POSTROUTING chain rules - ...And back out to the network - For INPUT (generally traffic destined to this host), the packet goes to: - evaluation against the mangle table INPUT chain rules - evaluation against the filter table INPUT chain rules - Local process (what? like stuff we actually do with the data? is this the turning point from inbound to outbound traffic?) - A routing decision. If ACCEPT... done? - For OUTPUT (generally traffic originating from this host), the packet goes to: - evaluation against the raw table OUTPUT chain rules - evaluation against the mangle table OUTPUT chain rules - evaluation against the nat table OUTPUT chain rules - evaluation against the filter table OUTPUT chain rules - A routing decision. If ACCEPT: - evaluation against the mangle table POSTROUTING chain rules - evaluation against the nat table POSTROUTING chain rules - ...And back out to the network IPv6 ---------------------------------------------------------------------------- iptables is for IPv4. See 'ip6tables' for IPv6. The syntax for `ip6tables` is _very_ similar to that of `iptables`. ``` # ip6tables --policy INPUT DROP # ip6tables -A INPUT -i lo -j ACCEPT # ip6tables -A INPUT -p ipv6-icmp -j ACCEPT # ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # mkdir -p /etc/iptables # sh -c "ip6tables-save > /etc/iptables/rules.v6" ``` ebtables for ARP ---------------------------------------------------------------------------- `ebtables` works on arp traffic. It's similar to iptables. See `man ebtables`. Connection Tracking ---------------------------------------------------------------------------- Netfilter provides connection tracking capabilities, exposed through the `CT` and `conntrack` iptables extensions. Connection tracking filters packets based on criteria that IP header information alone can not provide. In other words: stateful firewalling. Connection tracking keeps facts about a connection — its source and destination addresses, protocol, ports, timeout, etc. A connection may have one of the following states: - "new" for a valid, just-initiated connection where traffic has thus far only appeared from one direction - "established" for a connection where the firewall sees two-way communication - "related" for an expected connection (see "helpers") - "invalid" for packets that deviate from the behavior expected for any connection in the connection tracking table These states have nothing to do with TCP states; even UPD connection can be stateful in the sense of connection tracking. Connection tracking works primarily at layer 3, although some of the modules operate at higher layers. Connection tracking facilitates some application-layer protocols with hard-to-track properties, like FTP. A connection tracking "helper" has a set of _expectations_ about the properties of connections. The FTP helper expects that, within a given time and from a given source and destination, that a passive FTP connection will open a second high-number port for data transmission. The helper inspects packet contents in order to find the necessary information. The helper is application-aware. In the case of FTP, the helper digs through packet payloads looking for the PORT reply from the server to the client. When its expectations are met, the helper establishes a new state. Helpers exist for IRC, SIP, SNMP, H323, etc. Links ---------------------------------------------------------------------------- - https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html-single/Security_Guide/index.html#sect-Security_Guide-Firewalls-Using_IPTables - https://wiki.debian.org/DebianFirewall - https://wiki.debian.org/iptables - http://www.cyberciti.biz/tips/linux-iptables-examples.html - https://wiki.archlinux.org/index.php/Iptables - https://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and-netfilter-architecture Thu Oct 26 12:34:04 EDT 2017