7

There's a binary that I need to run which uses bind with a port argument of zero, to get a random free port from the system. Is there a way I can constrain the range of ports the kernel is allowed to pick from?

7

on Linux, you'd do something like

sudo sysctl -w net.ipv4.ip_local_port_range="60000 61000" 

instruction for changing ephemeral port range on other unices can be found for example at http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html

4

If you want to change the way a binary runs without having access to its sources, you can sometimes use a shim, a piece of code that, in your example, will replace the call on bind() by a call to a function you provide that can manipulate the data before calling the real function. See LD_PRELOAD in man ld.so.

Here's some C that does exactly that, shim_bind.c, overriding the port to 7777, and assuming an AF_INET socket. Compile it with gcc -Wall -O2 -fpic -shared -ldl -o shim_bind.so shim_bind.c and use it by putting LD_PRELOAD=shim_bind.so in front of your command.

/*
 * capture calls to a routine and replace with your code
 * http://unix.stackexchange.com/a/305336/119298
 * gcc -Wall -O2 -fpic -shared -ldl -o shim_bind.so shim_bind.c
 * LD_PRELOAD=/path/to/shim_bind.so ./test
 */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen){
    static int (*real_bind)(int sockfd, const struct sockaddr *addr,
                            socklen_t addrlen) = NULL;
    int port = 7777;
    struct sockaddr_in theaddr;

    if (!real_bind) {
        real_bind = dlsym(RTLD_NEXT, "bind");
        char *error = dlerror();
        if (error != NULL) {
            fprintf(stderr, "%s\n", error);
            exit(1);
        }
    }
    fprintf(stderr, "binding: port %d\n", port);
    memcpy(&theaddr, addr, sizeof(theaddr));
    theaddr.sin_port = htons((unsigned short)port);
    return real_bind(sockfd, (struct sockaddr*)&theaddr, addrlen);
}
  • The ip_local_port_range will be easier for me to set up right now, but I'll probably need to play with other calls on this binary so this looks very useful, thanks! – Délisson Junio Aug 24 '16 at 2:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.