Packet Marks with UDP and portforwarding

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

 



Hello,

we're using nftables on debian as a firewall and for NAT for ~300 students. I recently found an issue which might or might not be a bug and I hope this is the right place for sharing it. Any comments would be greatly appreciated.

We have a public IP-Address & interface, $nat_ip and $dev_ext; all packets from the local networks ($user, $man) undergo SNAT. Also, tcp or udp packets with certain destination ports addressed to $nat_ip should be forwarded to some clients on the local network ('portforwarding'). This is implemented using packet metainformation:

table ip nat {

  set forwarded_ports_tcp { type inet_service; }
  set forwarded_ports_udp { type inet_service; }

  chain portforwards {
    meta mark set mark or $mark_portforward
  }

  chain prerouting {
    type nat hook prerouting priority 0;

    meta iif $dev_ext tcp dport @forwarded_ports_tcp goto portforwards
    meta iif $dev_ext udp dport @forwarded_ports_udp goto portforwards

  }

  chain outgoing_post {
    snat ip saddr map {
      $user : $nat_ip,
      $man  : $nat_ip
    }
  }

  chain postrouting {
    type nat hook postrouting priority 0;

    meta oif $dev_ext goto outgoing_post
  }
}
add rule ip nat portforwards udp dport 7777 dnat 10.10.3.101 : 7777
add element ip nat forwarded_ports_udp { 7777 }
add rule ip nat portforwards tcp dport 7777 dnat 10.10.3.101 : 7777
add element ip nat forwarded_ports_tcp { 7777 }

Furthermore, in the filter table, we have the following chain, which contains among others the following rules and is traversed by all packets being forwarded to the local network:

  chain in_ext  {

    # ...

    # accept port forward
    meta mark and $mark_portforward != 0 return
    reject
  }

Now, this works fine for tcp, i.e. I can establish a tcp connection to $nat_ip:7777 and talk to my laptop (10.10.3.101) from the outside. For udp, only the first packet arrives at the destination. Adding "ip daddr 10.10.3.101 return" to the chain in_ext solves this problem.
This brings me to the following conclusion:

UDP portforwarding in our setup, using packet marks, fails because only the first packet of a 'connection' is marked ( 0x0008 = portforward ) as it hits the NAT prerouting chain. All following packets don't traverse the NAT chain because they belong to the same connection (this is expected), but they do not carry the mark (0x0008), which is surprising (to me), and different from the behaviour with TCP packets.

Now, my question is: Is this behaviour intended? If so, why is it different for TCP & UDP?

Best,
Philip



[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