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); } }
Attachment:
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