![在接受 TCP 连接之前是否可以检查对等地址?](https://linux22.com/image/226424/%E5%9C%A8%E6%8E%A5%E5%8F%97%20TCP%20%E8%BF%9E%E6%8E%A5%E4%B9%8B%E5%89%8D%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E6%A3%80%E6%9F%A5%E5%AF%B9%E7%AD%89%E5%9C%B0%E5%9D%80%EF%BC%9F.png)
我编写了一个简单的 Perl 服务器,它侦听 TCP 端口/套接字并接受连接。现在我想知道:
当想要实现基于地址的访问控制时,是否可以在接受连接之前检查请求连接的对等方的地址?
如果可能的话,我可以拒绝连接请求(我希望),而不是接受连接并立即再次关闭它。
答案1
TCP/IP 连接由内核建立,然后您的应用程序开始使用该连接。
过滤/阻止不需要的连接的唯一方法是使用内核防火墙。您还没有指定您的操作系统,但在 Linux 中,这将是 iptables/nftables。
答案2
并不是真正的答案,但一些评论太长了:
在 MacOS X 上man accept
说:
通过发出 msg_iovlen 为 0 且 msg_controllen 非零的 recvmsg(2) 调用,无需确认连接即可获取用户连接请求数据,或通过发出 getsockopt(2) 请求。类似地,可以通过发出仅提供控制信息的 sendmsg(2) 调用或通过调用 setsockopt(2) 来提供用户连接拒绝信息。
(强调我的)
但无法在 或man recvmsg
有关该主题的更多详细信息中找到。man getsockopt
man tcp
在 Debian 上,man accept
说道:
为了获得套接字上传入连接的通知,可以使用 select(2)、poll(2) 或 epoll(7)。当尝试新连接时,将传递一个可读事件,然后您可以调用accept()来获取该连接的套接字。或者,您可以将套接字设置为在套接字上发生活动时传递 SIGIO;详细信息请参见套接字(7)。
恕我直言,那里是唯一一个可能能够提供更多信息就可以了epoll
。
但即使您实际上可以获得信息,我也不太确定如果您不喜欢它,您将如何拒绝连接。
您最好在网络堆栈/防火墙级别(iptables 和朋友)进行过滤。
答案3
我并不声称拥有 Perl 方面的任何专业知识 - 但我怀疑这是不可能的。为了控制对服务器的访问,我会限制(按优先顺序):
- 通过接口/绑定地址
- 通过内核防火墙(iptables、nftables、eBPF)
- 通过 TCP 包装器或主机配置
鉴于目前不存在通过主机配置进行限制的设施,显然选择此作为起点似乎不寻常。
假设上面的1和2是不是一个选项,那么我建议使用 Perl 代码中的 TCP 包装器。这应该可以让您以最少的代码更改启动并运行,同时利用灵活、标准和强大的网络访问控制机制。也可以看看https://metacpan.org/pod/Net::TCPwrappers
我相信它也可以通过在运行时调整 LD_LIBRARY_PATH (即没有任何代码更改)来应用 tcp 包装器,但在快速 Google 搜索中找不到对此的引用。
答案4
传输控制协议不用于访问控制。
我建议你检查 TLShttps://en.m.wikipedia.org/wiki/Transport_Layer_Security
此外,看看 netfilter 防火墙输入挂钩。您可以删除和拒绝不需要的对等方。