19.3 The Netfilter Architecture of Linux 2.4

   


Linux Version 2.4 divides the packet-filtering functionality into two large blocks: The so-called netfilter hooks offer a comfortable way to catch and manipulate processed IP packets at different positions on their way through the Linux kernel. Building on this background, the iptables module implements three rules lists to filter incoming, forwarded, and outgoing IP packets. These lists correspond roughly to the rules lists used by ipchains. In addition, similar modules are available for other network protocols (e.g., ip6tables for IP Version 6).

19.3.1 Netfilter Hooks in the Linux Kernel

As was mentioned briefly in Section 19.2.2, the netfilter architecture includes a uniform interface, reducing the cost involved to implement new functions. It is called netfilter hook, which means that it provides a hook for packet-filter code. This section discusses the components of this architecture and its implementation in the Linux kernel. Actually, this section supplies brief instructions to facilitate your writing your own netfilter modules.

Netfilter modules can be loaded into the Linux kernel at runtime, so we need hooks in the actual routing code to enable dynamic hooking of functions. An integer identifier is allocated to each of these netfilter hooks. The identifiers of all hooks for each supported protocol are defined in the protocol-specific header file (<linux/netfilter_ipv4.h> or <linux/netfilter_ipv6.h>). The following five hooks are defined for IP Version 4 in <linux/netfilter_ipv4.h>:

  • NF_IP_PRE_ROUTING (0): Incoming packets pass this hook in the ip_rcv() function (see Section 14.2.1) before they are processed by the routing code. Prior to that, only a few simple consistency checks with regard to the version, length, and checksum fields in the IP header are done.

    Meaningful opportunities to use this hook result whenever incoming packets should be caught before they are processed for example, to detect certain types of denial-of-service attacks that operate on poorly built IP packets, or for address-translation mechanisms (NAT), or for accounting functions (counting of incoming packets).

  • NF_IP_LOCAL_IN (1): All incoming packets addressed to the local computer pass this hook in the function ip_local_deliver(). At this point, the iptables module hooks the INPUT rules list into place to filter incoming data packets. This corresponds to the input rules list in ipchains.

  • NF_IP_FORWARD (2): All incoming packets not addressed to the local computer pass this hook in the function ip_forward() that is, packets to be forwarded and leaving the computer over a different network interface.

    This includes any packet the address of which was modified by NAT. At this point, the iptables module hooks the FORWARD rules list into place to filter forwarded data packets. This corresponds to the forward rules list in ipchains.

  • NF_IP_LOCAL_OUT (3): All outgoing packets created in the local computer pass this hook in the function ip_build_and_send_pkt(). At this point, the iptables module hooks the OUTPUT rules list into place to filter outgoing data packets. This corresponds to the output rules list in ipchains.

  • NF_IP_POST_ROUTING (4): This hook in the ip_finish_output() function represents the last chance to access all outgoing (forwarded or locally created) packets before they leave the computer over a network device. Like the NF_IP_PRE_ROUTING hook, this is a good place to integrate accounting functions.

Figure 19-3 shows data packets traveling through different hooks.

Figure 19-3. The packet filtering architecture of Linux 2.4 (netfilter).

graphics/19fig03.gif


NF_HOOK()

include/linux/netfilter.h


Calling the NF_HOOK macro causes the routing code to process the filter functions hooked into a netfilter hook. This macro is defined in <linux/netfilter.h> as follows:

 #define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                     \ (list_empty(&nf_hooks[(pf)][(hook)])                                    \    ? (okfn)(skb)                                                        \    : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn))) 

The following fragment from net/ipv4/ip_output.c (at the end of the ip_build_and_send_pkt() function) serves as an example to see how we can use the NF_HOOK macro:

 /* Send it out. */ return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,                 output_maybe_reroute); 

In this example, rather than calling the function output_maybe_reroute() immediately, the packet-filtering functions registered with the hook NF_IP_LOCAL_OUT are processed first to send an IP packet. The values that filter functions can return are defined in <linux/netfilter.h>. If all functions return the value NF_ACCEPT, then the "okay" function okfn() at this hook (i.e., output_maybe_reroute() in this case) is invoked. If, however one of the filter functions returns NF_DROP, then the packet is dropped, and okfn() is not invoked.

More specifically, the NF_HOOK macro has the following arguments:

  • pf (protocol family): This is the identifier of the protocol family: PF_INET for IP Version 4, PF_INET6 for IP Version 6.

  • hook: This is the hook identifier. All valid identifiers for each protocol family are defined in a header file (e.g., <linux/netfilter_ipv4.h>).

  • skb: This is a pointer to the sk_buff structure with the packet to be handled.

  • indev (input device): This is a pointer to the net_device structure of the network device that received the packet. It is set to NULL in the above example, because the packet is an outgoing packet.

  • outdev (output device): This is a pointer to the net_device structure of the network device that should be used by the packet to leave the local computer. In the above example, the device used has to be determined first by use of the routing table (rt).

  • okfn() (okay function): This function is invoked when all filter functions registered with this hook returned NF_ACCEPT, thereby okaying the packet's transit.

19.3.2 Registering and Unregistering Packet-Filter Functions

The packet-filter functions that are actually hooked into the netfilter hooks are so-called hook functions of the type nf_hookfn. The signature of a hook function is defined in <linux/netfilter.h> as follows:

 typedef unsigned int nf_hookfn(unsigned int hooknum,                                struct sk_buff **skb,                                const struct net_device *in,                                const struct net_device *out,                                int (*okfn) (struct sk_buff *)); 

The parameters (except for the protocol family identifier) correspond exactly to those of the NF_HOOK macro (see Section 19.3.1), and they are passed by this macro to the packet-filter functions. [Russ00d] includes a simple example showing how a packet-filter function is implemented, with detailed explanations.

The return value of a packet-filter function specifies what should happen to the packet. It is of the type unsigned int and can take any of the following values, defined in <linux/netfilter.h>:

  • NF_DROP (0): The active rules list processing is stopped, and the packet is dropped.

  • NF_ACCEPT (1): The packet is passed to the next packet filter function in the rules list. Once the end of the list has been reached, the packet is released by okfn() for further processing.

  • NF_STOLEN (2): The packet filter function withholds the packet for further processing, so that the active rules list processing is stopped. In contrast to NF_DROP, however, the packet does not have to be explicitly dropped.

  • NF_QUEUE (3): The function nf_queue() (net/core/netfilter.c) puts the packet in a queue from which it can be removed and processed (e.g., by a user space program). Subsequently, nf_reinject() has to be invoked to return the packet to the Linux kernel for further processing by netfilter.

  • NF_REPEAT (4): In contrast to NF_ACCEPT, rather than a continuation of processing at the next packet-filter function, the current filter function is invoked again.

nf_register_hook(), nf_unregister_hook()

net/core/netfilter.c


This function registers or unregisters a packet-filter function with the Linux kernel. The parameter passed is a nf_hook_ops structure, which includes all information required.

struct nf_hook_ops

linux/netfilter.h


To register a new packet-filter function with the Linux kernel, we first have to initialize a structure of the type nf_hook_ops with all of the management information required:

 struct nf_hook_ops {             struct list_head list;             /* User fills in from here down. */             nf_hookfn *hook;             int pf;             int hooknum;             /* Hooks are ordered in ascending priority. */             int priority; };

The fields of this structure have the following meaning:

  • list: The nf_hook_ops structures are maintained in a linked list within the Linux kernel.

  • hook(): This is a pointer to the actual packet-filter function of the type nf_hookfn.

  • pf, hooknum: The protocol family identifier (e.g., PF_INET or PF_INET6) and the hook identifier (e.g., NF_IP_INPUT) are used to determine the hook for this packet-filter function.

  • priority: Packet-filter functions within the rules list of a hook are sorted by the priority field in ascending order, so that they will be invoked in this order when a packet transits. Priority values are defined as follows, e.g., in <linux/netfilter_ipv4.h>:

     enum nf_ip_hook_priorities {            NF_IP_PRI_FIRST = INT_MIN,            NF_IP_PRI_CONNTRACK = -200,            NF_IP_PRI_MANGLE = -150,            NF_IP_PRI_NAT_DST = -100,            NF_IP_PRI_FILTER = 0,            NF_IP_PRI_NAT_SRC = 100,            NF_IP_PRI_LAST = INT_MAX, };

19.3.3 Comparing iptables and ipchains

The most important differences between netfilter and the old ipchains architecture are doubtless that the flaws mentioned in Section 19.2.2 were removed: New packet-filter functions can easily be integrated into the Linux kernel by use of the programming interface introduced in Section 19.3.2. In addition, more complex functions, such as the support of transparent proxies or of address-translation mechanisms (NAT), are now implemented as independent modules with clearly defined interfaces. The changes to the existing network code to integrate a new hook for packet-filter functions are limited to one single call of the NF_HOOK macro in the netfilter architecture. (See Section 19.3.1.)

Moreover, the netfilter architecture changed the path different packet streams take across the kernel. In contrast to ipchains, iptables now handles each packet based on exactly one of the three rules lists used: INPUT, FORWARD, or OUTPUT. The routing decision is made early, before the transit through the INPUT or FORWARD hook, so that forwarded packets do not have to traverse all three hooks. (See Figure 19.3.) In ipchains (Figure 19.2), all packets had to traverse the input list before a routing decision was made; given this decision, packets were then redirected to a local process or to the forward list. This modification simplifies the rules-lists handling, because no undesired dependencies between them can occur, and it reduces the processing cost in the kernel, so that packets are handled faster.

And, finally, there was a slight change to the syntax of the iptables command-line tool used to manage rules lists, compared to the older ipchains. Table 19.1 gives an overview of the most important changes. Most options and parameters are identical. However, iptables rules lists use uppercase letters; also, DENY was renamed in DROP, and MASQ replaces the former MASQUERADE.

19.3.4 The iptables Command-line Tool

The ipchains management tool is a direct counterpart of the iptables program used in netfilter. This tool can be used to manipulate the rule sets in different tables and the associated rules lists. We saw in Table 19-1 that the invocation syntax of ipchains and iptables is similar in many aspects, because the netfilter architecture uses some of the same concepts, such as linked rules lists.

One of the most important differences is the name-giving introduction of several filter tables, reflecting the modular structure of the netfilter architecture. This modular structure includes NAT and other packet-manipulating functions, in addition to the pure filter functions. This is considered in the invocation syntax by introducing a new parameter, -t <table>, which expresses the reference of a rule definition to a table associated with a specific module. Accordingly, this changes the basic structure of an invocation to

iptables -t <table> -<operation> <chain> -j <branch destination> <criterion>.

This new form extends iptables, so that users don't have to use different management tools (e.g., ipmasqadm) to address additional functions and protocols.

The following program segment shows a simple configuration for a communication server that can be used by a network with the private address space 192.168.1.0-192.168.1.255 [RMKG + 96] to access the Internet; it obtains a dynamic IP address from the Internet provider:

 #!/bin/bash ## enable IP forwarding echo 1 >/proc/sys/net/ipv4/ip_forward ## insert connection-tracking modules (not needed if built into kernel). if [ ! -e /proc/net/ip_conntrack ] ; then                 insmod ip_tables                 insmod ip_conntrack                 insmod ip_conntrack_ftp                 insmod iptable_nat                 insmod ipt_MASQUERADE                 insmod ipt_LOG fi iptables -F ## clean up before calling new ruleset iptables -A FORWARD -m unclean -j DROP ## enable routing (source and destination) iptables -A FORWARD -s 192.168.1.0/24 -j ACCEPT iptables -A FORWARD -d 192.168.1.0/24 -j ACCEPT ## do NAT for all outbound connections iptables -t nat -A POSTROUTING -d ! 192.168.1.0/24 -j MASQUERADE 

The echo command at the beginning activates the forwarding of IP packets in the Linux kernel.

The if branch following next loads the kernel modules required, unless they were already loaded. ip_tables and ip_conntrack are the basic modules of the netfilter architecture for IP Version 4. The iptable_nat and ipt_MASQUERADE modules enable masquerading (a simple sort of NAT).

When iptables -F is invoked, all existing rules are deleted, to prevent a rule from being loaded twice.

The rule -m unclean -j DROP causes all packets with faulty IP headers (e.g., like those in a teardrop attack) to be dropped.

The next two rules enable access to addresses in any other IP network from the internal network (-s 192.168.1.0/24) and let packets from this network through to internal computers (-d 192.162.1.0/24).

The last rule activates the masquerading process, if the destination computer is not in the internal network.

19.3.5 The Netfilter Standard Modules

With the new netfilter architecture, we now have both the standard functionality and extensions (e.g., NAT) in the form of kernel modules. This section introduces some important netfilter modules:

  • Stateful connection tracking: The ip_conntrack.o module, which includes additional protocol-specific helper modules (e.g., ip_conntrack_ftp.o), allows us to assign specific states to the packets of a TCP connection, where four different states are available:

    • NEW: The connection is currently being established, and no reply packet has yet been received for the first packet of this connection.

    • ESTABLISHED: The packets belong to an existing TCP connection.

    • RELATED: The packets are in relation to an existing connection, but not an integral part of that connection.

    • INVALID: All packets that cannot be classified (packets that cannot be assigned to any named connection and that do not initiate connection establishments) fall into this category.

    In addition, the connection-tracking module lets you limit the packet quantities directed over a network interface. This can be used to prevent denial-of-service attacks, where an intruder tries to flood the network with IP packets. For example, an exceptionally fast increase of the packet traffic can be intercepted as follows:

     iptables -A INVALID-DROP -m limit -limit 5/hour --limit-burst 3 --limit LOG

    Chapter 20 discusses the connection-tracking functionality in detail.

  • Address translation (NAT): The new implementation of the NAT functionality (iptable_nat.o module, including protocol-specific helper modules, such as ip_nat_ftp.o) is much better performing than the "masquerading" of Linux 2.2. It is addressed from the nat table and implements various operating modes for address translation. The following four operating modes are currently available:

    • Source NAT changes the source address of an incoming packet before it is forwarded. This function is addressed by the SNAT option in iptables. This mode lets computers access Internet services from a network with private IP addresses, where the actual source address is hidden from the outside and replaced by the address of the firewall computer. A typical rule definition for source NAT is as follows:

       iptables -t nat -A POSTROUTING -j SNAT --to-source <firewall address>

    • The second operating mode is a special version of source NAT, one especially used in communication servers for masquerading. It is designed for interplay with dynamically allocated IP addresses. For this reason, all old connection data yielded by the connection-tracking module is dropped whenever the connection is interrupted. A typical rule definition looks like this:

       iptables -t nat -A POSTROUTING -j MASQUERADE -o ppp0

      This definition causes the source address of all packets leaving the router over the first PPP interface to be set to the address of this interface.

    • The destination NAT functionality is new in netfilter. It can be used to redirect packets to a different destination address exactly in line with the source NAT. For this purpose, the destination address in the IP header has to be changed before the packet passes the router, so that destination NAT is hooked in the netfilter hook NF_IP_PRE_ROUTING.

      For example, destination NAT can be used to implement transparent proxies. The following rule definition directs all HTTP packets (TCP port 80) arriving over the second Ethernet interface to port 8080 of the HTTP proxy with address 192.168.1.2:

       iptables -t nat -A PREROUTING -j DNAT \    --to-destination 192.168.1.2:8080 -p tcp --dport 80 -i eth1

      A special case of the destination NAT functionality is the REDIRECT branch destination. It redirects packets to a specific port in the local computer, so that transparent proxies can be easily included, if present in the local computer:

       iptables -t nat -A PREROUTING -j REDIRECT \    --to-port 8080 -i eth1 -p tcp --dport 80

  • Other possibilities for manipulating packets: Additional options that manipulate packets are available in the mangle tables. For example, we could mark specific packets to recognize them within the scope of a security concept or allocate packets to a specific queue in connection with the ip_queue.o module. For this purpose, we use the MARK branch destination. For example, the following call marks all TCP packets with the value 0x0a:

     iptables -t mangle -A PREROUTING -j MARK --set-mark 0x0a -p

    If packets are treated differently in the network, depending on the TOS or DS field (type of service / differentiated services) in the IP header, then this field can be changed by use of the TOS option, for example, to handle SSH packets in a special way:

     iptables -t mangle -A PREROUTING -j TOS --set-tos 0x10    -p tcp --dport ssh

  • Compatibility modules for ipchains and ipfwadm: The ipchains.o and ipfwadm.o compatibility modules ensure a soft transition from old Linux versions to Linux 2.4, because the old configuration files and scripts for ipchains (Linux 2.2) and ipfwadm (Linux 2.0) can be reused during a transition period. Because they exist solely for compatibility reasons, they will not be further developed in the future.


       


    Linux Network Architecture
    Linux Network Architecture
    ISBN: 131777203
    EAN: N/A
    Year: 2004
    Pages: 187

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net