Return to BSD News archive
Newsgroups: comp.unix.bsd.freebsd.misc Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!news.rmit.EDU.AU!news.unimelb.edu.au!munnari.OZ.AU!news.ecn.uoknor.edu!feed1.news.erols.com!disgorge.news.demon.net!demon!dispatch.news.demon.net!demon!rill.news.pipex.net!pipex!oleane!in2p3.fr!univ-lyon1.fr!fdn.fr!r2d2.fdn.org!sphynx.fdn.fr!causse From: causse@sphynx.fdn.fr (Philippe Causse) Subject: Re: Accept()-ing a connection from a specific IP address... X-Newsreader: TIN [version 1.2 PL2] Organization: individual - paris - france Message-ID: <EAnnEo.12E@sphynx.fdn.fr> References: <864144757.18711@dejanews.com> <EAHuuM.129@sphynx.fdn.fr> <5lvqjg$7rq$1@goof.Germany.EU.net> Date: Fri, 23 May 1997 22:20:47 GMT Lines: 162 Xref: euryale.cc.adfa.oz.au comp.unix.bsd.freebsd.misc:41533 Bernard Steiner (knob@wizards.staff.Germany.EU.net) wrote: : In article <EAHuuM.129@sphynx.fdn.fr>, : causse@sphynx.fdn.fr (Philippe Causse) writes: : > moballa@WESTECHMobile.com wrote: : >: Is there any way to use the Accept() routine to only accept a connection : >: from a specific IP address? Currently my program accepts a connection : >: from anyone issuing a connect() call to it. I would like to specify that : >: it should only accept a connection from a particular IP address. : > Afetr you created your `listening' socket: : > 1) bind it to the interface you whish to accept calls from : > (getnetent could help) : That helps in cases where you wish to service requests only on a particular : interface (or similar). That's exactly what I meant... : > 2) When accept() returns, check the peer address and if : > the address is not an "allowed one", you should immediately : > close the returned socket. : That does not help really, since AFAIK accept() does a three-way handshake and : closing the connection immediately is quite different from not accepting it. It may be more polite to accept, then write a short message like 500 - Service not available and close nicely. Yes,it'll require a few more packets, but saying "goodbye" never hurted anyone... : What I would like to know is whether or not it is now possible to : (a) use the rcvmsg() (or was that recvfrom() ?) calls for bound TCP sockets : *and According to the man page, it says recvfrom can be used on a socket, whether it is connection-oriented or not. Although does not state that recvfrom can be used on a passive socket! The demo program attached illustrates that you cannot guess the peer's address before accept() has been done (for TCP stuff, of course). : (b) somehow discard TCP SYNs from illegitimate addresses and optionally tell : the other side we are refusing connections ? Then you should probably setup a firwall ! AFAIK this is the only way to reject connection attemps. (kinda fascit stuff IMHO). : > Other option (simpler, faster): use the tcp_wrappers library ! : You mean reverse-engineer the thing ;-) Not at all. Just making use of the tcpwrappers API in your program like a few others did (ypserv for example). And if your server is started from inetd, it's trivial to start put it under tcpwrapper's control... RTFM! : Bernard ----[cut here]--- #include <stddef.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define SERVER_PORT 4321 /* * Method 1 : does not work. * Peek some data in the TCP queue to look for IP address... */ void filter_connect_1(int so) { struct sockaddr_in peer_addr; int peer_addr_len = sizeof(peer_addr); int sts; char buf[1]; bzero(&peer_addr, peer_addr_len); sts = recvfrom(so, buf, sizeof(buf), MSG_PEEK, (struct sockaddr *)&peer_addr, &peer_addr_len); if(sts < 0) perror("recvfrom"); printf("Rejecting incoming connect() from %s\n", inet_ntoa(peer_addr.sin_addr)); close( accept(so, NULL, 0)); } /* * Method 2 : does work :-) * Check the result of accept. */ void filter_connect_2(int so) { FILE * cli; int cli_sock; struct sockaddr_in peer_addr; int peer_addr_len = sizeof(peer_addr); bzero(&peer_addr, peer_addr_len); cli_sock = accept(so, (struct sockaddr *)&peer_addr, &peer_addr_len); if( cli_sock < 0) perror("accept"); printf("Incoming connect() from %s\n", inet_ntoa(peer_addr.sin_addr)); cli = fdopen(cli_sock, "w"); fprintf(cli, "500 - Not authorized to connect\r\n"); fflush(cli); fclose(cli); close(cli_sock); } int main() { int sts; int so; /* server socket */ struct sockaddr_in serv_addr; int serv_addr_len; fd_set readfds; int nfds; serv_addr.sin_port = htons(SERVER_PORT); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_len = sizeof(serv_addr); /* total length */ bzero(&serv_addr.sin_zero, sizeof(serv_addr.sin_zero)); serv_addr_len = sizeof(serv_addr); so = socket(AF_INET, SOCK_STREAM, PF_UNSPEC); assert(so >= 0); sts = bind(so, (struct sockaddr *)&serv_addr, serv_addr_len); assert( sts == 0); sts = listen(so, 5); assert(sts == 0); while(1) { puts("--> select()"); nfds = so + 1; FD_ZERO(&readfds); FD_SET(so, &readfds); sts = select(nfds, &readfds, 0, 0, NULL); puts("<-- select()"); /* filter_connect_1(so); */ /* doesn't work */ filter_connect_2(so); /* works */ } close(so); return EXIT_FAILURE; } ------[cut here, compile and telnet to port 4321]----- -- ------------------------------------------------------------------- P. Causse http://www.fdn.fr/~pcausse 4.4BSD/X11R6/Motif-2.0/C++ mailto:causse@sphynx.fdn.fr (UUCP)