Long-running asset monitoring toolkit for DNS records, TCP ports, web services, web paths, URL status, and lightweight exposure checks.
中文文档: README.zh-CN.md
This PROJECT was written with assistance from Codex AI.
watcher is a conservative security operations CLI for keeping a baseline of
business-facing assets and detecting changes over time. It stores imported and
discovered assets in a local SQLite database, runs scheduled monitoring batches,
generates human-readable reports, and can send the report package by email.
It is designed for teams that need to answer questions like:
- Did any domain start resolving to a different IP?
- Did a new TCP port open on a known asset?
- Which open ports look like web services?
- Did directory enumeration discover non-baseline URLs?
- Did a lightweight POC find an exposed sourcemap?
- What changed since the imported asset baseline?
watcher favors slow, low-noise probing over aggressive scanning. Use it only on
assets that you own or are authorized to assess.
- Baseline asset inventory: import domains, real IPs, bound IPs, ports, and URLs from Excel, or manage individual baseline assets from the CLI.
- Business-system centric model: assets are grouped by system so reports remain useful for ownership and remediation.
- DNS monitoring: resolves configured domain names and records DNS change alerts.
- Slow TCP port monitoring: scans configured ports with per-IP and per-port concurrency controls.
- Service fingerprinting: identifies HTTP/HTTPS services and captures simple banner/fingerprint details.
- Detailed service fingerprinting: optional nmap
-sVservice detection runs after the lightweight fingerprint phase. - Web path enumeration: uses a path dictionary, filters common fake-200 responses, and can discover links from HTML and JavaScript.
- Lightweight vulnerability checks: currently includes
webpack_sourcemap_disclosure. - SQLite persistence: local, portable storage with built-in migrations.
- Reports: always generates
summary.md, plus detail files inxlsx,json, orcsv, then packages everything as a zip. - SMTP notification: sends batch summaries and report zip attachments when enabled.
- Static-build friendly dependencies: uses
rustlsfor HTTP/SMTP TLS and bundled SQLite throughrusqlite.
The project is currently an early 0.1.0 implementation. The core workflow is
usable, but command output, report structure, and POC coverage may still evolve.
- Rust toolchain with Cargo
- A platform supported by
tokio,rusqlite, andreqwest
git clone <repository-url>
cd watcher
cargo build --releaseThe binary will be available at:
target/release/watcherFor local development, you can also run commands through Cargo:
cargo run -- --helpCreate the default config and database:
watcher initPrint an example YAML config:
watcher --exampleImport baseline assets from Excel:
watcher baseline import --asset-type excel ./assets.xlsxImport a web path dictionary:
watcher dict path import ./paths.txtRun one monitoring batch:
watcher task run --onceQuery recent logs:
watcher log query --limit 50Build a report package for the latest batch:
watcher reportwatcher uses the user config directory by default:
- Config:
~/.config/watcher/watcher.yml - Database:
~/.config/watcher/watcher.db - Reports:
~/.config/watcher/reports - Daemon PID file: next to the config file as
watcher.pid
Running watcher init or any normal command creates missing config/database
paths automatically.
The database is organized around business systems:
systems: business systems and ownership boundaries.domains: domain names and their expected/latest resolved IPs.ip_addresses: real IP addresses and resolved IP addresses.ports: TCP port state, service protocol, web flag, and fingerprint.urls: imported URLs, enumerated URLs, JS-discovered URLs, and vuln URLs.dict_paths: web enumeration dictionary entries.batches: monitoring batch status and report package path.alerts: DNS, port, and vulnerability events.vulnerabilities: lightweight POC findings.pending_work: carry-over work when a batch stops before completion.logs: application logs stored in SQLite for CLI query/export.
domains, ip_addresses, ports, and urls include an is_baseline marker.
Imported assets are baseline assets; assets found by scanning, enumeration, or
POCs are non-baseline discoveries by default.
The first worksheet should contain these headers:
id,system,servername,real_ip,servername_bind_ip,port,url
Column behavior:
id: ignored.system: business system name. Required.servername: domain name. Optional.real_ip: real asset IP address.servername_bind_ip: expected or previously known domain binding IP.port: TCP ports. Supports separators such as80,443/8080.url: related URL. Optional.
Example:
watcher baseline import --asset-type excel ./assets.xlsxBaseline assets can also be managed without Excel:
watcher baseline add --asset-type url --system core https://example.com/login
watcher baseline import --asset-type url --system core ./urls.txt
watcher baseline query --asset-type ip --keyword 10.0.0
watcher baseline add --asset-type ip --system core 10.0.0.1
watcher baseline add --asset-type port --system core --ip 10.0.0.1 443
watcher baseline import --asset-type port --system core --ip 10.0.0.1 ./ports.txt
watcher baseline add --asset-type name --system core --bind-ip 10.0.0.1 example.com
watcher baseline unmark --asset-type port --system core --ip 10.0.0.1 8443
watcher baseline delete --asset-type url --system core https://example.com/oldbaseline delete removes the asset row. baseline unmark keeps the row but
changes it from baseline to non-baseline.
watcher system add core
watcher system query --keyword core
watcher system export ./systems.csv
watcher system rename core core-prod
watcher system delete core-prodsystem query and system export include domain, IP, port, URL, and baseline
counters. Deleting a system cascades to assets under that system.
Each batch runs the following stages:
- DNS resolution: resolves every domain and records DNS changes.
- Port scanning: probes configured TCP ports on real IP assets and records open/closed changes.
- Fingerprinting: checks open ports for HTTP/HTTPS and banner details.
- Web enumeration: tries dictionary paths against web services, including
ip:portand same-systemname:portforms, then extracts possible links from HTML/JS. - Lightweight POCs: runs exposure checks in parallel with web enumeration.
- Report packaging: writes
summary.mdand detail files, then creates a zip package. - Email notification: sends the summary and zip attachment when enabled.
Use watcher --example to print the default YAML config, or see
examples/watcher.yml.
Watcher stores timestamps in UTC and renders human-facing output with
display.timezone. The default is UTC+08:00:
display:
timezone: "+08:00"Accepted values include fixed offsets such as +08:00, -05:30, UTC+8, and
UTC.
Port scanning uses two concurrency controls:
probe:
connect_timeout_ms: 2000
scan_ip_concurrency: 4
scan_port_concurrency_per_ip: 4Effective port probe parallelism is:
scan_ip_concurrency * scan_port_concurrency_per_ip
probe.concurrency is still used by non-port tasks such as fingerprinting, web
enumeration, and vulnerability checks.
Detailed fingerprinting is disabled by default because it depends on nmap.
When enabled, it starts after the lightweight fingerprint phase and runs in
parallel with web enumeration and vulnerability checks:
fingerprint:
detailed:
enabled: true
nmap_path: nmap
timeout_ms: 30000
concurrency: 2Configure explicit ports:
probe:
scan_ports:
- 80
- 443
- 8080Or scan all TCP ports:
probe:
scan_ports: fullfull and all both expand to 1..=65535. Full-port scans can take a long
time; use longer scheduler intervals and lower concurrency for conservative
monitoring.
An empty dns_servers list uses the host/system resolver:
probe:
dns_servers: []Custom DNS servers support IP and IP:port forms:
probe:
dns_servers:
- 8.8.8.8
- 1.1.1.1:53summary.md is always generated. Details are controlled by report.format:
report:
output_dir: ~/.config/watcher/reports
format: xlsxSupported formats:
xlsx: onedetails.xlsxworkbook withalerts,vulnerabilities,urls, andopen_portssheets.json: one structureddetails.jsonfile.csv: separate detail CSV files.
Each lightweight vulnerability POC can be enabled or disabled independently.
Currently the built-in POC list contains webpack_sourcemap_disclosure:
pocs:
webpack_sourcemap_disclosure:
enabled: true
max_urls_per_batch: 1000
max_js_files_per_url: 20
max_map_candidates_per_url: 20Set enabled: false to skip that POC without affecting other monitoring tasks.
The limit fields bound task5 work for large URL histories or pages with many
JavaScript files.
Run continuously in the background:
watcher daemon runRun in the foreground for debugging:
watcher daemon run --foregroundManage daemon state:
watcher daemon status
watcher daemon stop
watcher daemon restartManage task batches:
watcher task run --once
watcher task list
watcher task status
watcher task stopRuntime logs are stored in SQLite and can be queried or exported:
watcher log query --level info --limit 100
watcher log query --level error --keyword smtp --limit 20
watcher log export ./watcher-logs.csv --limit 1000
watcher log clear --before 2026-05-15T00:00:00ZSMTP notifications are optional. QQ/Foxmail users should use an SMTP authorization code instead of the web login password.
smtp_security: auto maps port 465 to implicit TLS/SMTPS and port 587 to
STARTTLS:
email:
enabled: true
smtp_host: smtp.qq.com
smtp_port: 465
smtp_security: auto
username: your-account@qq.com
password: "your-smtp-authorization-code"
from: your-account@qq.com
to:
- security@example.comFor mail troubleshooting:
watcher log query --keyword email --level warn --limit 20
watcher log query --keyword smtp --limit 20watcher init
watcher --example
watcher baseline import --asset-type excel <file>
watcher baseline add --asset-type url|port|ip|name --system <system> <value>
watcher baseline import --asset-type url|port|ip|name --system <system> <file>
watcher baseline query --asset-type url|port|ip|name
watcher baseline export --asset-type url|port|ip|name <file>
watcher baseline delete|unmark --asset-type url|port|ip|name --system <system> <value>
watcher system add|query|export|delete|rename
watcher daemon run|status|stop|restart
watcher task run|list|status|stop
watcher log query|export|clear
watcher dict path import|export|query|delete
watcher url import --system <system> <file>
watcher port import --system <system> [--ip <ip>] <file>
watcher ip import --system <system> <file>
watcher name import --system <system> [--bind-ip <ip>] <file>
watcher url|port|ip|name export|query|delete
watcher reportUse watcher <command> --help for exact arguments.
Run checks:
cargo fmt --check
cargo clippy -- -D warnings
cargo testRun the CLI locally:
cargo run -- --help
cargo run -- --example
cargo run -- task run --once- Broader POC registry and clearer extension points.
- Integration tests with mock HTTP services and sample Excel files.
- Systemd service examples for daemon deployment.
- More granular per-stage task progress.
- Richer report comparison sections for newly discovered assets.
MIT. See LICENSE.