Skip to content

Commit

Permalink
allow source IP binding (#12)
Browse files Browse the repository at this point in the history
* allow source IP binding

* Update README.md

* Update README.md

* Update bindToInterface.c

---------

Co-authored-by: JsBergbau <37013344+JsBergbau@users.noreply.github.com>
  • Loading branch information
sh4dowb and JsBergbau authored Oct 24, 2023
1 parent 785b646 commit d477326
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ Especially when using more complex scripts or programs, that use another working

This is the essential part. If not specified program will warn you, however it will not refuse the connection.

### BIND_SOURCE_IP (unreliable / only on some systems)

On some systems you can also set the source IP in case multiple IP addresses are attached to your interface, like this: `BIND_INTERFACE=eth0 BIND_SOURCE_IP=1.2.3.4 LD_PRELOAD...`

**Warning**: It highly depends on which system you are using BIND_SOURCE_IP. Kernel versions 5.10 seem not to work, whereas Kernel 5.15 seems to work, see https://github.com/JsBergbau/BindToInterface/pull/12#issuecomment-1776647513

**Use at your own risk and try if it works on your system**!

### DNS_OVERRIDE_IP

When you have multiple interfaces you normally also have multiple DNS servers. Since your program is bound to specified interface, also DNS traffic has to go through that interface.
Expand Down
26 changes: 23 additions & 3 deletions bindToInterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,23 @@
#include <arpa/inet.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>

//#define DEBUG

//compile with gcc -nostartfiles -fpic -shared bindToInterface.c -o bindToInterface.so -ldl -D_GNU_SOURCE
//Use with BIND_INTERFACE=<network interface> LD_PRELOAD=./bindInterface.so <your program> like curl ifconfig.me

int bind_to_source_ip(int sockfd, const char *source_ip)
{
struct sockaddr_in source_addr;
memset(&source_addr, 0, sizeof(source_addr));
source_addr.sin_family = AF_INET;
source_addr.sin_addr.s_addr = inet_addr(source_ip);

return bind(sockfd, (struct sockaddr *)&source_addr, sizeof(source_addr));
}

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
int *(*original_connect)(int, const struct sockaddr *, socklen_t);
Expand Down Expand Up @@ -80,6 +91,8 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
char *bind_addr_env;
bind_addr_env = getenv("BIND_INTERFACE");
char *source_ip_env;
source_ip_env = getenv("BIND_SOURCE_IP");
struct ifreq interface;

int errorCode;
Expand Down Expand Up @@ -118,9 +131,16 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
};
}
}
else
{
printf("Warning: Programm with LD_PRELOAD startet, but BIND_INTERFACE environment variable not set\n");

if(source_ip_env != NULL && strlen(source_ip_env) > 0){
if (bind_to_source_ip(sockfd, source_ip_env) < 0){
perror("bind_to_source_ip failed");
return -1;
}
}

if(!(source_ip_env != NULL && strlen(source_ip_env) > 0) && !(bind_addr_env != NULL && strlen(bind_addr_env) > 0)){
printf("Warning: Programm with LD_PRELOAD started, but BIND_INTERFACE environment variable not set\n");
fprintf(stderr, "Warning: Programm with LD_PRELOAD startet, but BIND_INTERFACE environment variable not set\n");
}
}
Expand Down

0 comments on commit d477326

Please # to comment.