拒绝来自主机的连接

时间:2009-07-12 15:22:50

标签: c++ sockets cross-platform network-programming

我正在使用套接字编写一个简单的tcp服务器应用程序。据我所知,我可以在调用accept()后获取客户端的IP地址和端口。

现在假设我有一个banlist,我想从我的服务器上禁用一些ip地址。有没有比接受连接然后丢弃它更好的方法?

在接受连接之前,有没有办法获取客户端的IP和端口?如果我们接受()为什么我们没有像垃圾()那样的东西?有没有办法拒绝连接或只是忽略来自主机的连接尝试?

4 个答案:

答案 0 :(得分:13)

TCP实现通常在用户进程甚至可以访问连接之前完成TCP 3次握手,而accept()函数只是从队列中获取下一个连接。因此,假装服务器已关闭已为时已晚。这对于常规TCP数据的工作方式相同;在TCP ACK发送之前,TCP实现不会等待应用程序实际recv()数据。这使得另一方不必要地重新传输正确接收的数据包,并允许吞吐量保持高,即使应用程序被其他东西陷入困境。在新连接(SYN数据包)的情况下,这也允许内核保护自己(和应用程序)免受SYN泛洪攻击。

虽然不可移植,但许多平台提供某种防火墙功能,允许根据IP地址/端口过滤传入连接。但是,这通常是在系统范围内配置的,而不是由单个应用程序配置的。

答案 1 :(得分:4)

windows 上:查看WSAAccept,可能是您需要的:

SOCKET WSAAccept(
  __in     SOCKET s,
  __out    struct sockaddr *addr,
  __inout  LPINT addrlen,
  __in     LPCONDITIONPROC lpfnCondition,
  __in     DWORD dwCallbackData
);

lpfnCondition - 可选的,应用程序指定的条件函数的地址,它将根据作为参数传入的调用者信息做出接受/拒绝决定,并可选择通过为其分配适当的值来创建或加入套接字组。该函数的结果参数g。如果此参数为NULL,则不调用条件函数。

对于 linux 解决方案,请看:GNU Common C ++ - TCPSocket类,它有onAccept()和reject()方法。

virtual bool TCPSocket::onAccept    (       const InetHostAddress &      ia,
        tpport_t    port
    )   [inline, protected, virtual]

调用派生的TCPSocket类的方法,该类在接受连接请求时充当服务器。

服务器可以实现协议特定规则,以通过返回false来排除远程套接字被接受。 Peek方法也可用于此目的。


但是,如果前置条件为假,您可以在接受后关闭套接字:)

答案 2 :(得分:1)

TCP Wrapper在类UNIX平台上变得非常普遍。是的,仅在 accept之后检查连接;但是,如果你正在这样做,你也可以使用与其他人一样的配置。

从本质上讲,您的程序可以使用tcpd运行,也可以直接修改为使用libwrap,如下所示:

#include <tcpd.h>
connfd = accept(listenfd, (struct sockaddr *)&addr, &addrlen);
if (!hosts_ctl("my_program", STRING_UNKNOWN, inet_ntoa(addr.sin_addr), STRING_UNKNOWN)) {
    fprintf(stderr, "Client %s connection disallowed\n", inet_ntoa(addr.sin_addr));
    close(connfd);
}

然后根据您的要求配置/etc/hosts.allow/etc/hosts.deny,例如

# /etc/hosts.allow
my_program: 127.0.0.1 10. 192.168.

# /etc/hosts.deny
my_program: ALL

这会导致my_program拒绝来自非本地地址的所有连接尝试,但可以在不触及my_program的情况下进行更改。

答案 3 :(得分:-1)

如果您正在使用NAT,则不接受基于IP地址的连接的概念将无效。