This is a highly-opinionated personal tool for interacting with various disparate networks, systems, and other resources of interest to me.
These used to be several CLIs, but the time has come to bring them together!
- Install
- Usage
xunnctl
(Entry Point)xunnctl config
xunnctl config get
xunnctl config set
xunnctl config unset
xunnctl dns record create A
xunnctl dns record create AAAA
xunnctl dns record create CAA
xunnctl dns record create CNAME
xunnctl dns record create MX
xunnctl dns record create TXT
xunnctl dns record retrieve
xunnctl dns record destroy
xunnctl dns zone
xunnctl dns zone create
xunnctl dns zone retrieve
xunnctl dns zone update
xunnctl dns zone destroy
xunnctl firewall
xunnctl firewall ban
xunnctl firewall status
xunnctl firewall unban
xunnctl raw
xunnctl super install
xunnctl super uninstall
- Appendix
- Contributing and Support
You can install this package globally:
npm install --global @-xun/ctl
And then execute the CLI:
npx xunnctl ...
Alternatively, you can use npx to execute the CLI without pre-installation:
npx @-xun/ctl ...
Be careful running commands with huge footprints (e.g. using the
--apex-all-known
parameter) in quick succession. Take note of the rate limits for the APIs you're invoking.
For first time usage, or if credentials are inaccessible, you will be prompted
to enter your credentials, which will be saved locally. You can do this
manually at any time via xunnctl config set
.
From there, you can begin issuing commands. Commands are organized
hierarchically, starting with the bare xunnctl
command at the root. For the
most up-to-date list of available commands and flags, use xunnctl ... --help
.
You can also use the xctl
and x
aliases, e.g. x --help
. Most commands also
have a single-letter alias, which is always the first letter of that command.
There are many individual commands available, each with their own accepted parameters and help text. These commands also share several standard parameters which can be found in the following table:
Name | Type | Default | Description | |
---|---|---|---|---|
optional | --config-path |
string | OS-dependent (XDG on linux) | Path to the xunnctl configuration file. |
optional | --help |
boolean | undefined | Show command-specific help text. Cannot be used with other parameters or sub-commands. |
optional | --hush |
boolean | false | The program output will be somewhat less verbose than usual. |
optional | --quiet |
boolean | false | The program output will be dramatically less verbose than usual. Implies (and takes precedence over) --hush . |
optional | --silent |
boolean | false | The program will not output anything at all. Implies (and takes precedence over) --quiet and --hush . |
Some commands have an additional --force
parameter that is required whenever
an exceedingly dangerous operation is requested. While present in help text
output, this parameter will not be mentioned in this documentation going
forward.
Currently, the available commands are:
Alias:
xctl
,x
This command is the entry point into the CLI and as such can be used to retrieve
metadata about the xunnctl
software itself, including the currently installed
version number.
xunnctl --version
xctl --version
x --version
Name | Type | Default | Description | |
---|---|---|---|---|
optional | --version |
boolean | undefined | Show version number. Cannot be used with other parameters or sub-commands. |
Alias:
x c
This command, unless called with --help
, is an alias for
xunnctl config get --all
.
xunnctl config
x c
See xunnctl config get
.
Alias:
x c g
This command dumps the value of one or more xunnctl
configuration options
straight to stdout without additional outputs, making it suitable for use in
scripts. These values are stored locally and protected with 0660
permissions.
See here for a list of available configuration options.
When called without any arguments, this command is an alias for
xunnctl config get --all
.
xunnctl config get --sub-name cfApiToken
x c g --sub-name cfApiToken cfAccountId
x c g --sub-name cfApiToken --sub-name cfAccountId
# The next two lines are equivalent
x c g --all
x c g
Name | Type | Default | Description | |
---|---|---|---|---|
optional | --all |
boolean | undefined | Dump the current value of all configuration options. Cannot be used with the --sub-name parameter. |
optional | --sub-name |
string[] | undefined | The names of one or more options to retrieve. Cannot be used with the --all parameter. |
Alias:
x c s
This command updates the value of the --sub-name
configuration option to
--content
, which is a valid JSON value. This includes double quotes if it's a
string.
This value is stored locally and protected with 0660
permissions.
Note that --content
can be any value JSON value, and that updating an option
with the wrong value or type of value will cause undefined behavior. See
here for a list of available configuration options and their valid values.
xunnctl config set --sub-name cfApiToken --content AbCd1234
x c s --sub-name cfApiToken --content AbCd1234
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED | --content |
string (unescaped spaces allowed) |
undefined | The new value of the option to update. This must be a valid JSON value. |
REQUIRED | --sub-name |
string | undefined | The name of the option to update. |
Alias:
x c u
This command deletes the configuration entry (name and content) associated with
the --sub-name
configuration option and commits the change to the filesystem.
xunnctl config unset --sub-name cfApiToken
x c u --sub-name cfApiToken
Name | Type | Default | Description | |
---|---|---|---|---|
optional | --all |
boolean | undefined | Delete all options in the configuration file. Cannot be used with the --sub-name parameter. |
optional | --sub-name |
string[] | undefined | The names of one or more options to delete. Cannot be used with the --all parameter. |
Alias:
x d r c a
This command creates a new DNS A resource record in one or more existing zones.
xunnctl dns record create a --apex xunn.io --sub-name @ --ipv4 1.2.3.4 --proxied=false
x d r c A --apex xunn.io --sub-name 'something.else' --ipv4 1.2.3.4
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED 1/2 | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
REQUIRED 2/2 | --apex-all-known |
boolean | undefined | Include all known zone apex domains. Can be used with other --apex* parameters. |
REQUIRED | --ipv4 |
string | undefined | A valid IPv4 address. |
REQUIRED | --sub-name |
string | undefined | The DNS record name in Punycode, or the character "@", but excluding the apex domain as a suffix. |
optional | --proxied |
boolean | false | Whether the record is receiving the performance and security benefits of Cloudflare. |
Alias:
x d r c aaaa
This command creates a new DNS AAAA resource record in one or more existing zones.
xunnctl dns record create aaaa --apex xunn.io --sub-name @ --ipv6 ::ffff:1.2.3.4 --proxied=false
x d r c AAAA --apex xunn.io --sub-name 'something.else' --ipv6 2001:db8::8a2e:7334
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED 1/2 | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
REQUIRED 2/2 | --apex-all-known |
boolean | undefined | Include all known zone apex domains. Can be used with other --apex* parameters. |
REQUIRED | --ipv6 |
string | undefined | A valid IPv6 address. |
REQUIRED | --sub-name |
string | undefined | The DNS record name in Punycode, or the character "@", but excluding the apex domain as a suffix. |
optional | --proxied |
boolean | false | Whether the record is receiving the performance and security benefits of Cloudflare. |
Alias:
x d r c caa
This command creates pre-configured "issue" and "iodef" CAA resource records in one or more existing zones.
xunnctl dns record create caa --apex xunn.io
x d r c CAA --apex xunn.io --apex xunn.at
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED 1/2 | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
REQUIRED 2/2 | --apex-all-known |
boolean | undefined | Include all known zone apex domains. Can be used with other --apex* parameters. |
Alias:
x d r c cname
This command creates a new DNS CNAME resource record in one or more existing zones.
xunnctl dns record create cname --apex xunn.io --sub-name 'sub.domain' --to-name 'diff.com'
x d r c CNAME --apex xunn.io --apex xunn.at --sub-name 'sub.domain' --to-name 'diff.com'
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED 1/2 | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
REQUIRED 2/2 | --apex-all-known |
boolean | undefined | Include all known zone apex domains. Can be used with other --apex* parameters. |
REQUIRED | --sub-name |
string | undefined | The DNS record name in Punycode, or the character "@", but excluding the apex domain as a suffix. |
REQUIRED | --to-name |
string | undefined | A valid fully-qualified hostname. Must not match the record's name. |
optional | --proxied |
boolean | false | Whether the record is receiving the performance and security benefits of Cloudflare. |
Alias:
x d r c mx
This command creates a new DNS MX resource record in one or more existing zones.
xunnctl dns record create mx --apex xunn.io --sub-name '@' --mail-name 'mail.xunn.io'
x d r c MX --apex xunn.io --apex xunn.at --sub-name 'something.else' --mail-name 'mail.xunn.io'
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED 1/2 | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
REQUIRED 2/2 | --apex-all-known |
boolean | undefined | Include all known zone apex domains. Can be used with other --apex* parameters. |
REQUIRED | --sub-name |
string | undefined | The DNS record name in Punycode, or the character "@", but excluding the apex domain as a suffix. |
REQUIRED | --mail-name |
string | undefined | A valid fully-qualified mail server hostname. |
Alias:
x d r c txt
This command creates a new DNS TXT resource record in one or more existing zones.
xunnctl dns record create txt --apex xunn.io --sub-name @ --content '...'
x d r c TXT --apex xunn.io --apex xunn.at --sub-name 'something.else' --content '...'
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED 1/2 | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
REQUIRED 2/2 | --apex-all-known |
boolean | undefined | Include all known zone apex domains. Can be used with other --apex* parameters. |
REQUIRED | --sub-name |
string | undefined | The DNS record name in Punycode, or the character "@", but excluding the apex domain as a suffix. |
REQUIRED | --content |
string | undefined | Text content for the record. |
Alias:
x d r r
This command retrieves one or more resource records of name --target-name
and/or of type --target-type
from the specified --apex*
DNS zone(s). If
--search-for-name
is given, --target-name
will be matched partially (via
startsWith()
) rather than exactly.
Omitting both --target-name
and --target-type
will retrieve all records.
The result can be queried via --local-query
, which accepts a JMESPath
value. Note that, as a feature, the presence of spaces in the query does not
necessitate quoting or escaping. When --local-query
is present, the resulting
JSON will be dumped straight to stdout.
xunnctl dns record retrieve --apex xunn.io --target-name mail --target-type CNAME
x d r r --apex-all-known --apex new-site.com --target-name mail
x d r r --apex xunn.io --apex xunn.at --target-type cname --local-query id
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED 1/2 | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
REQUIRED 2/2 | --apex-all-known |
boolean | undefined | Include all known zone apex domains. Can be used with other --apex* parameters. |
optional | --target-name |
string | undefined | The target DNS record name in Punycode, including the apex domain as a suffix. Note that the "@" character is not recognized here. |
optional | --target-type |
string | undefined | Case-insensitive DNS record type, such as AAAA or mx . |
optional | --local-query |
string (unescaped spaces allowed) |
undefined | A JMESPath query string. Unescaped spaces are preserved in CLI. The resulting JSON will be dumped straight to stdout. |
optional | --search-for-name |
boolean |
false | Match names starting with --target-name instead of matching said names exactly, which is the default behavior. |
Alias:
x d r d
This command irrecoverably destroys one or more resource records that are named
--target-name
and are of type --target-type
from the specified --apex*
DNS
zone(s). If no such record(s) exist, this command is a no-op.
If --search-for-name
is given, --target-name
will be matched partially (via
startsWith()
) rather than exactly.
xunnctl dns record destroy --apex dangerous.com --target-name some.specific.record --target-type CNAME
xunnctl d r d --apex dangerous.com --target-name some.specific.record --target-type cname
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED 1/2 | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
REQUIRED 2/2 | --apex-all-known |
boolean | undefined | Include all known zone apex domains. Can be used with other --apex* parameters. Note that this is incredibly dangerous! |
REQUIRED | --target-name |
string | undefined | The target DNS record name in Punycode, including the apex domain as a suffix. Note that the "@" character is not recognized here. |
REQUIRED | --target-type |
string | undefined | Case-insensitive DNS record type, such as AAAA or mx . |
optional | --search-for-name |
boolean |
false | Match names starting with --target-name instead of matching said names exactly, which is the default behavior. |
Alias:
x d z
This command, unless called with --help
, is an alias for
xunnctl dns zone retrieve --apex-all-known
.
xunnctl dns zone
x d z
See xunnctl dns zone retrieve
.
Alias:
x d z c
This command creates and initializes a new DNS --apex
zone. If a conflicting
apex zone already exists, this command will fail. If you're trying to bring an
existing zone up to current configuration standards, see
xunnctl dns zone update
instead.
xunnctl dns zone create --apex xunn.at
x d z c --apex xunn.at
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
Alias:
x d z r
This command returns information about one or more --apex
zones.
The result can be queried via --local-query
, which accepts a JMESPath
value. Note that, as a feature, the presence of spaces in the query does not
necessitate quoting or escaping. When --local-query
is present, the resulting
JSON will be dumped straight to stdout.
xunnctl dns zone retrieve --apex xunn.at
x d z r --apex-all-known --apex new-site.com --local-query id
x d z r --apex xunn.io --apex xunn.at --local-query { id: id, cdnOnly: meta.cdn_only }
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED 1/2 | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
REQUIRED 2/2 | --apex-all-known |
boolean | undefined | Include all known zone apex domains. Can be used with other --apex* parameters. |
optional | --local-query |
string (unescaped spaces allowed) |
undefined | A JMESPath query string. Unescaped spaces are preserved in CLI. The resulting JSON will be dumped straight to stdout. |
Alias:
x d z u
This command is equivalent to xunnctl dns zone create
but for zones that
already exist. It will attempt to bring one or more zones up to date with the
latest best practices with respect to zone configuration; any failures thrown
when attempting to create records, while reported, are ignored. No records are
deleted or updated, only creations will be attempted.
xunnctl dns zone update --apex-all-known
x d z u --apex xunn.at --apex xunn.io
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED 1/2 | --apex |
string[] | undefined | Zero or more zone apex domains. Can be used with other --apex* parameters. |
REQUIRED 2/2 | --apex-all-known |
boolean | undefined | Include all known zone apex domains. Can be used with other --apex* parameters. |
optional | --purge-first |
boolean | undefined | Delete pertinent records on the zone before recreating them. This can be dangerous! |
Alias:
x d z d
This command irrecoverably destroys a DNS --apex
zone. If no such zone exists,
this command is a no-op.
xunnctl dns zone destroy --apex be-careful.org
x d z d --apex dangerous.com
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED | --apex |
string | undefined | An apex domain to destroy. |
Alias:
x f
This command, unless called with --help
, is an alias for
xunnctl firewall status
.
xunnctl firewall
x f
Alias:
x f b
This command adds an ip address to the global hostile ip list, which is a Cloudflare WAF List. No managed system will accept packets coming from an IP on this list.
All IP formats supported by Cloudflare WAF Lists are supported. Additionally, full ipv6 addresses will be translated into the supported ipv6 CIDR double colon notation.
xunnctl firewall ban --ip 1.2.3.4 --ip 5.6.7.8
# Cloudflare doesn't support the following, but this CLI does:
x f b --ip 2600:8800:51a1:1234:5678:9101:2007:76eb
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED | --ip |
string[] | undefined | One or more IP addresses to ban. All IP formats supported by Cloudflare WAF Lists are supported here. Full ipv6 addresses are also supported (converted to /64 CIDRs). |
Alias:
x f s
This command returns the contents of the global hostile ip list, which is a Cloudflare WAF List. No managed system will accept packets coming from an IP on this list.
All IP formats supported by Cloudflare WAF Lists are supported. Additionally, full ipv6 addresses will be translated into the supported ipv6 CIDR double colon notation.
xunnctl firewall status
x f s --ip 5.6.7.8 --ip 2600:8800:51a1:1234:5678:9101:2007:76eb
Name | Type | Default | Description | |
---|---|---|---|---|
optional | --ip |
string[] | undefined | One or more IP addresses to report on. All IP formats supported by Cloudflare WAF Lists are supported here. Full ipv6 addresses are also supported (converted to /64 CIDRs). |
Alias:
x f u
This command removes an ip address from the global hostile ip list, which is a Cloudflare WAF List. No managed system will accept packets coming from an IP on this list.
All IP formats supported by Cloudflare WAF Lists are supported. Additionally, full ipv6 addresses will be translated into the supported ipv6 CIDR double colon notation.
xunnctl firewall unban --ip 1.2.3.4 --ip 5.6.7.8
# Cloudflare doesn't support the following, but this CLI does:
x f u --ip 2600:8800:51a1:1234:5678:9101:2007:76eb
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED | --ip |
string[] | undefined | One or more IP address to unban. All IP formats supported by Cloudflare WAF Lists are supported here. Full ipv6 addresses are also supported (converted to /64 CIDRs). |
optional | --if-comment-excludes |
string | undefined | Only unban if --ip 's comment does not include the given text. |
Alias:
x r
This command will dump freeform data into stdout depending on --id
and without
additional outputs, making it suitable for use in scripts.
The following values for --id
are supported:
This is an nginx configuration file consisting of directives that, when included in an server context, will cause nginx to reject all connection attempts from IP addresses that do not belong to Cloudflare.
When using this ID, you can also pipe in the contents of an nginx configuration
file and it will be included in the output with respect for the lines consisting
of ### START AUTOGENERATED RULES
and ### END AUTOGENERATED RULES
. For
example:
echo 'before\n### START AUTOGENERATED RULES\n\nx\ny\nz\n\n### END AUTOGENERATED RULES\nafter\n' | npx x r --id conf.nginx.allowOnlyCloudflare
Note that deny all;
should be included in your Nginx configuration for it to
be meaningful. This tool will not add it for you. For example:
...
### START AUTOGENERATED RULES
...
### END AUTOGENERATED RULES
allow 127.0.0.0/8;
allow ::1/128;
deny all;
xunnctl raw --id conf.nginx.allowOnlyCloudflare
x r --id conf.nginx.allowOnlyCloudflare
Name | Type | Default | Description | |
---|---|---|---|---|
REQUIRED | --id |
string | undefined | The identifier associated with the target data. |
Alias:
x s i
This command will install several privileged commands from a private repository. These commands will be dynamically added to xunnctl, potentially updating existing commands in the process, thus greatly expanding the available commands beyond those listed in this documentation.
This command is idempotent so long as the contents of said private repository remain unchanged. Running this command after said repository has been updated will install the updates but will not synchronize deletes.
To completely clear out installed commands, see xunnctl super uninstall
.
xunnctl super install
x s i
This command does not accept additional parameters.
Alias:
x s u
This command will completely uninstall any command that has ever been downloaded
and installed by xunnctl super install
. Downloaded commands that overwrote
their public versions will be reverted.
To reinstall all available privileged commands, see
xunnctl super install
xunnctl super uninstall
x s u
This command does not accept additional parameters.
Further documentation can be found under docs/
.
This is a CJS2 package with statically-analyzable exports
built by Babel for Node.js versions that are not end-of-life. For TypeScript
users, this package supports both "Node10"
and "Node16"
module resolution
strategies.
Expand details
That means both CJS2 (via require(...)
) and ESM (via import { ... } from ...
or await import(...)
) source will load this package from the same entry points
when using Node. This has several benefits, the foremost being: less code
shipped/smaller package size, avoiding dual package
hazard entirely, distributables are not
packed/bundled/uglified, a drastically less complex build process, and CJS
consumers aren't shafted.
Each entry point (i.e. ENTRY
) in package.json
's
exports[ENTRY]
object includes one or more export
conditions. These entries may or may not include: an
exports[ENTRY].types
condition pointing to a type
declarations file for TypeScript and IDEs, an
exports[ENTRY].module
condition pointing to
(usually ESM) source for Webpack/Rollup, an exports[ENTRY].node
condition
pointing to (usually CJS2) source for Node.js require
and import
, an
exports[ENTRY].default
condition pointing to source for browsers and other
environments, and other conditions not enumerated
here. Check the package.json file to see which export
conditions are supported.
Though package.json
includes
{ "type": "commonjs" }
, note that any ESM-only entry points will
be ES module (.mjs
) files. Finally, package.json
also
includes the sideEffects
key, which is false
for
optimal tree shaking where appropriate.
See LICENSE.
New issues and pull requests are always welcome and greatly appreciated! π€© Just as well, you can star π this project to let me know you found it useful! βπΏ Or you could buy me a beer π₯ΊThank you!
See CONTRIBUTING.md and SUPPORT.md for more information.
Thanks goes to these wonderful people (emoji key):
Bernard π π» π π§ |
||||||
Add your contributions |
This project follows the all-contributors specification. Contributions of any kind welcome!