descry

module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: Apache-2.0

README

descry

ci

A sink-agnostic, event-sourced HTTP uptime engine. A Check runs against a Target, produces an Observation, mapped to a CloudEvents 1.0 event, handed to an EventSink (stdout / file in v1); tenancy and routing ride along as an opaque Labels map the engine never interprets, so it owes no particular consumer anything. It runs in production in my homelab, watching real endpoints.

The part that is more than table stakes is the SSRF guard: two layers, the second of which checks the already-resolved socket address inside net.Dialer.ControlContext, so a rebound DNS answer is blocked before connect(2) rather than after. Threat model and residual risks are in Security.

Install

As a binary:

go install github.com/fairbearlab/descry/cmd/descry@latest

As a library:

go get github.com/fairbearlab/descry

Design

docs/ARCHITECTURE.md is the producer/consumer seam contract: what the engine owns and never delegates, what a consumer owns, and the litmus test for whether a proposed change leaks consumer specifics into the engine's exported types. Read it before adding a typed field to Observation.

60-second demo (stdout)

git clone https://github.com/fairbearlab/descry
cd descry
go run ./cmd/descry --config example.yaml
# prints CloudEvents 1.0 observations to stdout on the configured interval

File-sink replay demo

Edit example.yaml to switch the sink:

sink: file
file_path: events.jsonl

Then run:

go run ./cmd/descry --config example.yaml &
sleep 15
cat events.jsonl   # one valid CloudEvent per line

Version

descry --version prints version, commit, and build date. Release builds stamp them via -ldflags -X main.version=… (see .goreleaser.yaml); a plain go build reports the dev defaults.

HTTP check options

httpcheck.New takes a timeout plus optional functional options:

import httpcheck "github.com/fairbearlab/descry/checks/http"

// Default: net/http's stdlib User-Agent ("Go-http-client/1.1"), no impersonation.
c := httpcheck.New(10 * time.Second)

// Override the User-Agent (e.g. to satisfy a WAF that blocks the default UA):
c := httpcheck.New(10*time.Second, httpcheck.WithUserAgent("MyMonitor/1.0 (+https://example.com)"))

WithUserAgent("") (or omitting the option) leaves the stdlib default in place — the engine never impersonates a browser unless the caller explicitly opts in.

Security

The SSRF guard is best-effort, not a security boundary. Network egress isolation is the real control and the deployer's responsibility.

The guard runs two layers:

  1. Parse-time (Layer 1): A string-only allowlist/blocklist applied before any DNS lookup. Blocks private RFC 1918 ranges, loopback, link-local, CGNAT, TEST-NET ranges, reserved blocks, and non-standard ports. Literal IPv6 addresses are decoded for known embedding classes (::ffff:x.x.x.x).

  2. Dial-time (Layer 2): A net.Dialer.ControlContext hook runs on the already-resolved socket address before connect(2) — no TOCTOU window. Applies to every dial attempt including Happy Eyeballs and each redirect hop.

Residual risks the guard does not cover:

  • Kernel/network routing manipulation that maps a public-looking address to an internal host after the Layer 2 check — e.g. policy routing, NAT/NAT64, or a VPN/overlay that redirects an allowed destination IP to an internal endpoint. (Classic DNS rebinding is not a residual risk here: Layer 2 re-checks the resolved socket address on every dial, so a later private DNS answer is blocked locally before connect rather than bypassing the guard.)
  • IPv6 embedding classes not explicitly decoded (unknown future embedding schemes).
  • Non-HTTP protocols tunneled over allowed ports 80/443.

For production use, run descry inside a network namespace or egress firewall that enforces the isolation policy independently of this guard.

License

Apache-2.0. See LICENSE.

Directories

Path Synopsis
checks
cmd
descry command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL