Documentation
¶
Overview ¶
Package collect snapshots a host into a facts.Facts document. It is the only package that talks to netlink, /proc and Docker.
Index ¶
- Constants
- func All(opts Options) (facts.Facts, error)
- func ChainDevices() (map[chainKey][]string, []facts.Warning)
- func ClassifyAddr(ip netip.Addr) string
- func ConvertExprs(exprs []expr.Any) []facts.Expr
- func DockerFromSocket(socketPath string) (facts.Docker, []facts.Warning)
- func FamilyName(f nftables.TableFamily) string
- func HookName(h *nftables.ChainHook, family nftables.TableFamily) string
- func Host(procRoot string) (facts.Host, []facts.Warning)
- func LegacyBackend(procRoot string) []facts.Warning
- func ParseProcNet(r io.Reader, family, proto string) ([]facts.Socket, error)
- func PolicyName(p *nftables.ChainPolicy) string
- func Redecode(f *facts.Facts) int
- func Routes(procRoot string) ([]facts.Route, []facts.Warning)
- func RulePayloads() (map[ruleKey][]xtPayload, []facts.Warning)
- func Ruleset() (facts.Ruleset, []facts.Warning, error)
- func Sockets(procRoot string) ([]facts.Socket, []facts.Warning)
- type Options
Constants ¶
const DefaultDockerSocket = "/var/run/docker.sock"
DefaultDockerSocket is where the daemon listens on a stock install.
Variables ¶
This section is empty.
Functions ¶
func All ¶
All snapshots the host. Every sub-collector degrades to a warning rather than an error, because a partial snapshot still yields useful verdicts and the warnings are carried into the report.
func ChainDevices ¶ added in v0.5.0
ChainDevices returns the devices each base chain's hook is attached to, for the chains that have any. A chain missing from the map is one whose devices whyopen does not know, which the evaluator reads as "could see anything" rather than "sees nothing".
A failure here is never a failure to read the ruleset: it returns a warning and no devices, and whyopen falls back to the conservative answer it gave before it could read them at all.
func ClassifyAddr ¶
ClassifyAddr labels an address for the internet zone. Only "global" is reachable from outside; everything else cannot be a packet's destination when the source is the public internet.
func ConvertExprs ¶
ConvertExprs maps netlink expressions onto whyopen's serializable union. An xt extension without a typed decoder is preserved by name with Decoded false; a netlink expression with no case at all becomes facts.ExprUnknown. Either way the evaluator can see that it must refuse to guess, which it could not do if the expression were simply dropped.
func DockerFromSocket ¶
DockerFromSocket lists running containers and their published ports. An unreachable daemon is a warning, never an error: the ruleset still carries the DNAT rules, so verdicts remain possible, just less well attributed.
func FamilyName ¶
func FamilyName(f nftables.TableFamily) string
func HookName ¶
func HookName(h *nftables.ChainHook, family nftables.TableFamily) string
HookName returns the empty string for a regular (non-base) chain.
The family is not decoration: hook numbers are per family and they overlap. NF_NETDEV_INGRESS and NF_INET_PRE_ROUTING are both 0, and NF_NETDEV_EGRESS and NF_INET_LOCAL_IN are both 1, so naming a hook without knowing the family called a netdev ingress chain "prerouting". The evaluator then skipped it as a table of the wrong family, and a chain that can drop every packet arriving on a device was invisible to an audit whose whole job is to notice that.
func Host ¶
Host snapshots interfaces, their addresses and the sysctls that change a reachability answer. procRoot is "/proc" in production.
func LegacyBackend ¶
LegacyBackend reports iptables-legacy rules on the host. whyopen reads only the nftables ruleset; on a legacy host ListTables succeeds against an empty nft ruleset, so without this check every port would report reachable with nothing to say it was the wrong backend that was read. procRoot is "/proc" in production.
func ParseProcNet ¶
ParseProcNet parses one /proc/net/{tcp,tcp6,udp,udp6} table. For TCP only sockets in LISTEN are returned; for UDP every unconnected socket is, since an unconnected UDP socket is a listener.
func PolicyName ¶
func PolicyName(p *nftables.ChainPolicy) string
PolicyName returns the empty string for a regular chain, which has none.
func Redecode ¶ added in v0.4.0
Redecode re-derives every xt expression a document preserved the payload of, and returns how many it changed. It is what makes collect-once-evaluate-later hold across decoder generations: one document read by two builds differs exactly as their decoders differ.
Where there is a payload, this build decodes it, even over an answer the collecting build recorded. That is decision 0007's contract change and it rests on one fact: the payload is what the collecting build saw, so a reading build with a better decoder is better placed to read it, not worse. Where there is no payload the collector's answer stands untouched, because nothing can check it.
func Routes ¶ added in v1.3.0
Routes reads the host's routing table from /proc, reduced to the prefix and device a fib lookup needs (docs/decisions/0012-fib-and-routes.md).
It reads text files rather than adding a third netlink message type to the two decisions 0006 and 0007 fenced: the proc tables carry the destination and the device, which is all this question needs.
Nothing here warns. A host with one family disabled legitimately has no table for it, and a route whyopen cannot read only ever costs it the ability to resolve a fib lookup, which leaves the verdict unknown: the same place it was before routes were read at all.
func RulePayloads ¶ added in v0.6.0
RulePayloads returns the xt payloads of every rule that has any, in the order the kernel listed them within each rule.
A failure here is never a failure to read the ruleset: it returns a warning and no payloads, and the document is exactly as complete as one from before whyopen read them, which is to say lossy for typed extensions and no worse.