From c93a4036842427d6241d646e4b23b41d673f16dd Mon Sep 17 00:00:00 2001 From: Hongliang Liu Date: Thu, 12 Dec 2024 18:44:40 +0800 Subject: [PATCH] Fix default reject rule to correctly handle packets that should be reassembled When using an L7 NetworkPolicy that allows egress HTTP requests, the corresponding Suricata rules may look like the following example: ``` reject ip any any -> any any (msg: "Reject by AntreaNetworkPolicy:default/egress-allow-http"; flow: to_server, established; sid: 1;) pass http any any -> any any (msg: "Allow http by AntreaNetworkPolicy:default/egress-allow-http"; http.method; content:"GET"; sid: 2;)` ``` If an HTTP request exceeds the MTU, it will be split into multiple packets. The packets should be reassembled and allowed by the corresponding Suricata rule for the L7 NetworkPolicy. However, there is a default reject rule which is to reject packets which are not matched by the `pass` rule, which will take effect before packets are reassembled and matched by the `pass` rule, causing the connection to fail. To address the issue, the keyword `only_stream` is added to the default reject rule. This ensures that only reassembled packets are matched, preventing premature rejection of packets that should be allowed after reassembly. Signed-off-by: Hongliang Liu --- pkg/agent/controller/networkpolicy/l7engine/reconciler.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/agent/controller/networkpolicy/l7engine/reconciler.go b/pkg/agent/controller/networkpolicy/l7engine/reconciler.go index 40ff2ffa854..2b9295eccd7 100644 --- a/pkg/agent/controller/networkpolicy/l7engine/reconciler.go +++ b/pkg/agent/controller/networkpolicy/l7engine/reconciler.go @@ -173,8 +173,10 @@ func generateTenantRulesData(policyName string, protoKeywords map[string]sets.Se rulesData := bytes.NewBuffer(nil) sid := 1 - // Generate default reject rule. - allKeywords := fmt.Sprintf(`msg: "Reject by %s"; flow: to_server, established; sid: %d;`, policyName, sid) + // Generate default reject rule. The keyword `only_stream` is used to match on packets that have been reassembled by + // the Suricata stream engine. Without this keyword, reassembled packets, such as those from HTTP requests split + // across multiple packets, would be rejected by the default rule, causing an otherwise allowed connection to fail. + allKeywords := fmt.Sprintf(`msg: "Reject by %s"; flow: to_server, established, only_stream; sid: %d;`, policyName, sid) rule := fmt.Sprintf("reject ip any any -> any any (%s)\n", allKeywords) rulesData.WriteString(rule) sid++