Force any binary to use a specific network interface.
Requires gcc and bash. Linux only.
Usage:
$ sudo ./setnif.sh eth1 curl www.google.com
Inspired by Daniel Ryde's Libc wrapper for bind and connect.
Force any binary to use a specific network interface.
Requires gcc and bash. Linux only.
Usage:
$ sudo ./setnif.sh eth1 curl www.google.com
Inspired by Daniel Ryde's Libc wrapper for bind and connect.
| #!/usr/bin/env bash | |
| # Build lib | |
| build() | |
| { | |
| gcc -o $SO -nostartfiles -fpic -shared -xc - -ldl -D_GNU_SOURCE <<EOF | |
| #include <sys/socket.h> | |
| #include <sys/ioctl.h> | |
| #include <net/if.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <dlfcn.h> | |
| int (*std_socket)( int, int, int ); | |
| void _init( void ) | |
| { | |
| const char *err; | |
| std_socket = dlsym( RTLD_NEXT, "socket" ); | |
| if( (err = dlerror()) != NULL ) | |
| fprintf( stderr, "dlsym (socket): %s\n", err ); | |
| } | |
| static void set_nif( int sockfd ) | |
| { | |
| struct ifreq ifr; | |
| const char *nif; | |
| if( !(nif = getenv( "NIF" )) ) | |
| { | |
| fprintf( stderr, "NIF unset\n" ); | |
| return; | |
| } | |
| memset( &ifr, 0, sizeof( ifr ) ); | |
| strncat( ifr.ifr_name, nif, sizeof( ifr.ifr_name ) ); | |
| if( ioctl( sockfd, SIOCGIFINDEX, &ifr ) ) | |
| { | |
| perror( "ioctl" ); | |
| return; | |
| } | |
| if( setsockopt( | |
| sockfd, | |
| SOL_SOCKET, | |
| SO_BINDTODEVICE, | |
| (void *)&ifr, | |
| sizeof( ifr ) ) < 0 ) | |
| perror( "SO_BINDTODEVICE failed" ); | |
| } | |
| int socket( int domain, int type, int protocol ) | |
| { | |
| int sockfd; | |
| if( (sockfd = std_socket( domain, type, protocol )) > 2 && | |
| domain == AF_INET ) | |
| set_nif( sockfd ); | |
| return sockfd; | |
| } | |
| EOF | |
| } | |
| (( $# < 2 )) && { | |
| echo "usage: ${0##*/} DEVICE BINARY [ARGS]" | |
| exit 1 | |
| } | |
| readonly SO=${SO:-"${0%/*}/setnif.so"} | |
| if ! [ -r $SO ] || find ${SO%/*} -newer $SO -name ${0##*/} &>/dev/null | |
| then | |
| build || exit 1 | |
| fi | |
| export NIF=$1 | |
| shift | |
| LD_PRELOAD=$SO $@ |