-
Notifications
You must be signed in to change notification settings - Fork 5
Home
pDNSSOC is a minimalistic component allowing DNS data to be centrally collected, and correlated with malicious domains / IPs from a MISP instance.
A complete pDNSSOC deployment requires:
- Access to a MISP instance (URL + API key are needed)
- A source of DNS data, for example:
-
dnstap
files (typically rsync'ed of SSH) - a DNS server with a
go-dnscollector
sender
-
- A pDNSSOC server: a
go-dnscollector
receiver + pDNSSOC
-
Create the user that will run the service:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin dnscollector
-
Define the version of the
go-dnscollector
that you want to install:GO_DNSCOLLECTOR_VERSION=$(curl -s https://api.github.com/repos/dmachard/go-dnscollector/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' | sed 's/^v//')
-
Install
go-dnscollector
curl -LO "https://github.com/dmachard/go-dnscollector/releases/download/v${GO_DNSCOLLECTOR_VERSION}/go-dnscollector_${GO_DNSCOLLECTOR_VERSION}_linux_amd64.tar.gz" && \ tar xvf "go-dnscollector_${GO_DNSCOLLECTOR_VERSION}_linux_amd64.tar.gz" && \ mv go-dnscollector /usr/bin/
-
Adjust the permissions for the user and create the directories needed to be able to run
go-dnscollector
:chmod +x /usr/bin/go-dnscollector chcon -t bin_t /usr/bin/go-dnscollector setcap cap_net_raw+ep /usr/bin/go-dnscollector chown dnscollector:dnscollector /usr/bin/go-dnscollector mkdir -p /var/dnscollector /var/dnscollector/alerts /var/dnscollector/queries /var/dnscollector/matches touch /var/dnscollector/alerts/matches.json /var/dnscollector/misp_ips.txt /var/dnscollector/misp_domains.txt /var/dnscollector/queries/queries.json /var/dnscollector/alerts_db.txt /var/dnscollector/matches/matches_domains.json /var/dnscollector/matches/matches_ips.json chown -R dnscollector:dnscollector /var/dnscollector/ chmod -R u+rw /var/dnscollector/
-
Adjust the configuration file, which is automatically generated as config.yml using the following templates:
mkdir -p /etc/dnscollector curl -o /etc/dnscollector/config.yml https://raw.githubusercontent.com/CERN-CERT/pDNSSOC/main/config/dnscollector/server.yml chown -R dnscollector:dnscollector /etc/dnscollector/ chmod -R u+rw /etc/dnscollector/ vi /etc/dnscollector/config.yml
-
Test the configuration file to make sure it doesn't have typos:
go-dnscollector -config /etc/dnscollector/config.yml -test-config
-
Execute the collector:
Configure the collector as a service:
curl -o /etc/systemd/system/dnscollector.service https://raw.githubusercontent.com/CERN-CERT/pDNSSOC/main/config/dnscollector/dnscollector.service
systemctl daemon-reload
systemctl start dnscollector
systemctl enable dnscollector
For debugging purposes, it is possible to start go-dnscollector
manually
go-dnscollector -config /etc/dnscollector/config.yml
- Ensure that the collecting port set in the configuration file is accessible and the port open. For example:
sudo firewall-cmd --zone=public --add-port=7001/tcp --permanent sudo firewall-cmd --zone=public --add-port=7001/udp --permanent sudo firewall-cmd --reload
-
Create the pdnssoc directory.
mkdir /etc/pdnssoccli
-
Install
pdnssoc-cli
pip3 install git+https://github.com/safer-trust/pdnssoc-cli.git
-
Create the pdnssoccli configuration file (
pdnssoccli.yml
) under/etc/pdnssoccli
and modify it based on the pdnssoccli template. For details, see the configuration documentation.curl -o /etc/pdnssoccli/pdnssoccli.yml https://raw.githubusercontent.com/safer-trust/pdnssoc-cli/refs/heads/main/config/pdnssoccli.yml chown -R dnscollector:dnscollector /etc/pdnssoccli vi /etc/pdnssoccli/pdnssoccli.yml
-
Create the cronjob to automate correlation and alerting:
curl -o /etc/cron.d/pdnssoccli https://raw.githubusercontent.com/CERN-CERT/pDNSSOC/main/config/pdnssoccli/pdnssoccli.cron service crond reload
-
Create the user that will run the service:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin dnscollector
-
Define the version of the
go-dnscollector
that you want to install:GO_DNSCOLLECTOR_VERSION=$(curl -s https://api.github.com/repos/dmachard/go-dnscollector/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' | sed 's/^v//')
-
Install
go-dnscollector
curl -LO "https://github.com/dmachard/go-dnscollector/releases/download/v${GO_DNSCOLLECTOR_VERSION}/go-dnscollector_${GO_DNSCOLLECTOR_VERSION}_linux_amd64.tar.gz" && \ tar xvf "go-dnscollector_${GO_DNSCOLLECTOR_VERSION}_linux_amd64.tar.gz" && \ mv go-dnscollector /usr/bin/
-
Adjust the permissions for the user and create the directories needed to be able to run
go-dnscollector
:chmod +x /usr/bin/go-dnscollector chcon -t bin_t /usr/bin/go-dnscollector setcap cap_net_raw+ep /usr/bin/go-dnscollector chown dnscollector:dnscollector /usr/bin/go-dnscollector mkdir -p /var/dnscollector chown -R dnscollector:dnscollector /var/dnscollector/ chmod -R u+rw /var/dnscollector/
-
Adjust the configuration file, which is automatically generated as config.yml using the following templates:
mkdir -p /etc/dnscollector curl -o /etc/dnscollector/config.yml https://raw.githubusercontent.com/CERN-CERT/pDNSSOC/main/config/dnscollector/client.yml chown -R dnscollector:dnscollector /etc/dnscollector/ chmod -R u+rw /etc/dnscollector/ vi /etc/dnscollector/config.yml
-
Test the configuration file to make sure it doesn't have typos:
go-dnscollector -config /etc/dnscollector/config.yml -test-config
-
Execute the collector:
Configure the collector as a service:
curl -o /etc/systemd/system/dnscollector.service https://raw.githubusercontent.com/CERN-CERT/pDNSSOC/main/config/dnscollector/dnscollector.service
systemctl daemon-reload
systemctl start dnscollector
systemctl enable dnscollector
For debugging purposes, it is possible to start go-dnscollector
manually
go-dnscollector -config /etc/dnscollector/config.yml
- Check if the service is running and its logs:
# systemctl status dnscollector
# journalctl -u dnscollector -f
- Check if the process is running:
# ps -aux | grep dnscollector
dnscoll+ 37571 0.0 1.1 1395372 40108 ? Ssl May23 2:03 /usr/bin/go-dnscollector -c /etc/dnscollector/config.yml
-
Check if the connection has been established. We will use the port 7001 as example:
A. From the DNS sensor:
# netstat -putan | grep 7001 tcp 0 0 IP_DNS:59450 IP_PDNSSOC:7001 ESTABLISHED 37571/go-dnscollect
B. From pDNSSOC:
# netstat -putan | grep 7001 tcp6 0 0 :::7001 :::* LISTEN 19378/go-dnscollect tcp6 0 0 IP_PDNSSOC:7001 IP_DNS:59450 ESTABLISHED 19378/go-dnscollect
-
Check if the pDNSSOC collector is receiving logs:
# tail /var/dnscollector/queries.json
# tcpdump -i eth0 -A port 7001
- Check the location where pDNSSOC was installed:
# pip show pdnssoc-cli
- Verify that the pDNSSOC command line tool works
# pdnssoc-cli fetch-iocs
# pdnssoc-cli correlate
# pdnssoc-cli alert
- Verify that pdnssoccli.yml has a right format
# pip install yamllint
# yamllint /etc/pdnssoccli/pdnssoccli.yml
- Check if the IOCs could be fetched from MISP
# tail /var/dnscollector/misp_domains.txt
# tail /var/dnscollector/misp_ips.txt
- Test a malicious domain resolution to check that the alerts are created. You can use any domain from the misp_domains.txt,
# dig @IP_DNS maliciousdomain.com
# cat /var/dnscollector/queries.json | grep maliciousdomain.com
- You just need to download the template from github and put it in
/etc/pdnssoccli
as a file calledalert_email.html
- Add your webhook to the
/etc/pdnssoccli/pdnssoccli.yml
file (template can be found here)- It is now tested for Slack and Mattermost
- You use templates of the messages
- Under the 'alerting' header, add the following configuration:
slack: hook: "https://hooks.slack.com/services/your_hook" template: "/etc/pdnssoccli/slack.template" mattermost: hook: "https://hooks.mattermost.com/services/your_hook" template: "/etc/pdnssoccli/mattermost.template"
-
Create a telegram bot which will be used for the pDNSSOC alerts:
-
Search for 'BotFather' in telegram and write '/newbot' in the chat
-
Follow the instructions and keep note of the API key given to you once the bot is created
-
Once the bot has been added, find the telegram channel ID. You can use the following script:
import requests bot_token = 'API_TOKEN' response = requests.get("https://api.telegram.org/bot{bot_token}/getUpdates") data = response.json() if data['result']: for result in data['result']: print("Chat ID: ", result['message']['chat']['id'])
-
-
Now that you have your telegram bot and API key, you need to change the configuration file of your pdnssoc-cli program:
- Add the following under the 'alerting' tab of the pdnssoc-cli config file (
/etc/pdnssoccli/pdnssoccli.yml
):telegram: telegram_chat_id: <your_telegram_chat_ID> telegram_bot_token: <your_telegram_bot_API_key> template: "/etc/pdnssoccli/telegram.template"
- Add the following under the 'alerting' tab of the pdnssoc-cli config file (
-
You can test this has worked by trying to send an alert using the command
pdnssoc-cli alert
-
If you have already installed pdnssoc-cli on your machine you will need to run the commands below to update it:
git clone https://github.com/safer-trust/pdnssoc-cli.git cd pdnssoc-cli/ python3.11 -m pip install --force-reinstall .
To set up a test environment, you can easily deploy a Bind9 DNS server by following the steps outlined below. Please note that the provided template and installation instructions are intended for testing purposes only and are NOT suitable for a production environment. For best practices and production setups, please refer to the Official Documentation.
- Install Bind9
dnf copr enable isc/bind yum install isc-bind
- Create log directory and edit the
name.conf
file using the templatemkdir -p /var/log/named chown named:named /var/log/named curl -o /etc/opt/isc/scls/isc-bind/named.conf https://raw.githubusercontent.com/CERN-CERT/pDNSSOC/main/config/test_lab/named.conf vim /etc/opt/isc/scls/isc-bind/named.conf chown named:named /etc/opt/isc/scls/isc-bind/named.conf sudo -u named /opt/isc/isc-bind/root/usr/bin/named-checkconf /etc/opt/isc/scls/isc-bind/named.conf
- Start and enable the DNS service
systemctl start isc-bind-named systemctl enable isc-bind-named systemctl status isc-bind-named
- Open the internal firewall if you want to resolve domains from other instances
systemctl start firewalld systemctl enable firewalld firewall-cmd --permanent --add-service=dns firewall-cmd --reload firewall-cmd --list-all
- Check that the DNS can resolve domains.
host1# dig @IP_DNS maliciousdomain.com
dns# /opt/isc/isc-bind/root/usr/bin/dnstap-read /var/log/named/dnstap.log
27-May-2024 17:57:01.255 CQ IP_HOST1:47263 -> IP_DNS:53 UDP 49b maliciousdomain.com/IN/A