code wiki / _hdl_build / nx_conn_cap.nx
nx_conn_cap.nx source
↩ module page · 53 lines · 2130 B
1// nx_conn_cap.nx -- per-IP concurrent-connection cap, the access-wall DDoS L3-connection / slowloris defense
2// (RFC 7230 timeouts complement). A bounded in-memory table the enforcement daemon owns: cc_acquire(ip) at
3// accept (reject when an IP already holds >= cap, OR when the table is saturated = FAIL-CLOSED under a flood),
4// cc_release(ip) on close. Pure logic, nx_syscalls -- pairs with nx_rate_limit (request brute-force, L4) +
5// nx_access_wall (the rate_ok / conn-ok signals feed the PDP). license_tier: ORIGINAL
6import "nx_syscalls.nx"
7
8const CC_CAP_DEFAULT: i64 = 16 // default max concurrent connections per IP
9
10// find ip's slot in ips[0..n); -1 if absent.
11func cc_find(ips: *i64, n: i64, ip: i64) -> i64 {
12 var i: i64 = 0
13 while i < n { if ips[i] == ip { return i } i = i + 1 }
14 return 0 - 1
15}
16
17// try to acquire a connection slot for ip. ips/cnts = parallel tables, nbox[0] = used slots, slots = table
18// capacity, cap = max concurrent per IP. returns 1 (allowed, count++ ) or 0 (rejected: per-IP cap hit, or the
19// table is saturated -> fail-closed reject of a NEW flooding IP).
20func cc_acquire(ips: *i64, cnts: *i64, nbox: *i64, slots: i64, ip: i64, cap: i64) -> i64 {
21 let s: i64 = cc_find(ips, nbox[0], ip)
22 if s >= 0 {
23 if cnts[s] >= cap { return 0 }
24 cnts[s] = cnts[s] + 1
25 return 1
26 }
27 if nbox[0] >= slots { return 0 }
28 ips[nbox[0]] = ip
29 cnts[nbox[0]] = 1
30 nbox[0] = nbox[0] + 1
31 return 1
32}
33
34// release a connection slot for ip (on close): decrement; when it hits 0, free the slot (swap-with-last).
35func cc_release(ips: *i64, cnts: *i64, nbox: *i64, ip: i64) -> i64 {
36 let s: i64 = cc_find(ips, nbox[0], ip)
37 if s < 0 { return 0 }
38 if cnts[s] > 0 { cnts[s] = cnts[s] - 1 }
39 if cnts[s] == 0 {
40 let last: i64 = nbox[0] - 1
41 ips[s] = ips[last]
42 cnts[s] = cnts[last]
43 nbox[0] = last
44 }
45 return 0
46}
47
48// current concurrent count for ip (0 if absent).
49func cc_count(ips: *i64, cnts: *i64, nbox: *i64, ip: i64) -> i64 {
50 let s: i64 = cc_find(ips, nbox[0], ip)
51 if s < 0 { return 0 }
52 return cnts[s]
53}