All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: Stateless NAT with iptables
@ 2015-01-09 23:54 Jan Engelhardt
  2015-01-12 18:49 ` Glen Miner
  0 siblings, 1 reply; 9+ messages in thread
From: Jan Engelhardt @ 2015-01-09 23:54 UTC (permalink / raw)
  To: Glen Miner; +Cc: Netfilter user mailing list, Kristian Evensen


> What we're trying to do is set up UDP NAT proxy for a pair of
> clients on demand. The mappings are preceded by some application
> layer traffic used to figure out where the mapping should go --
> we're essentially trying to use the netfilter stack to do a blazing
> fast STUN/TURN server with no packet overhead.
>
> In my prototype this works but there's a problem: nf_conntrac gets
> in the way of the hand-off between the application layer socket and
> the NAT rule. I've tried telling iptables to go stateless: 
> iptables -t raw -F
> iptables -t raw -I PREROUTING -j NOTRACK
> iptables -t raw -I OUTPUT -j NOTRACK

Rules are rather static, but your described scenario requires
rather dynamic changes. There is a much more targeted solution:

Once your application decides it is time to switch, it needs to
change the conntrack entry for the UDP session. conntrack(8)
can be used, and there is also a C interface with
libnetfilter_conntrack.

(With the conntrack command line utility, updating certain parameters is 
not possible because of the program's way of option parsing. This 
limitation may be gone in the C interface. With the command-line 
utility, one could however recreate the entry, if the lack of atomicity 
between the operations is bearable.)

conntrack -D -p udp \
	--src client_addr --dst stun_addr \
	--sport client_port --dport stun_port
conntrack -I -p udp \
	--src client_addr --dst stun_addr \
	--sport client_port --dport stun_port \
	--reply-src real_server_addr --reply-dst client_addr \
	--reply-src-port real_server_port \
	--reply-dst-port client_port

At least, that is the general idea.. whether it works, or if it needs
additional commands, I have not tried.

^ permalink raw reply	[flat|nested] 9+ messages in thread
* Stateless NAT with iptables
@ 2015-01-09 18:38 Glen Miner
  2015-01-09 19:14 ` Kristian Evensen
  0 siblings, 1 reply; 9+ messages in thread
From: Glen Miner @ 2015-01-09 18:38 UTC (permalink / raw)
  To: netfilter@vger.kernel.org


After a day of hacking around and trolling the internet I'm more or less convinced this isn't possible with iptables but I figured I should ask in case I missed something.

What we're trying to do is set up UDP NAT proxy for a pair of clients on demand.

The mappings are preceded by some application layer traffic used to figure out where the mapping should go -- we're essentially trying to use the netfilter stack to do a blazing fast STUN/TURN server with no packet overhead. We need to bounce a few packets around on the ports we're going to proxy because this is how we figure out the remote peer address & ports we'll need to bind together.

In my prototype this works but there's a problem: nf_conntrac gets in the way of the hand-off between the application layer socket and the NAT rule. I've tried telling iptables to go stateless:

iptables -t raw -F

iptables -t raw -I PREROUTING -j NOTRACK
iptables -t raw -I OUTPUT -j NOTRACK

But of course this means that none of my -t nat rules are checked; I've read the documentation several times now and I can't seem to find a way to have my cake and eat it too.

In more detail here's how it currently works (and what goes wrong):

Alice sends a message to the relay server saying "can you help me talk to Bob?" (the mechanics of this communication channel are unimportant)

The relay server binds a pair of UDP sockets $anPort and $bnPort to be used for the proxy on $nAddr and tells

Alice: send me a packet to $nAddr:$bnPort so I can figure out how your router NATs to that endpoint
- this gives us $aAddr and $aPort

Bob: send me a packet to $anPort 
- this gives us $bAddr and $bPort

With that, the server then has enough information to create the following rules

# A->B
iptables -t nat -I PREROUTING -p udp -s $aAddr --sport $aPort -d $nAddr --dport $bnPort -j DNAT --to $bAddr:$bPort
iptables -t nat -A POSTROUTING -p udp -d $bAddr --dport $bPort -j SNAT --to $nAddr:$anPort
iptables -t nat -I OUTPUT -p udp -s $aAddr --sport $aPort -d $nAddr --dport $bnPort -j DNAT --to $bAddr:$bPort

# B->A (NOTE: these are not needed per se if Alice sends a packet to Bob first)
iptables -t nat -I PREROUTING -p udp -s $bAddr --sport $bPort -d $nAddr --dport $anPort -j DNAT --to $aAddr:$aPort
iptables -t nat -A POSTROUTING -p udp -d $aAddr --dport $aPort -j SNAT --to $nAddr:$bnPort
iptables -t nat -I OUTPUT -p udp -s $bAddr --sport $bPort -d $nAddr --dport $anPort -j DNAT --to $aAddr:$aPort

And now as far as Alice is concerned Bob is at $nAddr:$bnPort and as far as Bob is concerned Alice is at $nAddr:$anPort

We can technically close the sockets we used to discover the bind points -- they aren't needed any more -- but here's the rub: nf_conntrack_udp_timeout seconds has to elapse with NO traffic from Alice or Bob to the bind ports; evidently there is a connection kicking around that is preventing the NAT rules I added from taking over and the system default is 30 seconds.

I can see the connection with this command:

conntrack -L --proto udp --dport=$anPort

Until this times out I get no joy and any stray packet from the respective peer will reset the countdown.

There are two workarounds I can think of:

1) reduce nf_conntrack_udp_timeout 
2) try a conntract -D command to clear the connection
3) before binding the local sockets I create rules to NOTRACK them while they're in userland

The fourth option that I dream of, however, is a "please don't bother with nf_conntrack, I really don't need it, honest" -- this would be the ideal case but try as I might I can't find any way to make this work. NOTRACK means no -t nat and you can't rewrite source or dest headers without -t nat.

Here's why I'd really like to ditch conntrack: it's a waste of resources for us. In fact, when we get up to around 40,000 users on a server (not doing this NAT stuff, just doing other things), the conntrack table can overflow and cause all kinds or problems. I could be wrong but I'm pretty confident we don't need it for anything -- our firewall rules can be really simple.

I read some of the new nftables documentation but as far as I can tell it's still doing the same hooks and doesn't get me any closer to success. As far as I can tell I can't escape conntrack for what I'm doing.

If you've read this far, thanks for reading; if you have any light to shed, thanks in advance!

-g


 		 	   		  

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-01-12 22:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-09 23:54 Stateless NAT with iptables Jan Engelhardt
2015-01-12 18:49 ` Glen Miner
2015-01-12 19:25   ` Glen Miner
2015-01-12 22:06   ` Marcelo Ricardo Leitner
  -- strict thread matches above, loose matches on Subject: below --
2015-01-09 18:38 Glen Miner
2015-01-09 19:14 ` Kristian Evensen
2015-01-09 20:32   ` Glen Miner
2015-01-09 20:53     ` Kristian Evensen
2015-01-09 22:35       ` Glen Miner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.