Like "Canary" but more hipster, which means better 😎😎😎
knary is a canary token server that notifies a Slack/Discord/Teams/Lark/Telegram channel (or other webhook) when incoming HTTP(S) or DNS requests match a given domain or any of its subdomains. It also supports functionality useful in offensive engagements including subdomain allow/denylisting, working with Burp Collaborator, and automatic TLS certificate creation with Let's Encrypt.
Redteamers use canaries to be notified when someone (or something) attempts to interact with a server they control. Canaries help provide visibility over processes that were previously unknown. They can help find areas to probe for RFI or SSRF vulnerabilities, disclose previously unknown servers, provide evidence of an intercepting device, or just announce someone interacting with your server.
Defenders also use canaries as tripwires that can alert them of an attacker within their network by having the attacker announce themselves. If you are a defender, https://canarytokens.org might be what you’re looking for.
Prerequisite: You need Go >=1.16 to build knary.
go install github.com/sudosammy/knary/[email protected]
Important: The specifics of how to perform the next two steps will depend on your domain registrar. Google
How to set Glue Record on <registrar name> to get started. Ultimately, you need to configure your knary domain(s) to make use of itself as the nameserver (i.e.
ns2.knary.tld) and configure Glue Records to point these nameservers back to your knary host. You may need to raise a support ticket to have this performed by your registrar.
Set your chosen knary domain(s) nameserver(s) to point to a subdomain under itself; such as
ns.knary.tld. If required, set multiple nameserver records such as
Create a "Glue Record" (sometimes referred to as "Nameserver Registration" or "Nameserver IP address") to point to your knary server. This is what it looks like in
If your registry requires you to have multiple nameservers with different IP addresses, set the second nameserver to an IP address such as
This will take time to propagate, so go setup your webhook(s) while you wait. You can use this tool to check the propagation. Within a few hours you should see some DNS servers reflecting your knary domain as the nameserver.
.env file in the same directory as the knary binary and configure it as necessary. You can also use environment variables to set these configurations. Environment variables will take precedence over the
Optional For accepting TLS (HTTPS) connections set the
LETS_ENCRYPT=<email address> variable and knary will automagically manage wildcard certificates for you (see OPSEC note below). Otherwise, you can specify the path to your own certificates with
Run the binary (via the provided Docker container, or in
screen) and hope for output that looks something like this:
You will find systems that spam your knary even long after an engagement has ended. You will also find several DNS requests to mundane subdomains hitting your knary every day. To stop these from cluttering your notifications knary has a few features:
ALLOWLIST_FILE). Add the subdomains or IP addresses separated by a newline (case-insensitive):
knary.tld www.knary.tld 22.214.171.124 test.dns.knary.tld sam.knary.tld
If this were a denylist, it would stop knary from alerting on
www.knary.tld but not
If this were an allowlist, knary would alert on exact matches (
sam.knary.tld) and subdomain matches (
ALLOWLIST_STRICT=true to prevent this fuzzy matching and only alert on hits to
You can use both a deny and allowlist simultaneously. Note: wildcards in these files are not supported. An entry of
*.knary.tld will match that string exactly.
DNS_SUBDOMAINconfiguration allows you to specify a subdomain that knary must fuzzy match (i.e.
*.DNS_SUBDOMAIN.knary.tld) before alerting on DNS hits. This configuration does not affect HTTP(S) requests and remains primarily to mimic legacy knary v2 functionality. Consider using a deny/allowlist instead.
A configuration of
DNS_SUBDOMAIN=dns would stop knary from alerting on DNS hits to
blah.knary.tld but not
blah.dns.knary.tld. A HTTP request to
blah.knary.tld would still notify you unless prevented by an allow- or denylist.
Sample configurations can be found in the examples with common subdomains to deny.
Using knary in a container is as simple as creating your
.env file (or setting environment variables in the
docker-compose.yaml file) and running
sudo docker compose up -d
BURP_DOMAINif you are using those configurations). This is due to these domains being included in the SAN certificate generated for you. A remote adversary can read the certificate and extract the list of domains within it. To avoid this, don't configure
LETS_ENCRYPT. You can use self-signed certificates with
TLS_KEY=<path>; however, many hosts will refuse to connect reducing your visibility of incoming HTTPS connections.
These are environment variables /
.env file configurations. You can configure none, one, or many. Most common usage would be to configure one. Refer to the examples for usage help.
SLACK_WEBHOOKThe full URL of the incoming webhook for the Slack channel you want knary to notify
DISCORD_WEBHOOKThe full URL of the Discord webhook for the Discord channel you want knary to notify
TEAMS_WEBHOOKThe full URL of the Microsoft Teams webhook for the Teams channel you want knary to notify
PUSHOVER_TOKENThe application token for the Pushover Application you want knary to notify
PUSHOVER_USERThe user token of the Pushover user you want knary to notify
LARK_WEBHOOKThe full URL of the webhook for the Lark/Feishu bot you want knary to notify
LARK_SECRETThe secret token used to sign messages to your Lark/Feishu bot
TELEGRAM_CHATIDThe Telegram Bot chat ID you want knary to notify
TELEGRAM_BOT_TOKENThe Telegram Bot token