【问题标题】:Jetty Hook for TCP/IP connection early revocation (avoiding accept())用于 TCP/IP 连接提前撤销的 Jetty Hook(避免 accept())
【发布时间】:2015-06-28 20:23:33
【问题描述】:

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

我的想法是,我会在那个钩子上附加一个软件和平,对于每个传入的连接都可以说:接受/撤销。 撤销后,传入的连接将被忽略,并且套接字将保持关闭状态,从而避免 Jetty 容器在其上做更多的工作/使用资源。

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

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

我在 ServerConnector 类(open/close/accept/...)上找到了典型的 TCP/IP 套接字接口,但我没有找到可以注册 pre-accept() 挂钩或回调的地方。我还查看了 ServerConnector 的类祖先,但我也没有真正看到任何类似的东西。我从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 对象的一个​​简单方法,返回 true 或 false。

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

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

非常感谢。

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

【问题讨论】:

    标签: security jetty hook tcp-ip connector


    【解决方案1】:

    你有大量的工作等着你。

    为此,您基本上必须为 Java 提供自己的Socket 实现层。在 Jetty 中没有任何层可以让你做任何你提到的事情。您想要做的事情的种类要低得多,在 JVM 和/或操作系统级别。

    您需要处理java.net.Socketjava.net.ServerSocketjava.nio.channels.ServerSocketChannel

    这意味着您将为常规套接字编写自己的 javax.net.ServerSocketFactoryjavax.net.SocketFactoryjava.net.SocketImpljava.net.SocketImplFactory

    对于 SSL/TLS,您需要编写/处理/管理自己的 javax.net.ssl.SSLSocketjavax.net.ssl.SSLServerSocketjavax.net.ssl.SSLSocketFactoryjavax.net.ssl.SSLServerSocketFactory

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

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

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

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

    或者...

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

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

    【讨论】:

    • Joakim,谢谢,但这不是我力所能及的解决方案。出于显而易见的原因,我想留在标准码头。随着时间的推移,我无法维护我自己的上述类版本,更不用说以 Jetty 团队可以做到的质量生产它们了。我会/可能会失去使用 Jetty 的所有优势,因为我可能会危及它的健壮性、速度等。如果遇到问题,我总是想知道我是否没有因为我在这些课程中自己创建的问题而使 stackoverflow 变得混乱。
    • 我推荐的任何东西都不会破坏 Jetty 或导致它使用非标准的 Jetty。事实上,Jetty 代码几乎没有被触及。在 Jetty 参与之前,所有工作都将达到一个水平。
    • 好的,我明白了,您列出的类确实位于底层,可以说是在 java 级别。您建议的优点是套接字确实会保持关闭状态,并且接受队列(在设定的深度)不会受到过滤连接尝试的阻碍。我会调查一下,因为正如 greg 在他的解决方案中所说,用户代理仍然会看到一个打开+立即关闭。所以你的建议是更多的工作,但符合预期的功能。谢谢..
    【解决方案2】:

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

    或者,打开一个 Bugzilla 要求我们将接受的(套接字套接字)方法设置为受保护而不是私有,您可以在那里拒绝。

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

    【讨论】:

    • 格雷格,谢谢。我一直在考虑另一种选择,即创建一个继承 ServerConnector 并且只覆盖 accept(ID) 方法的类。撤销只是意味着不调用父类 accpet()。我认为如果不调用 accept() ,套接字将保持关闭状态。但是我担心后果,因为 accept() 方法返回 void 并且调用它的代码可能不会意识到套接字未被接受(通过背后的抑制),从而导致泄漏、挂起的分配和可能的抛出。然而,这会是一个解决方案吗?
    • 你错过了@gregw 所说的,java 和 jetty 仍然会接受,并且从操作系统和 java 级别的 tcp/ip 连接的角度来看是可以接受的。正是在这一点上,您应用您的逻辑并强制关闭连接或让 Jetty 处理它。这是 greg 建议的方法。
    猜你喜欢
    • 1970-01-01
    • 2020-01-12
    • 2013-01-15
    • 1970-01-01
    • 2015-02-27
    • 2014-06-28
    • 1970-01-01
    • 1970-01-01
    • 2022-08-08
    相关资源
    最近更新 更多