diff --git a/README.md b/README.md index 6a784b9..1297160 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/bindToInterface.c b/bindToInterface.c index 4354b3e..3c9c423 100644 --- a/bindToInterface.c +++ b/bindToInterface.c @@ -9,12 +9,23 @@ #include #include #include +#include //#define DEBUG //compile with gcc -nostartfiles -fpic -shared bindToInterface.c -o bindToInterface.so -ldl -D_GNU_SOURCE //Use with BIND_INTERFACE= LD_PRELOAD=./bindInterface.so 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); @@ -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; @@ -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"); } }