Traffic: исправить детект ingress redirect для реального вывода tc

has_ingress_redirect_to_ifb переведён на case-insensitive разбор и поддержку обоих вариантов: dev <ifb> и device <ifb>. Добавлены тесты на lowercase dev-формат и отрицательный кейс с другим ifb.

Также синхронизирован docs/ANTI_TORRENT.md: единая шкала threshold (100 default, 150 мягче, 200/250 permissive, 70 агрессивный), и антипример over 200 явно помечен как non-default/non-production.
This commit is contained in:
2026-05-10 18:07:05 +05:00
parent b83f2ee3a9
commit a4bb7adb4f
2 changed files with 28 additions and 9 deletions
+5 -5
View File
@@ -10,7 +10,7 @@
## 2. Важное исправление к простой команде
Не использовать такую форму как production rule:
Не использовать такую форму как production rule (это антипример; `200` здесь не default и не production-рекомендация):
```nft
nft add rule inet filter forward ip saddr 10.8.1.0/24 ct count over 200 drop
@@ -75,10 +75,10 @@ max_connections_per_peer = 100
Практические варианты:
- `150` — агрессивнее, больше риск задеть редкие легитимные сценарии.
- `100` — production default.
- `150` — мягче и более permissive при редких жалобах.
- `200/250` — ещё более permissive варианты, если нужно дополнительно снизить риск false positives.
- `100` — production default, более строгий режим.
- `150` — мягче, если есть жалобы на false positives.
- `200/250` — ещё более permissive варианты.
- `70` — агрессивный режим только после наблюдения реального трафика.
## 5. Почему это должно быть в orchestrator
+23 -4
View File
@@ -575,11 +575,16 @@ fn has_fq_codel_for_parent(raw_qdisc: &str, parent_class: &str) -> bool {
}
fn has_ingress_redirect_to_ifb(output: &str, ifb_name: &str) -> bool {
let ifb_lower = ifb_name.to_ascii_lowercase();
let needle_dev = format!("dev {ifb_lower}");
let needle_device = format!("device {ifb_lower}");
output.lines().any(|line| {
line.contains("mirred")
&& line.contains("redirect")
&& line.contains(&format!("dev {ifb_name}"))
}) || output.contains(&format!("redirect dev {ifb_name}"))
let l = line.to_ascii_lowercase();
l.contains("mirred")
&& l.contains("redirect")
&& (l.contains(&needle_dev) || l.contains(&needle_device))
})
}
fn link_is_up(output: &str) -> bool {
@@ -1030,6 +1035,20 @@ mod tests {
assert!(has_ingress_redirect_to_ifb(raw, "ifb0"));
}
#[test]
fn detects_ingress_redirect_to_ifb_dev_format_lowercase() {
let raw =
"filter parent ffff: protocol all pref 1 u32\n action order 1: mirred egress redirect dev ifb0";
assert!(has_ingress_redirect_to_ifb(raw, "ifb0"));
}
#[test]
fn does_not_match_redirect_to_other_ifb() {
let raw =
"filter parent ffff: protocol all pref 1 u32\n action order 1: mirred (Egress Redirect to device ifb1) stolen";
assert!(!has_ingress_redirect_to_ifb(raw, "ifb0"));
}
#[test]
fn detects_ifb_up_state() {
assert!(link_is_up(