TCP/IP 连接提前撤销的 Jetty Hook(避免 accept())

Jetty Hook for TCP/IP connection early revocation (avoiding accept())

我正在寻找一个 Hook 允许我 tell/instruct ServerConnector(或 Jetty 架构中任何其他更合适的挂钩点的对象)不接受传入 TCP/IP基于远程方 IP 地址的 Web 服务器端口(例如:80 或 443)上的连接(因为这是在调用 accept() 之前可用的所有信息,在接受之后,HTTP 数据变得可用来自 TCP/IP 帧的负载)。

我的想法是,我会在那个挂钩上附加一个软件和平,对于每个传入连接都可以说:Accept/Revoke。 撤销传入连接将被忽略,套接字将保持关闭状态,避免 Jetty 容器在其上执行更多 work/use 资源。

它还可以通过仅接受例如本地地址 (10.32....) 等来保护某些服务器端口后的系统功能(例如特殊管理菜单)。它甚至可以更好的是还能够到达连接设备的 MAC 地址,并且仅当 MAC 地址在授权列表中时才允许访问(=用户可以物理访问 LAN 以连接他的设备否则他的 MAC 地址永远不会是在 LAN 上看到的地址,因为如果不在同一个 LAN 上,就没有对等 MAC 地址交换。

通过这种方式,我打算防止恶意连接消耗 CPU、带宽和套接字,只是为了在攻击期间向它们发送 'main' 页面并迫使它们等待超时。同时,它还允许保护对基于 'physical local access' 的非 public 功能的访问。挂钩软件甚至可以撤销部分IP地址的连接,例如中国IP地址范围等

我在 ServerConnector classes (open/close/accept/...) 上找到了典型的 TCP/IP 套接字接口,但我没有找到可以注册的地方pre-accept() 挂钩或回调。我还查看了 ServerConnector 的 class 祖先,但我也没有真正看到任何此类内容。我从 org.eclipse.jetty.server Class ServerConnector

开始

为了清楚起见,并且对于那些更熟悉代码的人来说,这在概念上代表了我所寻找的代码。

...setup Jetty server, Factories, etc

ServerConnector http2=new ServerConnector(this.oServer,sslF,alpnF,h2F,https2F);
http2.setPort(8443);

http2.setPreAcceptHook(8843, oMyHook); <---INVENTED line

this.oServer.addConnector(http2);

挂钩是 MyHook 对象的一个​​简单方法,returns true 或 false。

boolean AcceptRevoke(IP, Port) <--return true=accept, false=revoke

我欢迎任何关于查看方向的提示(class 名称左右)或确认此类功能不可用或不可能因此永远不会可用。容器设计中可能存在不允许预接受撤销的限制,就像那些可以使用套接字库所做的那样,我不知道,因此会寻找不可能的情况。

非常感谢。

产品和版本信息: 码头 9.3.0 (v20150612) alpn-boot-8.1.3 (v20150130) JRE 8(Oracle 1.8.0 Build 45 - b15)

你有很多工作在你面前。

为此,您基本上必须为 Java 提供自己的 Socket 实现层。在 Jetty 中没有可以挂接的层允许您执行您提到的任何事情。您想做的事情的级别要低得多,在 JVM and/or OS 级别。

您需要处理 java.net.Socket, java.net.ServerSocket, and java.nio.channels.ServerSocketChannel

这意味着您将为常规套接字编写自己的javax.net.ServerSocketFactory, javax.net.SocketFactory, java.net.SocketImpl, and java.net.SocketImplFactory

而对于 SSL/TLS,您需要 write/handle/manage 您自己的 javax.net.ssl.SSLSocket, javax.net.ssl.SSLServerSocket, javax.net.ssl.SSLSocketFactory, and javax.net.ssl.SSLServerSocketFactory

并且不要忘记将所有 jetty-alpn 代码添加到标准 OpenJDK SSL 库中,这样您就可以 HTTP/2 为您工作(因为您显然正在使用它,根据您的问题详细信息)

在 Jetty 上进行测试之前,先在简单的 ServerSocket 和 ServerSocketChannel 设置上测试您的实现。

在您确认它可以满足您的要求后,您需要将它连接到 Jetty 中。对于普通的 ServerSocket / ServerSocketChannel,您必须在系统范围内使用 java.nio.channels.spi.SelectorProvider

对于 SSLServerSocket / SSLServerSocketChannel,您将通过您自己的 custom/overridden org.eclipse.jetty.util.ssl.SslContextFactory 实现来连接它。

或者...

您可以结合使用 post-accept 逻辑(内置于 Jetty 中)和 OS 级别的连接管理(例如 iptables),这样会简单得多。

您所说的在接受之前挂钩到一个点的要求对于 Java 服务器是可能的,但这是一种特殊的努力,您可以扩展核心 Java 网络和套接字行为。

作为替代方案,您可能只重写 ServerConnector 的 configure(Socket socket) 方法。如果要拒绝套接字,只需关闭连接即可。这可能会导致一些奇怪的异常,如果是这样,请在 Bugzilla 中报告它们,我们将进行清理。

或者,打开 Bugzilla 要求我们将 accepted(Socket socket) 方法设为受保护的而不是私有的,您可以在那里拒绝。

请注意,使用其中任何一个,客户端都会看到连接已被接受,然后立即关闭。