Problems with DNAT'ing in PREROUTING

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I am trying to build a custom firewall kernel module for Linux. The
module registers itself in the pre-routing chain as the first module.
In the NetFilter callback function I check if the skb is for a tcp
connection and the port is 80. If the two requirements are meant, I
modify the destination address and the checksum of the IP as well as
the TCP header to the ip address of the machine where this (DNAT) is
taking place in the ip header and let the packet pass. Unfortunately,
this is not working. I've put a great deal of effort trying to
understand the DNAT'ing code in xtables but again of no use. As far as
I've read, at the time of pre-routing nothing in the skb, excepting
the ethernet, ip and protocol headers along with the payload is set.
If that is the case (and if the checksums are all right), I don't see
a reason why a packet should be dropped.

Following is the NetFilter callback function code (I am not including
the rest of the code as it is trivial).

static unsigned int _rfw_prerouting_hook(unsigned int             _nHook,
                     struct sk_buff*          _pSKB,
                     const struct net_device* _pInNIC,
                     const struct net_device* _pOutNIC,
                     int (*_pOkFn)(struct sk_buff*))
{
  if(!strcmp(_pInNIC->name, "eth1"))
    {
      if(_pSKB)
    {
      struct iphdr* _pIPHeader = ip_hdr(_pSKB);

      if(_pIPHeader)
        {
          switch(_pIPHeader->protocol)
        {
        case IPPROTO_TCP:
          {
            struct tcphdr* _pTCPHeader = (struct tcphdr*)(_pSKB->data
+ (_pIPHeader->ihl << 2));


            if(_pTCPHeader &&
               (_pIPHeader->daddr != ((1 << 24) + 10)) &&
               (_pTCPHeader->dest == htons(80)))
              {
            // Only modifying TCP packets whose destination IP is not
10.0.0.1 and destination port is 80
            _pIPHeader->daddr = (1 << 24) + 10; // Hopefully this
translates to 10.0.0.1
            _pIPHeader->check = 0;
            _pIPHeader->check = ip_fast_csum((unsigned
char*)_pIPHeader, _pIPHeader->ihl);

            _pTCPHeader->check = 0;
            _pTCPHeader->check = tcp_v4_check(_pTCPHeader->doff << 2,
_pIPHeader->saddr,
                              _pIPHeader->daddr,
                              csum_partial((char*)_
pTCPHeader,
                                       _pTCPHeader->doff << 2,
                                       0));
              }
          } break;
        }
        }
    }
    }

  return NF_ACCEPT;
}

One might say that this task can be easily done using a trivial
iptables rule, but my problem does not end at this point. What I am
expected to do is eventually conditionally do a DNAT for just a
specified, dynamic set of IP addresses.

It would be great if someone could point me in the right direction.

Thank you and regards,
Subhadeep Ghosh
--
To unsubscribe from this list: send the line "unsubscribe netfilter" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux