Go Canary Collector
Gocanary is a simple collector of honeytokens that will generate alerts once a token has been interacted with.
Gocanary implements a DNS, HTTPS and HTTP honeytoken interaction traps.
The tokens are defined in a file, by default canary.yaml
The yaml is pretty simple and containts a sequence of canaries, example:
- key: 'mycanary1'
tag: 'gitlab-canary'
description: 'this canary is in gitlab project blah blah'
type: 'all'
alert: 'all'
level: 'low'
- key: 'mycanary2'
tag: 'gitlab-canary2'
description: 'test2'
level: 'low'
- key: 'mycanary3'
tag: 'gitlab-canary3'
description: 'test3 asdf lkasj kla sjlk j'
type: 'http'
alert: 'log'
level: 'low'
key
should be unique and will be token canary that needs to be exposed to the potential attackers.
tag
and level
are metadata that are included in all the alerts.
type
limits the types of alerts generated for that token.
The alert can have different sinks. Gocanary implements three sinks:
- slack: uses a webhook to send the alert using the slack/mattermost format
- log: prints to stdout or logfile
- syslog: send the alert to syslog
The alert content depends on the interaction trigger and contains both information of the token and the triggering source and system.
Eg:
{"time":"2024-05-16T10:49:16.374474022+02:00","level":"INFO","msg":"token-alert","Key":"mycanary1","Tag":"gitlab-canary","Level":"low","FullUrl":"http://myhost/test%20this/mycanary1/","UserAgent":"curl/7.81.0","RemoteIP":"127.0.0.1","RemotePort":49664,"LocalIP":"127.0.0.1","LocalPort":80,"Referer":"","Type":"token-http"}
DNS
The trap will be triggered when a domain that matches a honeytoken is resolved (gocanary implements a DNS resolver).
Eg: someone resolves mycanary1.domain
and this query reaches our gocanary resolver through NS delegation, i.e. domain is in reality subdomain.domain and domain nameservers delegate resolution of subdomain to our host
Beware that the remote ip will be typically the resolver that the client is using and not the IP of the potential attacker.
HTTP and HTTPS
The trap will be triggered when a URL that has either a token is defined that matches the last path component or the first component of the hostname.
Eg: A request is made to http://mycanary1.myhost.domain/whatever
or a request is made to http://myhost.domain/whatever/mycanary1
Running
Gocanary is a single binary that accepts command line options. Gocanary also reads a config file (default config.yaml
) where the same parameters that can be passed as arguments might alternatively be defined.
It is intended to be run as root
(to be able to bind to default DNS and WEB ports) and will drop privileges to nobody
and sandbox file access using landlock (https://docs.kernel.org/userspace-api/landlock.html)
It would be possible to run as nonroot and changing the different ports, and then using iptables/nftables to redirect traffic to it.
All configuration options can be defined in config.yaml. Example:
$ cat config.yaml
slack-hook: 'http://127.0.0.1/example'
For generating a self-signed certificate:
openssl req -new -newkey rsa:4096 -days 3650 -nodes -keyout cert.key -out cert.pem -x509 -subj "/C=CH/ST=GE/L=Geneva/O=CERN/CN=localhost.cern.ch"
All options:
gocanary is a honeytoken/canary collector daemon that listens for http/https/dns requests.
Alerts will be generated when a predefined haystack/honeytoken is detected.
Usage:
gocanary [flags]
Flags:
--autocert-domain stringArray Enable let's encrypt autocertificates (multiple accepted), https-cert and http-key will be ignored
-b, --bind-address string Ip address to bind servers to
--cache-dir string Writable directory for holding up autocertificates (default "./cache")
-c, --canary-file string File where canaries are defined (default "canary.yaml")
--dns-answer-with string IP address to give as an answer to DNS request matching a canary, if empty NXDOMAIN
--dns-not-answer Do not answer with any response, not even NXDOMAIN
--domain stringArray Only respond to this domain (multiple accepted)
--enable-dns Enable DNS listeners (tcp and udp) (default true)
--enable-hardening Enable extra hardening measures (default true)
--enable-http Enable HTTP listener (default true)
--enable-https Enable HTTPS listener
--enable-syslog Enable logging to syslog
-h, --help help for gocanary
--http-port uint16 Port for http server (default 80)
--https-cert string File containing the certificate in PEM format (default "cert.pem")
--https-key string File containing the certificate key in PEM format (default "cert.key")
--https-port uint16 Port for https server (default 443)
-s, --slack-hook string Webhook for alerts
--slack-silence uint16 Wait this many seconds between each slack alert (default 1)
The easiest way to run this is with docker compose.
The leanest way is to download the gocanary from the releases page and then use the docker-compose-inline.yml
The most compatible way to run is using the docker-compose-with-build.yml
, which will compile and run the project.
Except for the docker-compose-inline the compose file will need to be edited to at least bind only the public IPs and also to specify certificate options when using https support.