knock 0.1.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2011-2026 Carter Cole
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,17 +1,195 @@
1
- NPM Knock
2
- =========
1
+ # knock
3
2
 
4
- Knock, Knock whos there? Great for pen-testing or for doing an audit of a new client or getting competitive intellegince find the subdomains of a target domain
3
+ > Knock, knock. Who's there?
5
4
 
6
- Installation
7
- ------------
5
+ Subdomain enumeration for Node.js. Pulls candidate names from **Certificate
6
+ Transparency logs** (passive, via [crt.sh](https://crt.sh)) and a bundled
7
+ **31k-entry wordlist** (active DNS brute force), detects wildcard DNS so you
8
+ don't drown in false positives, and verifies everything with real lookups.
9
+
10
+ Use it as a CLI, a library, or an **MCP server** for AI agents. Zero
11
+ runtime dependencies. Great for attack-surface audits, pen-test recon,
12
+ or checking what a new client actually has exposed.
13
+
14
+ [![npm version](https://img.shields.io/npm/v/knock.svg)](https://www.npmjs.com/package/knock)
15
+ [![CI](https://github.com/neopunisher/node-knock/actions/workflows/ci.yml/badge.svg)](https://github.com/neopunisher/node-knock/actions/workflows/ci.yml)
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ npm install -g knock # CLI
21
+ npm install knock # library
22
+ ```
23
+
24
+ Or run the CLI without installing:
25
+
26
+ ```bash
27
+ npx knock example.com
28
+ ```
29
+
30
+ Requires Node.js >= 22.
31
+
32
+ ## CLI
33
+
34
+ ```bash
35
+ knock example.com
36
+ ```
37
+
38
+ ```
39
+ www.example.com 93.184.216.34 [ct+list]
40
+ api.example.com 203.0.113.10 [ct]
41
+ mail.example.com 198.51.100.7 [list]
42
+ # example.com: 3 found from 31307 candidates, 18 ct names (2 unresolved) in 41.3s
43
+ ```
44
+
45
+ Useful flags:
46
+
47
+ | Flag | Effect |
48
+ | --- | --- |
49
+ | `-p, --passive` | Certificate Transparency only — no brute force |
50
+ | `--no-ct` | wordlist brute force only |
51
+ | `--no-verify` | report CT names without resolving them |
52
+ | `--full-host` | scan the exact host given (skip the registrable-domain reduction) |
53
+ | `-l, --list <path\|subs\|org>` | custom wordlist, or a bundled one by name |
54
+ | `-c, --concurrency <n>` | parallel DNS queries (default 64) |
55
+ | `-s, --server <ip>` | DNS server to query (repeatable) |
56
+ | `-6, --ipv6` | also resolve AAAA records |
57
+ | `-w, --web` | probe http/https on each found host |
58
+ | `-j, --json` | full report as JSON |
59
+ | `-q, --quiet` | hostnames only (pipe-friendly) |
60
+ | `--mcp` | run as an MCP server on stdio (see below) |
61
+
62
+ Found hosts stream to stdout as they resolve; diagnostics go to stderr, so
63
+ `knock -q example.com | sort` does what you'd hope.
64
+
65
+ ## Library
66
+
67
+ ```js
68
+ import { knock } from 'knock';
69
+
70
+ const report = await knock('example.com', { concurrency: 128 });
71
+
72
+ for (const { name, addresses, sources } of report.results) {
73
+ console.log(name, addresses, sources); // 'www.example.com', ['93.184.216.34'], ['ct', 'wordlist']
74
+ }
75
+ console.log(report.wildcard); // { detected: false, addresses: [] }
76
+ console.log(report.ct); // { enabled: true, names: 18, unresolved: [...], error: null }
77
+ console.log(report.stats); // { words, candidates, queried, found, errors, durationMs }
78
+ ```
79
+
80
+ Stream results as they're discovered, or go passive-only:
81
+
82
+ ```js
83
+ await knock('example.com', { onResult: (r) => console.log(r.name) });
84
+
85
+ // Just the Certificate Transparency names, one HTTPS request, no DNS:
86
+ import { certSubdomains } from 'knock';
87
+ const names = await certSubdomains('example.com');
88
+ ```
89
+
90
+ ### Options
91
+
92
+ | Option | Default | Description |
93
+ | --- | --- | --- |
94
+ | `words` | — | array of labels to try (`[]` for passive-only) |
95
+ | `wordlist` | bundled `subs` | path to a wordlist file |
96
+ | `ct` | `true` | pull candidates from Certificate Transparency logs |
97
+ | `ctTimeout` | `15000` | crt.sh request timeout (ms) |
98
+ | `verify` | `true` | resolve CT names over DNS |
99
+ | `concurrency` | `64` | parallel DNS queries |
100
+ | `timeout` / `tries` | `5000` / `2` | per-query DNS timeout (ms) and retries |
101
+ | `servers` | system | DNS servers to query |
102
+ | `family` | `4` | `4`, `6`, or `'any'` for A + AAAA |
103
+ | `wildcardTests` | `3` | random probes for wildcard detection (`0` disables) |
104
+ | `web` / `webTimeout` | `false` / `5000` | probe http/https on found hosts |
105
+ | `baseDomainOnly` | `true` | reduce the target to its registrable domain first |
106
+ | `icannOnly` | `false` | ignore the PSL's PRIVATE section (github.io, …) |
107
+ | `signal` | — | `AbortSignal` to cancel the run |
108
+ | `onResult` | — | callback fired per discovery |
109
+ | `resolver` / `fetch` / `psl` | built-in | injectable for testing |
110
+
111
+ The bundled wordlists are exposed as `wordlists.subs` (~31k labels,
112
+ popularity-ordered) and `wordlists.org`, and helpers `loadWordlist(path)` /
113
+ `parseWordlist(text)` / `normalizeDomain(input)` are exported too. Full
114
+ TypeScript types ship with the package.
115
+
116
+ ## MCP server
117
+
118
+ knock ships a [Model Context Protocol](https://modelcontextprotocol.io)
119
+ server, so AI agents (Claude Code, Claude Desktop, Cursor, …) can enumerate
120
+ subdomains directly. It runs over stdio:
8
121
 
9
122
  ```bash
10
- npm install knock
123
+ claude mcp add knock -- npx -y knock --mcp
11
124
  ```
12
125
 
13
- Useage
14
- ------
15
- ```javascript
16
- var knock = require('knock');
126
+ Or in any client's JSON config:
127
+
128
+ ```json
129
+ {
130
+ "mcpServers": {
131
+ "knock": { "command": "npx", "args": ["-y", "knock", "--mcp"] }
132
+ }
133
+ }
17
134
  ```
135
+
136
+ | Tool | Does |
137
+ | --- | --- |
138
+ | `knock_enumerate` | full run (CT + brute force, or `passive: true`), returns the report |
139
+ | `knock_ct_lookup` | Certificate Transparency names only — one HTTPS request, no DNS |
140
+ | `knock_registrable_domain` | offline Public Suffix List lookup |
141
+
142
+ All tools are read-only, return structured JSON, stream progress per found
143
+ host, and honor cancellation. The server is implemented without the MCP SDK,
144
+ so the zero-dependency promise holds.
145
+
146
+ ## AI docs
147
+
148
+ [`llms.txt`](llms.txt) is a compact, agent-oriented reference to the whole
149
+ API (library, CLI and MCP tools) and ships in the npm package at
150
+ `node_modules/knock/llms.txt`. Contributors' coding agents get repo
151
+ conventions from [`AGENTS.md`](AGENTS.md).
152
+
153
+ ## How it works
154
+
155
+ 0. **Public Suffix List** — input like `https://deep.www.example.co.uk/x` is
156
+ first reduced to its registrable domain (`example.co.uk`) using a vendored
157
+ [PSL](https://publicsuffix.org) snapshot (refresh with `npm run
158
+ update-psl`), so private suffixes like `github.io` are handled correctly.
159
+ `--full-host` / `baseDomainOnly: false` scans the host exactly as given,
160
+ and the PSL helpers (`getRegistrableDomain`, `getPublicSuffix`,
161
+ `loadPublicSuffixList`) are exported for standalone use.
162
+ 1. **Certificate Transparency** — every publicly trusted TLS certificate is
163
+ logged; querying the logs for `%.example.com` reveals names that were ever
164
+ certified, including ones DNS brute forcing would never guess. Names that
165
+ no longer resolve are reported in `ct.unresolved` — often the most
166
+ interesting ones.
167
+ 2. **Wildcard detection** — a few random labels are resolved first; if the
168
+ zone answers for anything, wordlist hits that merely echo the wildcard
169
+ answer are suppressed (CT-sourced names are kept: the certificate is
170
+ evidence on its own).
171
+ 3. **Brute force** — wordlist labels are resolved through a bounded worker
172
+ pool using `node:dns` directly against your system resolvers (or servers
173
+ you pick with `-s`).
174
+
175
+ ## Development
176
+
177
+ TypeScript sources live in `src/` and run directly on Node's native type
178
+ stripping — `npm test` executes the `.ts` tests with `node --test`, no build
179
+ step needed. `npm run build` compiles `dist/` (what actually ships), and
180
+ `npm run knock -- example.com` runs the CLI from source.
181
+
182
+ ## Responsible use
183
+
184
+ DNS brute forcing generates thousands of queries and CT lookups are logged.
185
+ Only scan domains you own or are explicitly authorized to assess.
186
+
187
+ ## Publishing
188
+
189
+ Releases are published to npm from GitHub Actions via
190
+ [trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC) — no
191
+ long-lived npm tokens — with provenance attestations generated automatically.
192
+
193
+ ## License
194
+
195
+ MIT © [Carter Cole](https://github.com/neopunisher)
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from 'node:util';
3
+ import { readFileSync } from 'node:fs';
4
+ import process from 'node:process';
5
+ import { knock, wordlists } from './index.js';
6
+ const { version } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
7
+ const HELP = `knock ${version} — subdomain enumeration
8
+
9
+ Usage
10
+ knock [options] <domain> [domain ...]
11
+
12
+ Sources
13
+ Certificate Transparency logs (crt.sh, passive) and a wordlist DNS brute
14
+ force run by default; wildcard DNS answers are detected and filtered.
15
+
16
+ Options
17
+ -l, --list <path|subs|org> wordlist file, or a bundled list by name
18
+ (default: "subs", ~31k entries)
19
+ -p, --passive skip the wordlist brute force (CT lookup only)
20
+ --no-ct skip the Certificate Transparency lookup
21
+ --no-verify report CT names without resolving them
22
+ --full-host scan the exact host given, without reducing it
23
+ to the registrable domain (Public Suffix List)
24
+ -c, --concurrency <n> parallel DNS queries (default: 64)
25
+ -t, --timeout <ms> per-query DNS timeout (default: 5000)
26
+ -s, --server <ip> DNS server to use, repeatable
27
+ -6, --ipv6 also resolve AAAA records
28
+ -w, --web probe http/https on found hosts
29
+ --mcp run as an MCP server on stdio (for AI agents)
30
+ -j, --json print the full report as JSON
31
+ -q, --quiet hostnames only, no summary
32
+ -h, --help show this help
33
+ -V, --version print the version
34
+
35
+ Examples
36
+ knock example.com
37
+ knock --passive --json example.com
38
+ knock -l org -s 1.1.1.1 -c 128 example.com
39
+ claude mcp add knock -- npx -y knock --mcp
40
+
41
+ Only scan domains you own or are authorized to assess.`;
42
+ function fail(message) {
43
+ process.stderr.write(`knock: ${message}\n`);
44
+ process.exit(1);
45
+ }
46
+ function parseCliArgs() {
47
+ try {
48
+ return parseArgs({
49
+ allowPositionals: true,
50
+ options: {
51
+ list: { type: 'string', short: 'l' },
52
+ passive: { type: 'boolean', short: 'p', default: false },
53
+ 'no-ct': { type: 'boolean', default: false },
54
+ 'no-verify': { type: 'boolean', default: false },
55
+ 'full-host': { type: 'boolean', default: false },
56
+ concurrency: { type: 'string', short: 'c', default: '64' },
57
+ timeout: { type: 'string', short: 't', default: '5000' },
58
+ server: { type: 'string', short: 's', multiple: true },
59
+ ipv6: { type: 'boolean', short: '6', default: false },
60
+ web: { type: 'boolean', short: 'w', default: false },
61
+ mcp: { type: 'boolean', default: false },
62
+ json: { type: 'boolean', short: 'j', default: false },
63
+ quiet: { type: 'boolean', short: 'q', default: false },
64
+ help: { type: 'boolean', short: 'h', default: false },
65
+ version: { type: 'boolean', short: 'V', default: false },
66
+ },
67
+ });
68
+ }
69
+ catch (error) {
70
+ return fail(error instanceof Error ? error.message : String(error));
71
+ }
72
+ }
73
+ const { values: flags, positionals: domains } = parseCliArgs();
74
+ if (flags.help) {
75
+ console.log(HELP);
76
+ process.exit(0);
77
+ }
78
+ if (flags.version) {
79
+ console.log(version);
80
+ process.exit(0);
81
+ }
82
+ if (flags.mcp) {
83
+ const { serveMcp } = await import('./mcp.js');
84
+ await serveMcp();
85
+ process.exit(0);
86
+ }
87
+ if (domains.length === 0) {
88
+ fail('no domain given (try: knock example.com, or --help)');
89
+ }
90
+ const integer = (name, value) => {
91
+ const n = Number(value);
92
+ if (!Number.isInteger(n) || n <= 0)
93
+ fail(`--${name} expects a positive integer, got "${value}"`);
94
+ return n;
95
+ };
96
+ const options = {
97
+ concurrency: integer('concurrency', flags.concurrency),
98
+ timeout: integer('timeout', flags.timeout),
99
+ servers: flags.server,
100
+ family: flags.ipv6 ? 'any' : 4,
101
+ ct: !flags['no-ct'],
102
+ verify: !flags['no-verify'],
103
+ baseDomainOnly: !flags['full-host'],
104
+ web: flags.web,
105
+ };
106
+ if (flags.passive)
107
+ options.words = [];
108
+ if (flags.list === 'subs' || flags.list === 'org')
109
+ options.wordlist = wordlists[flags.list];
110
+ else if (flags.list)
111
+ options.wordlist = flags.list;
112
+ if (flags.passive && !options.ct)
113
+ fail('--passive together with --no-ct leaves nothing to do');
114
+ const sourceTag = (sources) => sources.length > 1 ? 'ct+list' : sources[0] === 'ct' ? 'ct' : 'list';
115
+ const printResult = (result) => {
116
+ if (flags.quiet) {
117
+ console.log(result.name);
118
+ return;
119
+ }
120
+ const addresses = result.addresses.length > 0 ? result.addresses.join(' ') : '-';
121
+ const web = result.web
122
+ ? ` https:${result.web.https ?? '-'} http:${result.web.http ?? '-'}`
123
+ : '';
124
+ console.log(`${result.name} ${addresses} [${sourceTag(result.sources)}]${web}`);
125
+ };
126
+ const reports = [];
127
+ let failed = false;
128
+ for (const domain of domains) {
129
+ try {
130
+ const report = await knock(domain, {
131
+ ...options,
132
+ onResult: flags.json ? undefined : printResult,
133
+ });
134
+ reports.push(report);
135
+ if (!flags.json && !flags.quiet) {
136
+ const { stats, wildcard, ct } = report;
137
+ if (wildcard.detected) {
138
+ process.stderr.write(`! wildcard DNS on ${report.domain} (${wildcard.addresses.join(', ')}) — matching wordlist hits suppressed\n`);
139
+ }
140
+ if (ct.error)
141
+ process.stderr.write(`! ct lookup failed: ${ct.error}\n`);
142
+ const ctNote = ct.enabled ? `, ${ct.names} ct names (${ct.unresolved.length} unresolved)` : '';
143
+ process.stderr.write(`# ${report.domain}: ${stats.found} found from ${stats.candidates} candidates${ctNote} in ${(stats.durationMs / 1000).toFixed(1)}s\n`);
144
+ }
145
+ }
146
+ catch (error) {
147
+ failed = true;
148
+ process.stderr.write(`knock: ${domain}: ${error instanceof Error ? error.message : String(error)}\n`);
149
+ }
150
+ }
151
+ if (flags.json && reports.length > 0) {
152
+ console.log(JSON.stringify(reports.length === 1 ? reports[0] : reports, null, 2));
153
+ }
154
+ process.exitCode = failed ? 1 : 0;
@@ -0,0 +1,148 @@
1
+ import type { PublicSuffixRules } from './psl.ts';
2
+ export type KnockSource = 'wordlist' | 'ct';
3
+ export interface KnockWebStatuses {
4
+ https: number | null;
5
+ http: number | null;
6
+ }
7
+ export interface KnockResult {
8
+ /** Fully qualified hostname, e.g. "www.example.com". */
9
+ name: string;
10
+ /** Addresses the name resolved to (empty for unverified CT names). */
11
+ addresses: string[];
12
+ /** Where the candidate came from. */
13
+ sources: KnockSource[];
14
+ /** HTTP status codes per protocol; only present when `web: true`. */
15
+ web?: KnockWebStatuses;
16
+ }
17
+ export interface KnockWildcard {
18
+ detected: boolean;
19
+ /** Addresses returned for random non-existent labels. */
20
+ addresses: string[];
21
+ }
22
+ export interface KnockCtReport {
23
+ enabled: boolean;
24
+ /** Unique in-scope names found in Certificate Transparency logs. */
25
+ names: number;
26
+ /** CT names that no longer resolve (stale or internal-only certificates). */
27
+ unresolved: string[];
28
+ /** Error message when the CT lookup failed; the run continues without it. */
29
+ error: string | null;
30
+ }
31
+ export interface KnockStats {
32
+ words: number;
33
+ candidates: number;
34
+ queried: number;
35
+ found: number;
36
+ errors: number;
37
+ durationMs: number;
38
+ }
39
+ export interface KnockReport {
40
+ domain: string;
41
+ wildcard: KnockWildcard;
42
+ ct: KnockCtReport;
43
+ results: KnockResult[];
44
+ stats: KnockStats;
45
+ }
46
+ /** Minimal resolver surface; satisfied by dns.promises.Resolver or a test double. */
47
+ export interface KnockResolver {
48
+ resolve4(name: string): Promise<string[]>;
49
+ resolve6(name: string): Promise<string[]>;
50
+ }
51
+ /** Minimal fetch surface; satisfied by globalThis.fetch or a test double. */
52
+ export type KnockFetch = (url: string, init: {
53
+ signal: AbortSignal;
54
+ headers: Record<string, string>;
55
+ }) => Promise<{
56
+ ok: boolean;
57
+ status: number;
58
+ json(): Promise<unknown>;
59
+ }>;
60
+ export interface CertSubdomainsOptions {
61
+ /** Request timeout in milliseconds. Default 15000. */
62
+ timeout?: number;
63
+ signal?: AbortSignal;
64
+ /** Injectable fetch implementation, mainly for testing. */
65
+ fetch?: KnockFetch;
66
+ }
67
+ export interface KnockOptions {
68
+ /** Labels to try. Takes precedence over `wordlist`. Pass [] for passive-only runs. */
69
+ words?: string[];
70
+ /** Path to a wordlist file. Defaults to the bundled `wordlists.subs`. */
71
+ wordlist?: string;
72
+ /** Parallel DNS queries. Default 64. */
73
+ concurrency?: number;
74
+ /** Per-query DNS timeout in milliseconds. Default 5000. */
75
+ timeout?: number;
76
+ /** DNS retry attempts per query. Default 2. */
77
+ tries?: number;
78
+ /** DNS servers to query instead of the system resolvers. */
79
+ servers?: string[];
80
+ /** Address family: 4 (A), 6 (AAAA) or 'any' for both. Default 4. */
81
+ family?: 4 | 6 | 'any';
82
+ /** Random probes used to detect wildcard DNS. 0 disables. Default 3. */
83
+ wildcardTests?: number;
84
+ /** Pull candidates from Certificate Transparency logs. Default true. */
85
+ ct?: boolean;
86
+ /** CT request timeout in milliseconds. Default 15000. */
87
+ ctTimeout?: number;
88
+ /** Resolve CT-discovered names over DNS. Default true. */
89
+ verify?: boolean;
90
+ /** Probe http/https on each found host. Default false. */
91
+ web?: boolean;
92
+ /** Per-request web probe timeout in milliseconds. Default 5000. */
93
+ webTimeout?: number;
94
+ /**
95
+ * Reduce the target to its registrable domain via the Public Suffix List
96
+ * before enumerating (so "dev.example.co.uk" is scanned as "example.co.uk").
97
+ * Default true; set false to enumerate under the exact host given.
98
+ */
99
+ baseDomainOnly?: boolean;
100
+ /**
101
+ * When reducing to the registrable domain, use only the ICANN section of the
102
+ * Public Suffix List, ignoring private suffixes like github.io. Default false.
103
+ */
104
+ icannOnly?: boolean;
105
+ /** Injectable Public Suffix List rules, mainly for testing. */
106
+ psl?: PublicSuffixRules;
107
+ /** Abort the run; knock() rejects with the abort reason. */
108
+ signal?: AbortSignal;
109
+ /** Injectable resolver, mainly for testing. */
110
+ resolver?: KnockResolver;
111
+ /** Injectable fetch implementation used for the CT lookup. */
112
+ fetch?: KnockFetch;
113
+ /** Called with each result as it is discovered. */
114
+ onResult?: (result: KnockResult) => void;
115
+ }
116
+ /** Absolute paths to the wordlists bundled with the package. */
117
+ export declare const wordlists: {
118
+ subs: string;
119
+ org: string;
120
+ };
121
+ /**
122
+ * Reduce user input like "HTTPS://www.Example.com/path" to a bare hostname.
123
+ * Throws TypeError when no usable hostname can be extracted.
124
+ */
125
+ export declare function normalizeDomain(input: string): string;
126
+ /** Parse wordlist text into unique, lowercased labels. Blank lines and #comments are skipped. */
127
+ export declare function parseWordlist(text: string): string[];
128
+ /** Read and parse a wordlist file. */
129
+ export declare function loadWordlist(path: string): Promise<string[]>;
130
+ /**
131
+ * Query Certificate Transparency logs (via crt.sh) for names certified under
132
+ * `domain`. Purely passive: one HTTPS request, no DNS traffic to the target.
133
+ * Wildcard entries like "*.dev.example.com" are reported as "dev.example.com".
134
+ * Resolves to a sorted array of hostnames, the apex excluded.
135
+ */
136
+ export declare function certSubdomains(domain: string, options?: CertSubdomainsOptions): Promise<string[]>;
137
+ /**
138
+ * Enumerate subdomains of `domain`.
139
+ *
140
+ * Two sources feed the candidate set: Certificate Transparency logs
141
+ * (passive, `ct` option) and a wordlist brute force over DNS. Candidates
142
+ * are resolved concurrently; hosts that only echo a wildcard DNS answer are
143
+ * suppressed unless Certificate Transparency vouches for them.
144
+ */
145
+ export declare function knock(domain: string, options?: KnockOptions): Promise<KnockReport>;
146
+ export { publicSuffixListPath, parsePublicSuffixList, loadPublicSuffixList, getPublicSuffix, getRegistrableDomain, } from './psl.ts';
147
+ export type { PublicSuffixRule, PublicSuffixRules, PublicSuffixOptions } from './psl.ts';
148
+ export default knock;