In this article, we will highlight the difference between stateless and stateful traffic filtering. Moreover, we’ll delve into various traffic filtering approaches that are stateless in nature but try to emulate stateful: ACLs, Reflexive ACLs, Cisco ACI contracts. Additionally, we’ll also explain how traffic filtering works in Linux.
Traffic filtering: stateless and stateful
Traffic filtering can be done by different devices: switches, routers, hosts, but of course the first device type that comes to mind is a firewall. The first firewall was invented by Digital Equipment Corporation (DEC) in 1987 and worked as a simple packet filter. Packet filter is a synonym for a stateless firewall; that means that a decision is made for every packet individually without considering any context.
Stateless traffic filtering
From the early 1990s, different companies worked on a second generation of firewalls that could understand the state of bidirectional communication and recognize if a packet is a part of an already established session. Thus only the first packet that initiates a connection is checked by ACL and if ACL permits it then session is considered legitimate and the other packets belonging to the same session are permitted also. We can call this stateful packet filtering. To identify that a packet belongs to a particular stored session, 5-tuple or 6-tuple matching is used (the last parameter ingress interface is optional). Those tuples are:
- Source IP.
- Destination IP.
- Protocol (TCP, UDP, etc.).
- Source port.
- Destination port.
- Ingress interface (optional).
Together with the tuples, each session record (or as it is often called, session metadata) contains a session timeout. This is a countdown timer; when it reaches zero then the session record is deleted from the session table and in such a scenario even if a packet belonging to that session arrives, the ACL has to verify it. Each packet that matches the session tuples resets this timer to its initial value. That’s why it’s very important to set timeout parameters wisely to control the uncontrolled growth of the session table.
Stateful traffic filtering
Together with the idea of ‘state’, the second generation of (stateful) firewalls introduced a very basic understanding of simple protocols such as FTP due to analyzing the application layer (FTP is a specific protocol that by default uses port TCP/21 for initial connection but then opens another port TCP/20 for data transfer). When the number of protocols analyzed on the application layer increased and firewalls could manage intrusion prevention and content analysis, we got the third generation of firewalls called next-generation firewalls, or NGFW. Nowadays all firewalls are stateful.
The main advantage of stateful filtering is a higher security level due to the ability to track the whole bidirectional connection and all packet parameters inside it (source and destination addresses and ports, TCP sequence numbers, etc.) At the same time, stateful filtering simplifies writing ACLs: we can consider only the initial connection packets and not worry about return traffic. That’s very important because usually the initial connection is made to one of the well-known ports such as TCP/22 (SSH), TCP/443 (HTTPS), etc. The source port of the connection technically can be any port and is chosen by software on the client side; but according to RFC 6506, the source port should be randomly chosen from the range of so-called ephemeral ports (49152 to 65535). The whole range of ports from 0 to 65535 are divided by the Internet Assigned Numbers Authority (IANA) into three main categories:
- 1 - 2023, well-known ports.
- 1024 - 49151, registered ports.
- 49152 - 65535, ephemeral ports.
That random source port makes precise manual writing of a reverse ACL rule for return traffic impossible. Or we have to define the whole range of ephemeral ports (or even any port). The main disadvantage of stateful filtering is a significant amount of memory to store states of hundreds of thousand or even millions of open sessions. Multilayer switches that provide us with stateless filtering use special type of memory called TCAM to store ACL rules and check traffic against them. TCAM is an extremely fast but very expensive type of memory and even in high-end network devices its amount is limited (thousands of bytes). Obviously we cannot use it to store session states in stateful firewalls and have to use traditional RAM (small stateful firewalls have several Gigabytes of RAM, high-end ones have several hundreds Gigabytes of RAM). Searching among thousands of records in RAM is much more time consuming than going through tens of rules in a special, very fast TCAM memory in the case of stateless traffic filtering. Leading firewall vendors invent different techniques to accelerate such searches, but it still takes much more time than simple stateless filtering. Also, stateful packet filters are vulnerable to attacks that aim to exhaust resources by overwhelming the state table with new records.
And what about stateless? Are simple packet filters still used today? Yes, they are. Stateless packet filtering is much simpler, doesn’t require system resources such as RAM, and can be easily implemented in hardware. That’s why stateless traffic filtering can be done at very high speed, usually at the speed of the interface and is most often used in switches. Such an approach is very practical; especially in data centers when we have to use an NGFW to inspect traffic between segments. Stateless filtering on data center switches can drop all traffic that is obviously not legitimate, thereby reducing possible legitimate traffic that the NGFW should inspect.
The pros and cons for both types of filtering are summarized in the following table:
Stateless packet filtering | Stateful packet filtering |
---|---|
Pros:
|
Pros:
|
Cons:
|
Cons:
|
Stateless that looks like stateful
Returning to the history of networking when stateless filtering began being implemented, the biggest problem was passing return traffic. For example, a significant advantage of the PIX firewall (bought by Cisco Systems and later Cisco ASA was built on its base) over the usual router was the necessity of configuring ACL only on the inside interface (traditionally, a PIX/ASA interface connected to an internal network is called ‘inside’), and return traffic was permitted on the outside interface automatically (traditionally, a PIX/ASA interface connected to an external network such as the Internet is called ‘outside’).
Access Control Lists (ACLs)
To emulate such behavior, at least for TCP traffic on routers, an extended ACL on the outside interface often includes rules like:
permit tcp any any established
Connection initiation:
Established connection:
Connection closing:
This simple configuration set allows initiating TCP connections only from inside the network to the outside, and not vice versa. Of course, this is just the simplest example. In real life, you should use only your public IP subnet as a destination. But you get the idea.
Reflexive ACL
The next approach to emulate stateful behavior without keeping a state table was reflexive ACL, introduced by Cisco Systems. This works more intelligently than just analyzing the ACK flag. A reflexive access list is triggered when a new IP upper-layer session (such as TCP or UDP) is initiated from inside your network, with a packet traveling to the external network. When triggered, the reflexive access list generates a new, temporary entry. This entry will permit traffic to enter your network if it is returned traffic.
The rules of building this temporary entry are pretty straightforward:
- The entry is always a permit entry.
- The entry specifies the same protocol as the original outbound packet.
- The entry specifies the same source and destination addresses as the original outbound packet, except the addresses are swapped.
- The entry specifies the same source and destination port numbers as the original outbound packet, except the port numbers are swapped.
This entry characteristic applies only for TCP and UDP packets. Other protocols, such as ICMP and IGMP, do not have port numbers, and other criteria are specified. For example, for ICMP, type numbers are used instead. Inbound traffic will be evaluated against the entry until the entry expires. If an inbound packet matches the entry, the inbound packet will be forwarded into your network. The entry will expire after the last packet of the session passes through the interface. If no packets belonging to the session are detected for a configurable length of time (the timeout period), the entry will expire.
A configuration example (from the official Cisco configuration guide ):
interface Serial 1
description Access to the Internet via this interface
ip access-group inboundfilters in
ip access-group outboundfilters out
!
ip reflexive-list timeout 120
!
ip access-list extended outboundfilters
permit tcp any any reflect tcptraffic
!
ip access-list extended inboundfilters
permit eigrp any any
deny icmp any any
evaluate tcptraffic
show access-list output before outbound session was initiated:
Extended IP access list inboundfilters
permit eigrp any any
deny icmp any any
evaluate tcptraffic
Extended IP access list outboundfilters
permit tcp any any reflect tcptraffic
show access-list output after outbound session was initiated:
Extended IP access list inboundfilters
permit eigrp any any
deny icmp any any
evaluate tcptraffic
Extended IP access list outboundfilters
permit tcp any any reflect tcptraffic
Reflexive IP access list tcptraffic
permit tcp host 172.19.99.67 eq telnet host 192.168.60.185 eq 11005 (5 matches) (time left 115 seconds)
We can consider this approach as really being stateful filtering in spite of the fact that no state table is used, but ACL entries do the same job.
Both approaches are still used by Cisco Systems in its flagship data center solution Cisco ACI for traffic filtering. By the way, it's a good example of the value of understanding fundamental technologies because often new shiny features are just decorated versions of well-known ones.
Cisco ACI contracts
For traffic filtering in ACI, Cisco introduced a new concept: contracts. Roughly speaking, contracts are ACLs without IP addresses that are used to filter traffic between end-points (that are grouped into EPGs - end-point groups). As described previously, we can use the simplest approach by checking the ACK flag in the TCP packet header to classify a connection as established (in ACI the more attractive word “stateful” is used):
Also, in configuring contracts we can use a feature that is similar to a reflexive ACL but with one important difference: a reflexive ACL is formed dynamically but a Cisco ACI contract is purely static. This means that the reflected rules for return traffic are formed at the same moment as the direct rules are configured. To form such reflected rules, two options should be turned on: Apply Both Directions and Reverse Filter Ports:
In contrast to a really dynamic reflexive ACL, we cannot configure the dynamic source port of the user's connection and have to use the port Unknown, that means Any.
As you can see, Cisco ACI doesn’t provide you with real stateful traffic filtering, so if you need that you should use an external firewall (hardware or virtual).
Traffic filtering in Linux
Finally, let’s briefly look at how traffic filtering works in Linux. In Linux, traffic filtering is done by the kernel according to rules that are managed by a well-known tool named iptables. Does Linux support stateful traffic filtering? Yes, since 2002 when the module conntrack was initially introduced in Linux kernel 2.4.20.
Module conntrack works according to its name: it tracks all network connections and maintains a state table which can be displayed by the command:
conntrack -L
After loading the module conntrack, you may use the following connection state parameters in your iptables rules:
- NEW - a packet requesting a new connection, only the SYN flag is set and no ACK flag.
- ESTABLISHED - a packet that is part of an existing connection; the ACK flag is set.
- RELATED - a packet that is requesting a new connection but is part of an existing connection (FTP is a good example when the initial connection is established using port TCP/21, but data is transferred to a different port TCP/20).
- INVALID - a packet that is not part of any connections in the connection tracking table.
iptables command to configure a rule that allows forwarding a packet of an already established connection:
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables command to configure a rule that checks a new connection and allows it if it is SSH:
iptables -A FORWARD -p tcp --dport 22 -m state --state NEW -j ACCEPT
Summary
In this article, we have briefly described the different types of traffic filtering. As usual, choosing the right one depends on the equipment you use and the problem you are trying to solve.