Netfilter --------- Linux Netfilter firewall is often configured via one of the following tools * iptables/ip6tables — administration tool for IPv4/IPv6 packet filtering and NAT * nft - Administration tool of the nftables framework for packet filtering and classification * firewall-cmd - firewalld command line client Default policy ============== Allowing everything and denying a few ports you don't need and who may be dangerous is not a good idea. For an effective network filtering, it's far better to deny everything by default and allow what is needed. Each server and computer should have an active firewall to filter network traffic. This deny policy should be applied to incoming traffic and routed traffic but also to outgoing traffic. `Lateral movement `_ refers to the techniques that cyber attackers, or threat actors, use to progressively move through a network as they search for the key data and assets that are ultimately the target of their attack campaigns. If each server and computer filter not only the incoming traffic but also the outgoing traffic, attackers will have less ways to move through your servers. TCP MSS ======= The TCP protocol includes a mechanism for both ends of a connection to advertise the `Maximum Segment Size `_ (MSS) to be used by its peer when the connection is created. Each end uses the OPTIONS field in the TCP header to advertise a proposed MSS. If one endpoint does not provide its MSS, then 536 bytes is assumed for IPv4. Small MSS are bad for performance. Technically, the MSS can be lower than 536. Some of the packets generated by `nmap `_ while doing OS fingerprinting are using such values. .. literalinclude:: osscan2.cc :caption: osscan2.cc :name: osscan2-cc :lines: 84-97 :lineno-match: :emphasize-lines: 11 I have chosen to drop packets with a MSS lower than 536. iptables ======== :code:`iptables` and :code:`ip6tables` are used to set up, maintain, and inspect the tables of IPv4 and IPv6 packet filter rules in the Linux kernel. Several different tables may be defined. Each table contains a number of built-in chains and may also contain user-defined chains. On AlmaLinux 9, :code:`iptables-nft` package brings nftables compatibility for :code:`iptables`, :code:`arptables` and :code:`ebtables`. A good policy is to deny everything by default. .. code-block:: shell iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP Remember that filtering the OUTPUT traffic limits lateral movement. .. image:: tables_traverse.jpg :alt: https://www.frozentux.net/iptables-tutorial/images/tables_traverse.jpg To filter anomalous traffic early, instead of doing it in :code:`INPUT` and :code:`FORWARD` from table :code:`filter`, it's possible to do it in :code:`PREROUTING` from table :code:`mangle`. In this example, the external interface is :code:`eth7`. .. code-block:: shell iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP iptables -t mangle -A PREROUTING -p tcp ! --tcp-flags ALL SYN -m conntrack --ctstate NEW,RELATED -j DROP iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN -m tcpmss ! --mss 536:65535 -j DROP iptables -t mangle -A PREROUTING -p tcp --sport 0 -j DROP iptables -t mangle -A PREROUTING -p udp --sport 0 -j DROP iptables -t mangle -A PREROUTING -m set -i eth7 --set blocklist src -j DROP These rules are dropping * :code:`INVALID` packets * :code:`NEW` (or :code:`RELATED`) tcp packets without :code:`SYN` flag. AFAIK, there should be no :code:`SYN` + :code:`URG` and no :code:`SYN` + :code:`PSH`. * tcp packets containing a :code:`SYN` and no :code:`RST` with a MSS lower than 536. * tcp and udp packets with source port 0 * packets from the `blocklist` ipset but only on the external interface. .. code-block:: console # iptables -nvL PREROUTING -t mangle Chain PREROUTING (policy ACCEPT 3655M packets, 9547G bytes) pkts bytes target prot opt in out source destination 986K 48M DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID 48868 6843K DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp flags:!0x3F/0x02 ctstate NEW 7108K 284M DROP tcp -- eth7 * 0.0.0.0/0 0.0.0.0/0 ctstate NEW,RELATED tcpmss match !536:65535 4 192 DROP udp -- eth7 * 0.0.0.0/0 0.0.0.0/0 udp spt:0 6 336 DROP tcp -- eth7 * 0.0.0.0/0 0.0.0.0/0 tcp spt:0 2584 1285K DROP all -- eth7 * 0.0.0.0/0 0.0.0.0/0 match-set blocklist src To prevent mapping of internal network topology, I drop packets with a `Time-to-Live `_ (TTL) lower than 5. Note that dropping INVALID packets, new TCP connexion without SYN and TCP SYN packet without the :code:`MSS` option isn't necessary if its done in the :code:`PREROUTING` rules. .. code-block:: console iptables -A FORWARD -m state --state INVALID -j DROP iptables -A FORWARD -m state --state NEW,RELATED -p tcp ! --tcp-flags ALL SYN -j DROP iptables -A FORWARD -m state --state NEW,RELATED -p tcp ! --tcp-option 2 -j DROP iptables -A FORWARD -i eth7 -m ttl --ttl-lt 5 -m limit --limit 4/s -j LOG --log-prefix "TTL too short " iptables -A FORWARD -i eth7 -m ttl --ttl-lt 5 -j DROP iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT .. code-block:: console # iptables -nvL FORWARD Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination ... 15871 991K LOG all -- eth7 * 0.0.0.0/0 0.0.0.0/0 TTL match TTL < 5 limit: avg 4/sec burst 5 LOG flags 0 level 4 prefix `TTL too short ' 17856 1101K DROP all -- eth7 * 0.0.0.0/0 0.0.0.0/0 TTL match TTL < 5 3529M 9533G ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED Similar rules can be created for INPUT. .. code-block:: console iptables -P INPUT DROP iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -m state --state INVALID -j DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp ! --tcp-flags ALL SYN -m state --state NEW -m limit --limit 4/s -j LOG --log-prefix "TCP INPUT without SYN " iptables -A INPUT -p tcp ! --tcp-flags ALL SYN -m state --state NEW -j DROP ... iptables -A INPUT -m limit --limit 4/s -j LOG --log-prefix "INPUT bad " iptables -A INPUT -j DROP It's good practice to filter outgoing packets from your servers too.