What client-side Linux / Liberty / HttpComponents configuration can prevent requests from being mis-identified as Small Window Attacks?

huangapple go评论75阅读模式
英文:

What client-side Linux / Liberty / HttpComponents configuration can prevent requests from being mis-identified as Small Window Attacks?

问题

Citrix已经确认了我们正在经历的TCP通信问题,原因是在客户端和服务器之间的NetScaler负载均衡器上启用了TCP Small Window Attack Protection (TCP-SWAP)。负载均衡器将不定期丢弃TCP连接,Citrix和文章建议禁用TCP-SWAP。由于NetScaler用于除我的系统流量之外的其他系统流量,禁用此设置可能会引发全局事件,并使NetScaler面临潜在的Small Window攻击。

禁用TCP-SWAP的替代方法是确保客户端请求不被分类为Small Window Attacks。

受影响的特定客户端通过NetScaler向服务器发送多部分请求。这些请求包括头部、XML部分和文件部分,它们之间由标准生成的边界分隔。NetScaler不定期地将某些附件大小为62-66kb的请求标记为Small Window Attacks,并阻止服务器接收请求的最后部分。随后的相同请求(包括使用相同的边界)会成功;这种情况无法按需复制,但可以通过大量复制。

在被视为Small Window Attack的合格场景中,整个客户端请求被传递到负载均衡器,然后客户端等待服务器响应。服务器接收到头部、XML部分和文件部分的大约50%后,等待请求文件的其余部分。负载均衡的NetScaler从未传输文件的其余部分。客户端和服务器最终因等待超时而中断。

客户端和服务器两侧的代码审查未发现代码问题。将NetScaler从通信路径中移除后,问题得以解决;当它不再位于客户端和服务器之间时,一段时间内没有问题。不幸的是,负载均衡器是必需的。

问题在于由于TCP-SWAP,NetScaler将客户端请求错误地分类为Small Window Attacks,从而阻止服务器接收请求的最后部分。除了在NetScaler上禁用TCP-SWAP外,客户端可以采取什么措施来防止请求被识别为Small Window Attacks

客户端是在Linux上运行的Java 8(IBM SDK 8.0-6.11-linux-x86_64)应用程序,使用IBM Liberty(WAS Liberty 20.0.0.7),并使用org.apache.httpcomponents.httpclient通过PoolingHttpClientConnectionManager进行通信,具有标准的超时、安全和连接管理设置。是否有配置设置可以应用于Liberty或HttpComponents,以防止将请求标识为Small Window Attacks

以下是代码示例;这是一个非典型的示例:

public HttpResponse post(URL url, Map<String, Object> parameterMap) throws Exception {

    HttpPost httpPost = new HttpPost(url.toString());

    MultipartEntityBuilder builder = MultipartEntityBuilder.create();

    for (Map.Entry<String, Object> entry : parameterMap.entrySet()) {

        if (entry.getValue() instanceof String) {

            builder.addTextBody(entry.getKey(), (String) entry.getValue());

        } else {

            String partName = getNextPartName();

            if (entry.getValue() instanceof File) {

                builder.addBinaryBody(partName, (File) entry.getValue(), ContentType.APPLICATION_OCTET_STREAM, entry.getKey());

            } else if (entry.getValue() instanceof InputStream) {

                builder.addBinaryBody(partName, (InputStream) entry.getValue(), ContentType.APPLICATION_OCTET_STREAM, entry.getKey());

            } else if (entry.getValue() instanceof byte[]) {

                builder.addBinaryBody(partName, (byte[]) entry.getValue(), ContentType.APPLICATION_OCTET_STREAM, entry.getKey());

            } else {

                throw new IllegalArgumentException("Cannot attach entry " + entry.getKey() + " with Object of class " + entry.getValue().getClass().getName());
            }
        }
    }

    httpPost.setEntity(builder.build());

    return new HttpResponseImpl(getClient().execute(httpPost), httpPost);
}
英文:

Citrix has identified a TCP communication issue we are experiencing as due to active TCP Small Window Attack Protection (TCP-SWAP) on the NetScaler load balancer between the client and servers. The load balancer will intermittently drop TCP connections and the advice from Citrix/the article is to disable TCP-SWAP. As the NetScaler is used for other system traffic besides mine, disabling this setting may create a global incident and expose the NetScaler to potential Small Window Attacks.

An alternative to disabling TCP-SWAP would be to ensure the client requests are not classified as Small Window Attacks.

The particular affected client sends multi-part requests over the NetScaler to the servers. The requests are headers, an XML part and a file part, separated by standard generated boundaries. NetScaler is intermittently flagging certain requests with attachments sized 62-66kb as Small Window Attacks, and are preventing the last part of the request to be received by the server. Subsequent identical requests (including using the same boundaries) succeed; the scenario is impossible to replicate on demand, but can be replicated with volume.

During a qualifying scenario where the request is treated as a Small Window Attack, the entire client request is passed to the load balancer, then the client pends for a server response. The server receives the header, XML part and ~50% of the file part, then pends for the rest of the request file part. The load balancing NetScaler never transmits the rest of the file part. The client and server ultimately time-out waiting.

Code reviews on the client and server sides reveal no issues with the code. Removing the NetScaler from the communication path fixed the problem; there were no issues for an extended timespan when it was no longer between the client and servers. Unfortunately, the load balancer is required.

The issue is that client requests are being mis-classified as Small Window Attacks by the NetScaler due to TCP-SWAP, which prevents the server from receiving the final part of the request. Other than disabling TCP-SWAP on the NetScaler, what can the client change to prevent requests from being classified as Small Window Attacks?

The client is a Java 8 (IBM SDK 8.0-6.11-linux-x86_64) application running under IBM Liberty (WAS Liberty 20.0.0.7) on Linux (Oracle Linux Server 7.8), and it uses org.apache.httpcomponents.httpclient to communicate via PoolingHttpClientConnectionManager with normal settings for timeout, security and connection management. Is there a configuration setting to apply to either Liberty or HttpComponents to prevent requests from being identified as Small Window Attacks?

The post code follows; it is atypical:

public HttpResponse post(URL url, Map&lt;String, Object&gt; parameterMap) throws Exception {
HttpPost httpPost = new HttpPost(url.toString());
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
for (Map.Entry&lt;String, Object&gt; entry : parameterMap.entrySet()) {
if (entry.getValue() instanceof String) {
builder.addTextBody(entry.getKey(), (String)entry.getValue());
} else {
String partName = getNextPartName();
if (entry.getValue() instanceof File) {
builder.addBinaryBody(partName, (File)entry.getValue(), ContentType.APPLICATION_OCTET_STREAM, entry.getKey());
} else 
if (entry.getValue() instanceof InputStream) {
builder.addBinaryBody(partName, (InputStream)entry.getValue(), ContentType.APPLICATION_OCTET_STREAM, entry.getKey());
} else 
if (entry.getValue() instanceof byte[]) {
builder.addBinaryBody(partName, (byte[])entry.getValue(), ContentType.APPLICATION_OCTET_STREAM, entry.getKey());
} else {
throw new IllegalArgumentException(&quot;Cannot attach entry &quot; + entry.getKey() + &quot; with Object of class &quot; + entry.getValue().getClass().getName());
}
}
}
httpPost.setEntity(builder.build());			
}
return new HttpResponseImpl(getClient().execute(httpPost), httpPost);
}

答案1

得分: 1

假设您实际上并未遭受TCP小窗口攻击,那么您的TCP窗口大小如此小的事实表明,最可能的问题是客户端的Linux内核认为自己承受压力,正在启用流量控制(即设置小窗口)。我建议您调查客户端网络堆栈是否进行了良好的调整并且未过载;否则,您可以尝试不同的拥塞控制算法或其他拥塞窗口调整。例如:链接

英文:

Assuming you're not actually under a TCP small window attack, then the fact that your TCP window size is so small suggests the most likely issue is that the client-side Linux kernel is deciding that it's under pressure and activating flow control (i.e. setting a small window). I suggest investigating whether your client network stack is well tuned and unsaturated; otherwise, you might try different congestion control algorithms or other cwnd tuning. For example: https://publib.boulder.ibm.com/httpserv/cookbook/Operating_Systems-Linux.html#Operating_Systems-Linux-Networking-TCP_Congestion_Control

huangapple
  • 本文由 发表于 2020年9月10日 06:07:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/63820178.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定