From d477326d85f64fdd1dc46382fe698e46f4843100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87a=C4=9Fr=C4=B1?= Date: Tue, 24 Oct 2023 10:45:22 +0300 Subject: [PATCH] allow source IP binding (#12) * allow source IP binding * Update README.md * Update README.md * Update bindToInterface.c --------- Co-authored-by: JsBergbau <37013344+JsBergbau@users.noreply.github.com> --- README.md | 8 ++++++++ bindToInterface.c | 26 +++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) 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"); } }