带有Tomcat的JSR-356 WebSockets - 如何限制单个IP地址内的连接?

Pio*_*ler 6 java tomcat servlets websocket jsr356

我制作了一个JSR-356 @ServerEndpoint,其中我想限制来自单个IP地址的活动连接,以防止简单的DDOS攻击.

请注意,我正在搜索Java解决方案(JSR-356,Tomcat或Servlet 3.0规范).

我尝试过自定义端点配置程序,但即使在HandshakeRequest对象中也无法访问IP地址.

如何在没有iptables等外部软件的情况下限制单个IP地址的JSR-356连接数?

ant*_*tix 11

根据Tomcat开发人员@mark-thomas客户端IP 没有通过JSR-356公开,因此用纯JSR-356 API-s实现这样的功能是不可能的.

你必须使用一个相当丑陋的黑客来解决标准的限制.

需要做的事情归结为:

  1. 在初始请求时(在websocket握手之前)为每个用户生成包含其IP的令牌
  2. 将令牌传递到链中,直到它到达端点实现

至少有两个hacky选项可以实现这一目标.

使用HttpSession

  1. 使用a监听传入的HTTP请求 ServletRequestListener
  2. 调用request.getSession()传入请求以确保它具有会话并将客户端IP存储为会话属性.
  3. 创建一个ServerEndpointConfig.Configurator提升客户端IP HandshakeRequest#getHttpSessionEndpointConfig使用该modifyHandshake方法将其作为用户属性附加到其中.
  4. EndpointConfig用户属性获取客户端IP ,将其存储在映射或其他任何位置,并在每个IP的会话数超过阈值时触发清理逻辑.

您也可以使用@WebFilter而不是ServletRequestListener

请注意,除非您的应用程序已使用会话(例如用于身份验证),否则此选项的资源消耗较高.

将IP作为URL中的加密令牌传递

  1. 创建一个附加到非websocket入口点的servlet或过滤器.例如/mychat
  2. 获取客户端IP,使用随机盐和密钥对其进行加密以生成令牌.
  3. 用于ServletRequest#getRequestDispatcher将请求转发给/mychat/TOKEN
  4. 配置端点以使用路径参数,例如 @ServerEndpoint("/mychat/{token}")
  5. 提升令牌@PathParam并解密以获取客户端IP.将其存储在地图或其他任何位置,并在每个IP的会话数超过阈值时触发清理逻辑.

为了便于安装,您可能希望在应用程序启动时生成加密密钥.

请注意,即使您正在进行客户端不可见的内部调度,您也需要加密IP.没有任何东西可以阻止攻击者/mychat/2.3.4.5直接连接,从而欺骗客户端IP(如果它没有加密).

也可以看看: