lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <6zlhtsvnqp.fsf@southpole.se>
Date:	Fri, 23 May 2014 11:38:22 +0200
From:	nisse@...thpole.se (Niels Möller)
To:	netdev@...r.kernel.org
Cc:	Jonas Bonn <jonas@...thpole.se>
Subject: What's the right way to use a *large* number of source addresses?

Hi,

I have a client doing traffic generation for load testing. When they
experienced performance problems with assigning a large number (say,
100000) ip addresses to an interface, they wrote a custom and
proprietary source NAT kernel module which let's you set any desired
source address on a socket, and then sets up SNAT to that address. This
was a couple of years ago, and it appears to have worked fine.

However, the code is a bit complex, and duplicates functionality in the
iptables SNAT target and the connection tracking machinery in the
current kernel. If I could relicense the module under a free license, I
suspect it would be shot down for technical reasons.

So now I'm trying to figure out what's the Right Way to enable traffic
generations with a large number of source addresses, to possibly retire
the proprietary kernel module. I see a couple of different approaches:

1. Simply assign all addresses to be used to the interface, fixing any
   remaining performance problems.

   I've done a simple benchmark with a script assigning n addresses
   using "ip address add", and this seems to have O(n^2) complexity.
   E.g, assigning n=25500 addresses took 26 s, and doubling n, assigning
   51000 addresses, took 122 s, 4.6 times longer. Which isn't
   necessarily a problems once all the addresses are assigned, but it
   sounds a bit like there's a linear datastructure in there, not
   intended for a large number of addresses.

   A way to add an address range (or a prefix), using a *single* entry
   of whatever datastructures are used, would help.

2. Do source NAT. I think the current SNAT target does almost everything
   needed. It could be extended with some setsockopt to set the desired
   address on a per socket basis. Not sure where to store that info;
   either associate the desired address with the socket, and have the
   SNAT module look for that. Or maybe one could have setsockopt create
   a conntrack entry in advance, prior to connect.

   Main drawback of using NAT is the overhead for connection tracking;
   it would be preferable if the only per-connection state needed is the
   socket itself.

3. Just set the desired local address with the bind call. Currently,
   this gives an EADDRNOTAVAIL error, so the first step would be some
   option to allow arbitrary source addresses.

   For an arbitrary source address, the network stack can't guess the
   intended interface. So one would also need to support something like
   SO_BINDTODEVICE to tell it explicitly.

   And for replies to be passed up to the transport layer, one must set
   up some processing of incoming packets to deliver them to the local
   machine. It's very unclear to me if there's any good way to do that,
   maybe one needs a conntrack entry for each connection just like with
   SNAT. Even with conntrack I think this approach is a bit cleaner than
   SNAT, in that the transport-layer 5-tuple would be based on the
   address that really is used on the wire.

What do you think? From a user perspective, I think I'd prefer either
(1), or (3) with a single setsockopt call which means "I'm going to use
an arbitrary source address. Transmit my packets over interface X, and
arrange the processing of incoming packets so that replies arrive to
this socket.", and then specify the desired source address with bind()
as usual.

Best regards,
/Niels Möller
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ