On Thu, Jan 16, 2003 at 12:48:21AM +0300, Daniel Ginsburg wrote: > > номер 3. использовать универсальный враппер который будет маскировать для > > приложения наличие конкретного интерфейса, т.е. задавая конфигурационно > > какие интерфейсы разрешены можно для любого демона указать к чему > > биндиться. > > > > Вопрос есть ли в природе подобный враппер, возможно ли теоретически > > создать враппер с данной функциональностью? > > > > Существует ли в природе подобное изделие, не знаю. Но нарисовать такое > достаточно несложно. Достаточно подменить библиотечную функцию bind() на > свою, которая в соотвествии с какими-то правилами поменяет во втором > своем аргументе INADDR_ANY на что-то более здравое. > > Единственные грабли (не считая статически собранных программ), которые > видны сходу: один сокет может быть привязан либо к INADDR_ANY, либо к > одному конкретному адресу, поэтому получится слушать либо на всех > интерфейсах сразу или только на одном, а на двух интерфейсах из трех не > получится. > > Случай, когда программа не делает bind(), а сразу делает listen() не > рассматриваем как неинтересный. >
Вот, от бессонницы примерчик нахакался. См. аттачи. Меняет bind(... INADDR_ANY ...) на bind( .... 127.0.0.1 ...). Идея должна быть ясна. В боевой версии, скорее всего, будет разумным передавать адрес куда байндиться через переменную среды. Инструкции по использованию: сказать make, запустить ./bindlocal.sh /path/to/your/program. Предупреждаю, я это практически не тестировал. -- dg
/* Whacked up by dg.
* Copyright: I don't give a damn.
* Warranty: If it breaks blame yourself not me.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
void *handle;
int (*orig_bind)(int, const struct sockaddr *, socklen_t);
char *error;
struct sockaddr_in *inaddr = (struct sockaddr_in *)addr;
handle = dlopen("/lib/libc.so.6", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "dlopen: %s\n", dlerror());
exit(EXIT_FAILURE);
}
orig_bind = dlsym(handle, "bind");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "dlsym: %s\n", dlerror());
exit(EXIT_FAILURE);
}
if (inaddr->sin_family == AF_INET) {
struct sockaddr_in new_addr = *inaddr;
if (inaddr->sin_addr.s_addr == INADDR_ANY) {
struct in_addr local;
inet_aton("127.0.0.1", &local);
new_addr.sin_addr = local;
}
return orig_bind(sockfd, (struct sockaddr *)&new_addr, addrlen);
} else {
return orig_bind(sockfd, addr, addrlen);
}
}
bindlocal.sh
Description: Bourne shell script
libbindlocal.so: bindlocal.o
gcc -shared -o libbindlocal.so bindlocal.o -lc -ldl
bindlocal.o: bindlocal.c
gcc -fPIC -rdynamic -c bindlocal.c
clean:
rm -f libbindlocal.so bindlocal.o

