[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Хочется странного



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

Reply to: