- Connections: the kernel's tracked connections, read and closed over ctnetlink (internal/conntrack, raw netlink like the drop log), with their NAT and TCP state; closing one makes the rules check its next packet again (GET /connections, POST /connections/close; hc connections; Traffic → Connections). - Rules can check every packet (every_packet, --every-packet): before established connections are accepted, so a drop or reject also stops connections already open. They can't accept. - A packet tracer (internal/trace): a table of its own, inet housecarl-trace, marks the packets a filter picks, `nft monitor trace` reports every rule and policy they meet in every table, and the tracer names what accepted or dropped them, Housecarl's rules by name (POST, GET, DELETE /trace; hc trace; Traffic → Trace). One trace at a time, at most 200 packets and 20 a second; the table goes when it ends. e2e: 157 checks, among them an upload a normal block doesn't stop and an every-packet one does, and a trace naming the blocking rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
31 lines
677 B
Go
31 lines
677 B
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"housecarl/internal/trace"
|
|
)
|
|
|
|
// otherTables lists the tables in an `nft -j list ruleset` other than
|
|
// Housecarl's ("inet main").
|
|
func otherTables(data []byte) []string {
|
|
var doc struct {
|
|
Nftables []map[string]json.RawMessage `json:"nftables"`
|
|
}
|
|
out := []string{}
|
|
if json.Unmarshal(data, &doc) != nil {
|
|
return out
|
|
}
|
|
for _, item := range doc.Nftables {
|
|
raw, ok := item["table"]
|
|
if !ok {
|
|
continue
|
|
}
|
|
var t struct{ Family, Name string }
|
|
if json.Unmarshal(raw, &t) == nil && !(t.Family == "inet" && (t.Name == "housecarl" || t.Name == trace.Table)) {
|
|
out = append(out, t.Family+" "+t.Name)
|
|
}
|
|
}
|
|
return out
|
|
}
|