Last active
September 30, 2023 00:51
-
-
Save stefansundin/e4fce00d97f7694c7a27 to your computer and use it in GitHub Desktop.
Bind programs to specific network interface. (Linux)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
https://gist.github.com/stefansundin/e4fce00d97f7694c7a27 | |
http://www.ryde.net/code/bind.c.txt | |
http://daniel-lange.com/archives/53-Binding-applications-to-a-specific-IP.html | |
*/ | |
/* | |
Copyright (C) 2000 Daniel Ryde | |
This library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Lesser General Public | |
License as published by the Free Software Foundation; either | |
version 2.1 of the License, or (at your option) any later version. | |
This library is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Lesser General Public License for more details. | |
*/ | |
/* | |
LD_PRELOAD library to make bind and connect to use a virtual | |
IP address as localaddress. Specified via the enviroment | |
variable BIND_ADDR. | |
Compile on Linux with: | |
gcc -nostartfiles -fpic -shared bind.c -o bind.so -ldl -D_GNU_SOURCE | |
Example in bash to make inetd only listen to the localhost | |
lo interface, thus disabling remote connections and only | |
enable to/from localhost: | |
BIND_ADDR="127.0.0.1" LD_PRELOAD=./bind.so /sbin/inetd | |
Example in bash to use your virtual IP as your outgoing | |
sourceaddress for ircII: | |
BIND_ADDR="your-virt-ip" LD_PRELOAD=./bind.so ircII | |
Note that you have to set up your servers virtual IP first. | |
This program was made by Daniel Ryde | |
email: daniel@ryde.net | |
web: http://www.ryde.net/ | |
TODO: I would like to extend it to the accept calls too, like a | |
general tcp-wrapper. Also like an junkbuster for web-banners. | |
For libc5 you need to replace socklen_t with int. | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <dlfcn.h> | |
#include <errno.h> | |
int (*real_bind)(int, const struct sockaddr *, socklen_t); | |
int (*real_connect)(int, const struct sockaddr *, socklen_t); | |
char *bind_addr_env; | |
unsigned long int bind_addr_saddr; | |
unsigned long int inaddr_any_saddr; | |
struct sockaddr_in local_sockaddr_in[] = { 0 }; | |
void _init (void) | |
{ | |
const char *err; | |
real_bind = dlsym (RTLD_NEXT, "bind"); | |
if ((err = dlerror ()) != NULL) { | |
fprintf (stderr, "dlsym (bind): %s\n", err); | |
} | |
real_connect = dlsym (RTLD_NEXT, "connect"); | |
if ((err = dlerror ()) != NULL) { | |
fprintf (stderr, "dlsym (connect): %s\n", err); | |
} | |
inaddr_any_saddr = htonl (INADDR_ANY); | |
if ((bind_addr_env = getenv ("BIND_ADDR"))) { | |
bind_addr_saddr = inet_addr (bind_addr_env); | |
local_sockaddr_in->sin_family = AF_INET; | |
local_sockaddr_in->sin_addr.s_addr = bind_addr_saddr; | |
local_sockaddr_in->sin_port = htons (0); | |
} | |
} | |
int bind (int fd, const struct sockaddr *sk, socklen_t sl) | |
{ | |
static struct sockaddr_in *lsk_in; | |
lsk_in = (struct sockaddr_in *)sk; | |
// printf("bind: %d %s:%d\n", fd, inet_ntoa (lsk_in->sin_addr.s_addr), ntohs (lsk_in->sin_port)); | |
if ((lsk_in->sin_family == AF_INET) | |
&& (lsk_in->sin_addr.s_addr == inaddr_any_saddr) | |
&& (bind_addr_env)) { | |
lsk_in->sin_addr.s_addr = bind_addr_saddr; | |
} | |
return real_bind (fd, sk, sl); | |
} | |
int connect (int fd, const struct sockaddr *sk, socklen_t sl) | |
{ | |
static struct sockaddr_in *rsk_in; | |
rsk_in = (struct sockaddr_in *)sk; | |
// printf("connect: %d %s:%d\n", fd, inet_ntoa (rsk_in->sin_addr.s_addr), ntohs (rsk_in->sin_port)); | |
if ((rsk_in->sin_family == AF_INET) | |
&& (bind_addr_env)) { | |
real_bind (fd, (struct sockaddr *)local_sockaddr_in, sizeof (struct sockaddr)); | |
} | |
return real_connect (fd, sk, sl); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment