Linux free port allocation algorithm - Networking

This is a discussion on Linux free port allocation algorithm - Networking ; There seems to have been a change in the Linux free port allocation algorithm somewhere between kernel 2.6.9 and 2.6.17. When a socket is allocated (with the bind() system call) with sin_port = 0 in 2.6.9 it seems that free ...

+ Reply to Thread
Results 1 to 10 of 10

Thread: Linux free port allocation algorithm

  1. Linux free port allocation algorithm

    There seems to have been a change in the Linux free port allocation
    algorithm somewhere between kernel 2.6.9 and 2.6.17.

    When a socket is allocated (with the bind() system call) with
    sin_port = 0 in 2.6.9 it seems that free ports are handed out
    sequentially, while 2.6.17 will hand them out in random order.

    Unfortunately this breaks a program I use, which depends on being able
    to allocate a port, free it and then allocate it again shortly
    thereafter; if ports are handed out randomly and there are several
    programs on the machine doing the same thing the allocation will fail
    fairly often (this is the birthday paradox).

    Does anyone know when the algorithm was changed? Is there a way to
    restore the old behavior in newer kernels?

    Thanks!

  2. Re: Linux free port allocation algorithm

    kreide@gmail.com writes:

    >There seems to have been a change in the Linux free port allocation
    >algorithm somewhere between kernel 2.6.9 and 2.6.17.


    >When a socket is allocated (with the bind() system call) with
    >sin_port = 0 in 2.6.9 it seems that free ports are handed out
    >sequentially, while 2.6.17 will hand them out in random order.


    >Unfortunately this breaks a program I use, which depends on being able


    Well, then that program should be changed. It has a bug in it.

    >to allocate a port, free it and then allocate it again shortly
    >thereafter; if ports are handed out randomly and there are several
    >programs on the machine doing the same thing the allocation will fail
    >fairly often (this is the birthday paradox).


    Have you found such failures or are you just guessing?


    >Does anyone know when the algorithm was changed? Is there a way to
    >restore the old behavior in newer kernels?



  3. Re: Linux free port allocation algorithm

    > >Unfortunately this breaks a program I use, which depends on being able
    > Well, then that program should be changed. It has a bug in it.


    I agree, however, I do not have the option of changing the program in
    question, thus unless I can find a way to preserve the old behavior on
    newer kernels I am stuck with 2.6.9.

    > >programs on the machine doing the same thing the allocation will fail
    > >fairly often (this is the birthday paradox).

    > Have you found such failures or are you just guessing?


    Yes, unfortunately this does happen in practice, which is why I am
    trying to find a solution.

  4. Re: Linux free port allocation algorithm

    On Jan 5, 1:22 pm, kre...@gmail.com wrote:

    > Yes, unfortunately this does happen in practice, which is why I am
    > trying to find a solution.


    Preload a library that changes the 'bind' wrapper so that a 'bind'
    with a port of zero uses a port that you select using whatever
    algorithm you like. Google for 'LD_PRELOAD' for more information.

    DS

  5. Re: Linux free port allocation algorithm

    > Preload a library that changes the 'bind' wrapper so that a 'bind'

    Actually that is a great idea, and what is even better it turned out
    to work great in practice. Thank you for the help!

  6. Re: Linux free port allocation algorithm

    On Jan 5, 1:22 pm, kre...@gmail.com wrote:
    > Yes, unfortunately this does happen in practice, which is why I am
    > trying to find a solution.


    David Schwartz wrote:
    > Preload a library that changes the 'bind' wrapper so that a 'bind'
    > with a port of zero uses a port that you select using whatever
    > algorithm you like.


    Alternatively, change your program (since that's the one with the
    incorrect expectation) to give bind() a specific port number.

    Chris

  7. Re: Linux free port allocation algorithm

    Hello,

    kreide@gmail.com a écrit :
    > There seems to have been a change in the Linux free port allocation
    > algorithm somewhere between kernel 2.6.9 and 2.6.17.
    >
    > When a socket is allocated (with the bind() system call) with
    > sin_port = 0 in 2.6.9 it seems that free ports are handed out
    > sequentially, while 2.6.17 will hand them out in random order.


    [cut description of application with broken behaviour]

    > Does anyone know when the algorithm was changed?


    2.6.11 :
    [TCP]: Efficient port randomization

    Provide port randomization for incoming connections using
    variation of existing sequence number hash.

    2.6.15 :
    [TCP/DCCP]: Randomize port selection

    This patch randomizes the port selected on bind() for connections
    to help with possible security attacks. It should also be faster
    in most cases because there is no need for a global lock.

    > Is there a way to restore the old behavior in newer kernels?


    I haven't found any sysctl which does that.

  8. Re: Linux free port allocation algorithm

    > Preload a library that changes the 'bind' wrapper so that a 'bind'

    In case someone else is interested I am posting the source code for
    the program that I came up with. It has been a while since I did low-
    level C programming, but hopefully someone here can do a code review
    and point out any flaws or suggest improvements.

    #include
    #include

    // avoid duplicate definition of bind()
    #define _SYS_SOCKET_H 1
    #include

    // required to get RTLD_NEXT
    #ifndef __USE_GNU
    #define __USE_GNU 1
    #endif
    #include

    #define LOW_PORT 32768
    #define HIGH_PORT 60999

    volatile static int next_port = LOW_PORT;

    int bind(int __fd, struct sockaddr * __addr, socklen_t __len) {
    static off_t (*funcptr)(int, struct sockaddr *, socklen_t) = NULL;

    if (!funcptr) {
    funcptr = (off_t (*)(int, struct sockaddr *, socklen_t))
    dlsym(RTLD_NEXT, "bind");
    }

    if ( __addr->sa_family == AF_INET) {
    struct sockaddr_in * __addr_in = (struct sockaddr_in *) __addr;
    if (__addr_in->sin_port == 0) {
    int ret;
    do {
    if (next_port > HIGH_PORT) next_port = LOW_PORT;
    int my_port = next_port++;
    __addr_in->sin_port = htons(my_port);
    ret = (*funcptr)(__fd, __addr, __len);
    } while (ret < 0 && errno == EADDRINUSE);
    return ret;
    }
    }
    return (*funcptr)(__fd, __addr, __len);
    }

  9. Re: Linux free port allocation algorithm

    > [cut description of application with broken behavior]

    Let me quickly describe why I need this; it is not as unreasonable as
    one might think.

    I have several server modules which are unit tested automatically; my
    testing tool is integrated with the RCS (mercurial in case anyone is
    curious) which checks out and tests all committed revisions. Since the
    testing is somewhat time consuming and the machine has lots of spare
    CPU cores many revisions are tested in parallel.

    Some of the server modules are 3rd party and require a port number to
    be specified when they are started; since many instances of each
    server module is running on the same machine they need different port
    numbers and the way I obtain these is by allocating a socket on a free
    port, close the socket and give that port number to the server module.
    There is of course a race condition here, but if free ports are handed
    out sequentially this is not a problem in practice; if they are random
    it is.

    Changing the 3rd party modules is unfortunately not an option, and I
    would like to avoid having to implement my own service to keep track
    of allocated ports on the machine; depending on bind() behaving in a
    certain way seems like the better option.

  10. Re: Linux free port allocation algorithm

    On Jan 7, 9:51 am, kre...@gmail.com wrote:

    > Some of the server modules are 3rd party and require a port number to
    > be specified when they are started; since many instances of each
    > server module is running on the same machine they need different port
    > numbers and the way I obtain these is by allocating a socket on a free
    > port, close the socket and give that port number to the server module.
    > There is of course a race condition here, but if free ports are handed
    > out sequentially this is not a problem in practice; if they are random
    > it is.


    A better solution, IMO, is to use a range of ports that is outside the
    range the system assigns from. So if the system assigns from, say,
    33,000 to 55,000, you assign from 60,000 up sequentially, wrapping
    around if you run out.

    You don't seem to have any need for system-assigned port numbers here.

    DS

+ Reply to Thread