@push.rocks/smartnftables 2.5.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +31 -0
- package/dist_rust/smartnftables_linux_amd64_musl +0 -0
- package/dist_rust/smartnftables_linux_amd64_musl.tsrust-build.json +5 -5
- package/dist_rust/smartnftables_linux_arm64_musl +0 -0
- package/dist_rust/smartnftables_linux_arm64_musl.tsrust-build.json +5 -5
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/managed.egress.types.d.ts +69 -3
- package/package.json +6 -6
- package/readme.md +342 -61
- package/rust/src/egress.compile.rs +157 -76
- package/rust/src/egress.host.rs +104 -44
- package/rust/src/egress.hostgrant.rs +14 -14
- package/rust/src/egress.keys.rs +305 -0
- package/rust/src/egress.leased.rs +399 -0
- package/rust/src/egress.poolguard.rs +45 -0
- package/rust/src/egress.private.rs +197 -0
- package/rust/src/egress.published.rs +370 -0
- package/rust/src/egress.router.rs +64 -295
- package/rust/src/egress.rs +248 -17
- package/rust/src/egress.workloadgrant.rs +88 -0
- package/rust/src/egress_hostgrant_tests.rs +196 -47
- package/rust/src/egress_localplatform_tests.rs +204 -0
- package/rust/src/egress_localport_tests.rs +266 -0
- package/rust/src/egress_publishedrange_tests.rs +812 -0
- package/rust/src/egress_routerequivalence_tests.rs +448 -0
- package/rust/src/egress_tests.rs +132 -230
- package/rust/src/egress_workloadgrant_tests.rs +313 -0
- package/rust/src/owner.rs +77 -15
- package/rust/src/owner_host_traffic_tests.rs +4 -0
- package/rust/src/owner_hostgrant_traffic_tests.rs +9 -4
- package/rust/src/owner_identity_tests.rs +228 -80
- package/rust/src/owner_localplatform_tests.rs +274 -0
- package/rust/src/owner_localport_tests.rs +241 -0
- package/rust/src/owner_publishedrange_traffic_tests.rs +306 -0
- package/rust/src/owner_router_traffic_tests.rs +2 -0
- package/rust/src/owner_scale_traffic_tests.rs +383 -0
- package/rust/src/owner_tests.rs +15 -0
- package/rust/src/owner_workloadgrant_tests.rs +278 -0
- package/rust/src/policy.rs +29 -25
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/managed.egress.types.ts +71 -3
package/rust/src/policy.rs
CHANGED
|
@@ -90,12 +90,37 @@ fn covers(parent: &str, child: &str) -> Result<bool> {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
impl Policy {
|
|
93
|
-
pub fn prepare(
|
|
93
|
+
pub fn prepare(self) -> Result<Prepared> {
|
|
94
|
+
let policy = self.normalize(32, 128)?;
|
|
95
|
+
let digest = format!(
|
|
96
|
+
"sha256:{:x}",
|
|
97
|
+
Sha256::digest(serde_json::to_vec(&policy).map_err(|_| Error::Invalid)?)
|
|
98
|
+
);
|
|
99
|
+
let prepared = Prepared { policy, digest };
|
|
100
|
+
// Compile during preparation; an oversized native batch never reaches the kernel.
|
|
101
|
+
let program = prepared.program(&format!("snft_{}", "x".repeat(59)))?;
|
|
102
|
+
// Reserve enough of the batch for deleting a previous maximum
|
|
103
|
+
// graph, then installing this complete graph in the same transaction.
|
|
104
|
+
if program.len() > 768
|
|
105
|
+
|| program
|
|
106
|
+
.iter()
|
|
107
|
+
.map(|(_, attrs)| wire::encode_attrs(attrs).len() + 20)
|
|
108
|
+
.sum::<usize>()
|
|
109
|
+
> 100_000
|
|
110
|
+
{
|
|
111
|
+
return Err(Error::Invalid);
|
|
112
|
+
}
|
|
113
|
+
Ok(prepared)
|
|
114
|
+
}
|
|
115
|
+
/// Validates and orders the endpoints and rules. Schema v1 compiles one rule
|
|
116
|
+
/// per endpoint and grant, so it admits 32 endpoints and 128 rules; the
|
|
117
|
+
/// set-backed router scope of schema v2 admits more.
|
|
118
|
+
pub(crate) fn normalize(mut self, endpoints: usize, rules: usize) -> Result<Self> {
|
|
94
119
|
if self.schema_version != 1
|
|
95
120
|
|| self.revision == 0
|
|
96
121
|
|| self.revision > 9_007_199_254_740_991
|
|
97
|
-
|| self.endpoints.len() >
|
|
98
|
-
|| self.rules.len() >
|
|
122
|
+
|| self.endpoints.len() > endpoints
|
|
123
|
+
|| self.rules.len() > rules
|
|
99
124
|
{
|
|
100
125
|
return Err(Error::Invalid);
|
|
101
126
|
}
|
|
@@ -185,28 +210,7 @@ impl Policy {
|
|
|
185
210
|
}
|
|
186
211
|
}
|
|
187
212
|
}
|
|
188
|
-
|
|
189
|
-
"sha256:{:x}",
|
|
190
|
-
Sha256::digest(serde_json::to_vec(&self).map_err(|_| Error::Invalid)?)
|
|
191
|
-
);
|
|
192
|
-
let prepared = Prepared {
|
|
193
|
-
policy: self,
|
|
194
|
-
digest,
|
|
195
|
-
};
|
|
196
|
-
// Compile during preparation; an oversized native batch never reaches the kernel.
|
|
197
|
-
let program = prepared.program(&format!("snft_{}", "x".repeat(59)))?;
|
|
198
|
-
// Reserve enough of the batch for deleting a previous maximum
|
|
199
|
-
// graph, then installing this complete graph in the same transaction.
|
|
200
|
-
if program.len() > 768
|
|
201
|
-
|| program
|
|
202
|
-
.iter()
|
|
203
|
-
.map(|(_, attrs)| wire::encode_attrs(attrs).len() + 20)
|
|
204
|
-
.sum::<usize>()
|
|
205
|
-
> 100_000
|
|
206
|
-
{
|
|
207
|
-
return Err(Error::Invalid);
|
|
208
|
-
}
|
|
209
|
-
Ok(prepared)
|
|
213
|
+
Ok(self)
|
|
210
214
|
}
|
|
211
215
|
}
|
|
212
216
|
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -60,9 +60,14 @@ export interface IManagedNftEgressGenerationV2 extends IManagedNftHandoffAllocat
|
|
|
60
60
|
* `transitSourceAddress:transitPort`, this translates on to the workload. */
|
|
61
61
|
export interface IManagedNftRouterPublishedPortV2 {
|
|
62
62
|
protocol: 'tcp' | 'udp';
|
|
63
|
-
/** Published handoff port, 1–65535
|
|
64
|
-
* It is the `targetPort` of the matching host-transit publication. */
|
|
63
|
+
/** Published handoff port, 1–65535; published ports never overlap per protocol across the
|
|
64
|
+
* scope. It is the `targetPort` of the matching host-transit publication. */
|
|
65
65
|
transitPort: number;
|
|
66
|
+
/** Optional last port of a published range `transitPort..transitPortEnd`, greater than
|
|
67
|
+
* `transitPort`. A range keeps every port, so `endpointPort` must equal `transitPort`; like one
|
|
68
|
+
* port it is one interval set element per set, and its translation keeps the port. Absent for
|
|
69
|
+
* one port, which is its only canonical form. */
|
|
70
|
+
transitPortEnd?: number;
|
|
66
71
|
endpointPort: number;
|
|
67
72
|
/** Exact current workload endpoint address behind one veth endpoint of this
|
|
68
73
|
* scope. Never a router-local address, a gateway or a platform endpoint. */
|
|
@@ -70,6 +75,12 @@ export interface IManagedNftRouterPublishedPortV2 {
|
|
|
70
75
|
/** Exact leased transit source address of one current generation, present on
|
|
71
76
|
* `handoff`. No wildcard, secondary-address or route inference. */
|
|
72
77
|
transitSourceAddress: string;
|
|
78
|
+
/** Optional: the workload may open flows from `endpointAddress` and its published endpoint
|
|
79
|
+
* port(s) toward unprotected space, source-translated to `transitSourceAddress` and the
|
|
80
|
+
* published transit port (a range keeps the port). The protected union stays denied, and its
|
|
81
|
+
* endpoint ports may not overlap another publication's on the same address. Absent and
|
|
82
|
+
* `false` are the same canonical policy. */
|
|
83
|
+
symmetric?: boolean;
|
|
73
84
|
}
|
|
74
85
|
|
|
75
86
|
/** One exact host-origin flow: the node's own host network namespace dials one port of one local
|
|
@@ -88,6 +99,22 @@ export interface IManagedNftHostGrant {
|
|
|
88
99
|
destinationPort: number;
|
|
89
100
|
}
|
|
90
101
|
|
|
102
|
+
/** One stateful one-way flow between two workloads behind the same router: the source workload opens
|
|
103
|
+
* connections to one exact port of the destination workload, which may only answer. Both addresses are
|
|
104
|
+
* exact current addresses of two different veth workload endpoints of the scope. It admits the tuple
|
|
105
|
+
* (a TCP opening only with SYN) and its ESTABLISHED replies in the default conntrack zone and nothing
|
|
106
|
+
* else: no reverse opening, no translation and no source-port selection. Grant the reverse direction as
|
|
107
|
+
* a second grant. */
|
|
108
|
+
export interface IManagedNftWorkloadGrant {
|
|
109
|
+
protocol: 'tcp' | 'udp';
|
|
110
|
+
/** Exact unicast address of the dialling workload endpoint, never a prefix. */
|
|
111
|
+
sourceAddress: string;
|
|
112
|
+
/** Exact unicast address of the dialled workload endpoint, never a prefix. */
|
|
113
|
+
destinationAddress: string;
|
|
114
|
+
/** The destination workload's exact listening port, 1–65535; never a range. */
|
|
115
|
+
destinationPort: number;
|
|
116
|
+
}
|
|
117
|
+
|
|
91
118
|
/** One combined private/TUN/local/egress table; never compose a second ACCEPT over v1 terminal drops. */
|
|
92
119
|
export interface IManagedNftRouterEgressScopeV2 {
|
|
93
120
|
kind: 'routerEgress';
|
|
@@ -111,18 +138,33 @@ export interface IManagedNftRouterEgressScopeV2 {
|
|
|
111
138
|
* workload. Absent and empty are the same canonical policy, digest and compiled graph; at most 1024,
|
|
112
139
|
* held in a named set behind a constant number of rules. */
|
|
113
140
|
hostGrants?: IManagedNftHostGrant[];
|
|
141
|
+
/** Optional stateful one-way workload-to-workload grants. Absent and empty are the same canonical
|
|
142
|
+
* policy, digest and compiled graph; at most 1024, held in two named sets behind four rules. They
|
|
143
|
+
* share the scope's set element budget with `hostGrants`. */
|
|
144
|
+
workloadGrants?: IManagedNftWorkloadGrant[];
|
|
114
145
|
}
|
|
115
146
|
|
|
116
147
|
/** One inbound uplink publication, compiled inside the same host-transit generation. */
|
|
117
148
|
export interface IManagedNftPublishedPortV2 {
|
|
118
149
|
protocol: 'tcp' | 'udp';
|
|
119
|
-
/** Published uplink port, 1–65535
|
|
150
|
+
/** Published uplink port, 1–65535; published ports never overlap per protocol across the scope. */
|
|
120
151
|
hostPort: number;
|
|
152
|
+
/** Optional last port of a published range `hostPort..hostPortEnd`, greater than `hostPort`.
|
|
153
|
+
* A range keeps every port, so `targetPort` must equal `hostPort`; like one port it is one
|
|
154
|
+
* interval set element per set, and its translation keeps the port. Absent for one port, which
|
|
155
|
+
* is its only canonical form. */
|
|
156
|
+
hostPortEnd?: number;
|
|
121
157
|
targetPort: number;
|
|
122
158
|
/** Exact leased transit source address of one current allocation; it selects the handoff. */
|
|
123
159
|
targetAddress: string;
|
|
124
160
|
/** Exact current uplink address that publishes this port. No wildcard or route inference. */
|
|
125
161
|
hostIp: string;
|
|
162
|
+
/** Optional: flows from `targetAddress` and the published target port(s) may leave through the
|
|
163
|
+
* uplink toward unprotected space, source-translated to `hostIp` and the published uplink port
|
|
164
|
+
* (a range keeps the port). The protected union stays denied, its target ports may not fall in
|
|
165
|
+
* a leased range of `targetAddress` or overlap another publication's. Absent and `false` are
|
|
166
|
+
* the same canonical policy. */
|
|
167
|
+
symmetric?: boolean;
|
|
126
168
|
}
|
|
127
169
|
|
|
128
170
|
/** Shared-host capture barrier and explicit outer SNAT; Docker forwarding remains a separate owner. */
|
|
@@ -143,6 +185,28 @@ export interface IManagedNftHostTransitScopeV2 {
|
|
|
143
185
|
* host-local, a platform endpoint nor a leased transit source address. Absent and empty are the
|
|
144
186
|
* same canonical policy; at most 1024, held in a named set behind a constant number of rules. */
|
|
145
187
|
hostGrants?: IManagedNftHostGrant[];
|
|
188
|
+
/** Optional ids of `protection.platformEndpoints` this host serves itself, on an exact current address
|
|
189
|
+
* of the uplink or of a handoff link (rtnetlink verifies it at apply, recovery and inspection). Only a
|
|
190
|
+
* declared endpoint may hold a host address. Leased flows reach it from their exact handoff with the
|
|
191
|
+
* leased source address and a source port of the allocation's range for the endpoint's protocol; its
|
|
192
|
+
* ESTABLISHED replies return. Absent and empty are the same canonical policy, digest and compiled graph. */
|
|
193
|
+
localPlatformEndpoints?: string[];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** One loopback TCP service that only one local user may dial. Every packet the host sends to the
|
|
197
|
+
* exact address and port from a socket of any other user is rejected with a TCP reset, after ordinary
|
|
198
|
+
* output destination NAT; the address and port arriving on any interface but loopback are dropped.
|
|
199
|
+
* The service must bind exactly this address: a wildcard listener stays reachable through others. */
|
|
200
|
+
export interface IManagedNftLocalTcpPortOwner {
|
|
201
|
+
/** Exact IPv4 loopback host address in 127.0.0.0/8, e.g. `127.0.0.1`. Never a prefix or wildcard. */
|
|
202
|
+
address: string;
|
|
203
|
+
/** The service's exact listening port, 1–65535; never a range. */
|
|
204
|
+
port: number;
|
|
205
|
+
/** The only user id whose sockets may send to the port: the socket file's file-system uid as
|
|
206
|
+
* the user namespace owning the network namespace sees it, 0–4294967294. Packets without a socket file carry no uid and
|
|
207
|
+
* are not matched: kernel replies, the teardown of an orphaned socket, and in-kernel sockets such as NFS or CIFS clients,
|
|
208
|
+
* which only privileged mounts create. */
|
|
209
|
+
uid: number;
|
|
146
210
|
}
|
|
147
211
|
|
|
148
212
|
/** Host-wide IPv4 destination denial for caller-authenticated private allocation pools.
|
|
@@ -156,6 +220,10 @@ export interface IManagedNftAllocationPoolGuardScopeV2 {
|
|
|
156
220
|
* listed pool, and their replies. Absent and empty are the same canonical policy; at most 1024,
|
|
157
221
|
* held in a named set behind a constant number of rules. */
|
|
158
222
|
hostGrants?: IManagedNftHostGrant[];
|
|
223
|
+
/** Optional host-wide loopback port ownership, compiled ahead of the guard in the same table.
|
|
224
|
+
* Absent and empty are the same canonical policy, digest and compiled graph; at most 8, one per
|
|
225
|
+
* exact address and port. */
|
|
226
|
+
localTcpPortOwners?: IManagedNftLocalTcpPortOwner[];
|
|
159
227
|
}
|
|
160
228
|
|
|
161
229
|
export interface IManagedNftPolicyV2 {
|