From 2674e4c35bdb1763cbe22e2ff52a960225153452 Mon Sep 17 00:00:00 2001 From: wiegratz Date: Mon, 18 Mar 2024 15:00:45 +0000 Subject: [PATCH] feat: add synproxy statement and list object also mark some other statements that are missing. compare with nftables json_parse_stmt: https://git.netfilter.org/nftables/tree/src/parser_json.c?id=c4c740117f6fbf39dd67dd87635ea8b497718ad7#n2884 --- src/schema.rs | 29 +++++++++++++++++++++++++++++ src/stmt.rs | 27 +++++++++++++++++++++++++-- src/types.rs | 11 +++++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/schema.rs b/src/schema.rs index d32a250..dfdca7e 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -42,6 +42,7 @@ pub enum NfListObject { CTTimeout(CTTimeout), #[serde(rename = "ct expectation")] CTExpectation(CTExpectation), + SynProxy(SynProxy), } #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] @@ -435,3 +436,31 @@ pub struct CTExpectation { #[serde(skip_serializing_if = "Option::is_none")] pub size: Option, } + +/// [SynProxy] intercepts new TCP connections and handles the initial 3-way handshake using +/// syncookies instead of conntrack to establish the connection. +/// +/// Named SynProxy requires **nftables 0.9.3 or newer**. +/// +/// [SynProxy]: https://wiki.nftables.org/wiki-nftables/index.php/Synproxy +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +pub struct SynProxy { + /// The table’s family. + pub family: NfFamily, + /// The table’s name. + pub table: String, + /// The synproxy's name. + pub name: String, + #[serde(skip_serializing_if = "Option::is_none")] + /// The synproxy's handle. For input, it is used by the [delete command][NfCmd::Delete] only. + pub handle: Option, + #[serde(skip_serializing_if = "Option::is_none")] + /// The maximum segment size (must match your backend server). + pub mss: Option, + #[serde(skip_serializing_if = "Option::is_none")] + /// The window scale (must match your backend server). + pub wscale: Option, + #[serde(skip_serializing_if = "Option::is_none")] + /// The synproxy's [flags][crate::types::SynProxyFlag]. + pub flags: Option>, +} diff --git a/src/stmt.rs b/src/stmt.rs index 74ce7bd..1a15c3b 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use strum_macros::EnumString; -use crate::types::RejectCode; +use crate::types::{RejectCode, SynProxyFlag}; use crate::visitor::single_string_to_option_hashset_logflag; use crate::expr::Expression; @@ -36,8 +36,10 @@ pub enum Statement { #[serde(rename = "quota")] /// reference to a named quota object QuotaRef(String), + // TODO: last Limit(Limit), + // TODO: flow FWD(Option), /// Disable connection tracking for the packet. Notrack, @@ -48,6 +50,7 @@ pub enum Statement { Redirect(Option), // redirect is subset of NAT options Reject(Option), Set(Set), + // TODO: map Log(Option), #[serde(rename = "ct helper")] @@ -57,6 +60,7 @@ pub enum Statement { Meter(Meter), Queue(Queue), #[serde(rename = "vmap")] + // TODO: vmap is expr, not stmt! VerdictMap(VerdictMap), #[serde(rename = "ct count")] @@ -73,9 +77,12 @@ pub enum Statement { /// This represents an xt statement from xtables compat interface. /// Sadly, at this point, it is not possible to provide any further information about its content. XT(Option), - + /// A netfilter synproxy intercepts new TCP connections and handles the initial 3-way handshake using syncookies instead of conntrack to establish the connection. + SynProxy(SynProxy), /// Redirects the packet to a local socket without changing the packet header in any way. TProxy(TProxy), + // TODO: reset + // TODO: secmark } #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] @@ -432,6 +439,22 @@ pub struct CTCount { pub inv: Option, } +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +/// Limit the number of connections using conntrack. +/// +/// Anonymous synproxy was requires **nftables 0.9.2 or newer**. +pub struct SynProxy { + #[serde(skip_serializing_if = "Option::is_none")] + /// maximum segment size (must match your backend server) + pub mss: Option, + #[serde(skip_serializing_if = "Option::is_none")] + /// window scale (must match your backend server) + pub wscale: Option, + #[serde(skip_serializing_if = "Option::is_none")] + /// The synproxy's [flags][crate::types::SynProxyFlag]. + pub flags: Option>, +} + #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] /// Redirects the packet to a local socket without changing the packet header in any way. diff --git a/src/types.rs b/src/types.rs index 74a08ad..1b75b05 100644 --- a/src/types.rs +++ b/src/types.rs @@ -90,3 +90,14 @@ pub enum RejectCode { /// Address unreachable (ICMPv6) AddrUnreach, } + +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] +#[serde(rename_all = "lowercase")] +/// Describes a SynProxy's flags. +pub enum SynProxyFlag { + /// Pass client timestamp option to backend. + Timestamp, + #[serde(rename = "sack-perm")] + /// Pass client selective acknowledgement option to backend. + SackPerm, +}