Welcome to Linux Support and Sun Help
Search LinuxSupport
From: Subject: Netfilter connection tracking and nat helper modules Date: Thu, 9 Aug 2001 14:15:43 +0100 MIME-Version: 1.0 Content-Type: text/html; charset="Windows-1252" Content-Transfer-Encoding: quoted-printable Content-Location: http://www.gnumonks.org/ftp/pub/doc/conntrack+nat.html X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2919.6600 Netfilter connection tracking and nat helper = modules

Netfilter connection tracking and nat helper modules

Harald Welte, laforge@gnumonks.org

Version 1.2, = 2000/10/14=20 20:37:53=20


Well... This initially wasn't intended to be a publicly available = document.=20 It just contains some of my thoughts during a summer holiday in italy, = where I=20 was trying to port the ip_masq_irc module to the new netfilter = conntrack/nat=20 framework. There was no documentation about this topic available on the = net, so=20 I tried to understand the netfilter code.

1. Introduction

1.1 What the hell is this all about?

This document gives a brief description how to write netfilter = connection=20 tracking helper and nat helper modules. Netfilter is the packet = filtering / NAT=20 infrastructure provided by the Linux 2.4.x kernel.=20

1.2 What to read first

I strongly recommend You reading Rusty Russel's `netfilter hacking = howto'=20 which is available from the netfilter project homepage at=20 http://netfilter.kernelnotes.org=20

2. Connection tracking helper modules

2.1 Description

The duty of a connection tracking module is to specify which packtets = belong=20 to an already established connection. The module has the following means = to do=20 that:=20

2.2 Structures and Functions available

At first some basic structures=20

`struct ip_conntrack_tuple' (just printed the fields valid for TCP)=20

src.ip

the source IP address

src.u.tcp.port

the TCP source port

dst.ip

the destination IP address

dst.protonum

the protocol (IPPROTO_TCP, ...)

dst.u.tcp.port

the TCP destination port

Your kernel module's init function has to call=20 `ip_conntrack_helper_register()' with a pointer to a `struct=20 ip_conntrack_helper'. This struct has the following fields:=20

list

This is the header for the linked list. Netfilter handles this list = internally. Just initialize it with { NULL, NULL }

tuple

This is a `struct ip_conntrack_tuple' which specifies the packets = our=20 conntrack helper module is interested in.

mask

Again a `struct ip_conntrack_tuple'. This mask specifies which bits = of=20 tuple are valid.

help

The function which netfilter should call for each packet matching=20 tuple+mask

2.3 Example skeleton of a conntrack helper module


#define FOO_PORT        111

static int foo_help(const struct iphdr *iph, size_t len,=20
                struct ip_conntrack *ct,=20
                enum ip_conntrack_info ctinfo)
{
        /* analyze the data passed on this connection and=20
           decide how related packets will look like */

        if (there_will_be_new_packets_related_to_this_connection)
        {
                t = new_tuple_specifying_related_packets;
                ip_conntrack_expect_related(ct, &t);
               =20
                /* save information important for NAT in
                        ct->help.ct_foo_info;   */
       =20
        }
        return NF_ACCEPT;
}              =20

static struct ip_conntrack_helper foo;

static int __init init(void)
{
        memset(&foo, 0, sizeof(struct ip_conntrack_helper);

        /* we are interested in all TCP packets with destport 111 */
        foo.tuple.dst.protonum = IPPROTO_TCP;
        foo.tuple.dst.u.tcp.port = htons(FOO_PORT);
        foo.mask.dst.protonum = 0xFFFF;
        foo.mask.dst.u.tcp.port = 0xFFFF;
        foo.help = foo_help;

        return ip_conntrack_helper_register(&foo); =20
}

static void __exit fini(void)
{
        ip_conntrack_helper_unregister(&foo);
}

3. NAT helper modules

3.1 Description

NAT helper modules do some application specific NAT handling. Usually = this=20 includes on-the-fly manipulation of data. Think about the PORT command = in FTP,=20 where the client tells the server which ip/port to connect to. = Thererfore a FTP=20 helper module has to replace the ip/port after the PORT command in the = FTP=20 control connection.=20

If we are dealing with TCP, things get slightly more complicated. The = reason=20 is a possible change of the packet size (FTP example: The length of the = string=20 representing an IP/port tuple after the PORT command has changed). If we = had to=20 change the packet size, we have a syn/ack difference between left and = right side=20 of the NAT box. (i.e. if we had extended one packet by 4 octets, we have = to add=20 this offset to the TCP sequence number of each following packet)=20

Special NAT handling of all related packets is required, too. Take as = example=20 again FTP, where all incoming packets of the DATA connection have to be = NATed to=20 the ip/port given by the client with the PORT command on the control = connection.=20

3.2 Structures and Functions available

Your nat helper module's `init()' function has to call=20 `ip_nat_helper_register()' with a pointer to a `struct ip_nat_helper'. = This=20 struct hast the following members:=20

list

Just again the list header for netfilters internal use. Initialize = this=20 with { NULL, NULL }.

tuple

a `struct ip_conntrack_tuple' describing which packets our nat = helper is=20 interested in.

mask

a `struct ip_conntrack_tuple', telling netfilter which bits of=20 tuple are valid.

help

The help function which is called for each packet matching = tuple+mask.

name

The uniqe name this nat helper is identified by.

3.3 Example NAT helper module


#define FOO_PORT        111

static int foo_nat_expected(struct sk_buff **pksb,
                        unsigned int hooknum,
                        struct ip_conntrack *ct,
                        struct ip_nat_info *info,
                        struct ip_conntrack *master,
                        struct ip_nat_info *masterinfo,
                        unsigned int *verdict)

/* called whenever a related packet (as specified in the =
connectiontracking
   module) arrives
   params:      pksb    packet buffer
                hooknum HOOK the call comes from (POST_ROUTING, =
PRE_ROUTING)
                ct      information about this (the related) connection
                info    (STATE: established, related, new)
                master  information about the master connection
                masterinfo      (STATE: established, related, new) of =
master */
{
        /* basically just change ip/port of the packet to the =
masqueraded
           values (read from master->tuplehash) */

}      =20

static int foo_help(struct ip_conntrack *ct,   =20
                struct ip_nat_info *info,
                enum ip_conntrack_info ctinfo,
                unsigned int hooknum,
                struct sk_buff  **pksb)
/* called for the packet causing related packets=20
   params:      ct      information about tracked connection
                info    (STATE: related, new, established, ... )
                hooknum HOOK the call comes from (POST_ROUTING, =
PRE_ROUTING)
                pksb    packet buffer
*/
{
        /* extract information about future related packets,
           exchange address/port with masqueraded values,
           insert tuple about related packets */
}

static struct ip_nat_expect foo_expect = {
        { NULL, NULL },
        foo_nat_expected };

static struct ip_nat_helper hlpr;

static int __init(void)
{
        if (ip_nat_expect_register(&foo_expect))
        {
                memset(&hlpr, 0, sizeof(struct ip_nat_helper));
                hlpr.list = { NULL, NULL };
                hlpr.tuple.dst.protonum = IPPROTO_TCP;
                hlpr.tuple.dst.u.tcp.port = htons(FOO_PORT);
                hlpr.mask.dst.protonum = 0xFFFF;
                hlpr.mask.dst.u.tcp.port = 0xFFFF;
                hlpr.help = foo_help;

                ip_nat_helper_register(hlpr);
        }
}

static void __exit(void)
{
        ip_nat_expect_unregister(&foo_expect);
        ip_nat_helper_unregister(&hlpr);
}

4. Credits

I want to thank all the great netfilter folks, especially Rusty = Russel, for=20 providing us (the Linux community) with this neat infrastructure.=20

Valid HTML 4.01! Valid CSS!