Sunday, March 19, 2017

Linux SNAT with per-connection source address from IP pool

When doing NAT with pool of addresses to choose from (instead of masquerading) Linux insists on always using same IP from pool for particular source IP. Often this is preferred, but not always. To workaround we need to patch kernel a bit.

Code to tamper with is located in net/netfilter/nf_nat_core.c which also has explanation for this behavior. There's some discussion about this on which also includes patch we need to fix this.

Original nf_nat_core.c
283         /* Hashing source and destination IPs gives a fairly even
284          * spread in practice (if there are a small number of IPs
285          * involved, there usually aren't that many connections
286          * anyway).  The consistency means that servers see the same
287          * client coming from the same IP (some Internet Banking sites
288          * like this), even across reboots.
289          */
290         j = jhash2((u32 *)&tuple->src.u3, sizeof(tuple->src.u3) / sizeof(u32),
291                    range->flags & NF_NAT_RANGE_PERSISTENT ?
292                         0 : (__force u32)tuple->dst.u3.all[max] ^ zone->id);

All we need to do is replace line 290 with this and remove lines 291 and 292.
290         j = prandom_u32();

That's it. Now every new connection will get randomized IP from specified pool. My use case for this? Quite unique I guess. This was my first attempt to work around limitation of Linux IPSEC VTI interfaces not supporting more than one client connecting using same IP address. Situation which rather common with 4G LTE networks and CGNAT's masquerading thousands of users users behind single public IPv4 address.

Here's funky rules I came up with. First one redirect all incoming UDP traffic to Strongswan listening on port udp/4500. Second NATs connection to random IP address from subnet. Yes, this is crazy. Yes, this actually works. Yes, it is useful. No, it's not supported by anyone and most certainly isn't how these components were intended to be used.

iptables -t nat -I PREROUTING -p udp -d -j REDIRECT --to-port 4500
iptables -t nat -I INPUT -p udp -d -j SNAT --to-source

On client side my settings are at least as odd. I added following rule for outbound traffic. This performs DNAT on outbound Strongswan packets. Paired with rightikeport=4500 on ipsec.conf and port=0 + port_nat_t=0 on charon.conf connections over Internet use random UDP source port and random UDP destination port. Yet it's still standard IKEv2 NAT-T traffic to both client and server processes.

iptables -t nat -I OUTPUT --dst -p udp --dport 4500 -j DNAT --to-destination :1-65535 --random

Have fun. :)


  1. you have done a great job. I will definitely dig it and personally recommend to my friends. I am confident they will be benefited from this site 야한동영상

    Please visit once. I leave my blog address below

  2. Wow! After all I got a web site from where I can actually get valuable information regarding my study and knowledge. 일본야동

    Please visit once. I leave my blog address below

  3. Hello friends, its fantastic article about teaching and entirely explained, keep it up all the time. 한국야동닷컴

    Please visit once. I leave my blog address below

  4. Thanks for sharing. I found a lot of interesting information here. A really good post, very thankful and hopeful that you will write many more posts like this one. 국산야동

    Please visit once. I leave my blog address below

  5. Amazing article. Your blog helped me to improve myself in many ways thanks for sharing this kind of wonderful informative blogs in live. I have bookmarked more article from this website. Such a nice blog you are providing. 중국야동넷

    Please visit once. I leave my blog address below


Got something to say?!