% DNSMonitor.app/Contents/MacOS/DNSMonitor
...
PROCESS:
{
processID = 17357;
processPath = "/usr/bin/nslookup";
processSigningID = "com.apple.nslookup";
}
PACKET:
Xid: 10948
QR: Query
Server: -nil-
Opcode: Standard
AA: Non-Authoritative
TC: Non-Truncated
RD: Recursion desired
RA: No recursion available
Rcode: No error
Question (1):
objective-see.org IN A
Answer (0):
Authority (0):
Additional records (0):
Running DNSMonitor
After copying DNSMonitor to the /Applications directory, launch it by executing its binary (DNSMonitor.app/Contents/MacOS/DNSMonitor) via the Terminal:
% DNSMonitor.app/Contents/MacOS/DNSMonitor -h
DNSMonitor usage:
-h or -help Display this usage info
-json Output is formatted as JSON
-pretty JSON output is 'pretty-printed'
-nx Block via 'NX' packet
-daemon Run in 'daemon' mode (extension won't be unloaded)
-unload Unload extension
-block File of domains / ip addresses to block
When run with no arguments, DNSMonitor will begin monitoring for and printing out DNS packets:
% DNSMonitor.app/Contents/MacOS/DNSMonitor
PROCESS:
{
processID = 17357;
processPath = "/usr/bin/nslookup";
processSigningID = "com.apple.nslookup";
}
PACKET:
Xid: 10948
QR: Query
Server: -nil-
Opcode: Standard
AA: Non-Authoritative
TC: Non-Truncated
RD: Recursion desired
RA: No recursion available
Rcode: No error
Question (1):
objective-see.org IN A
Answer (0):
Authority (0):
Additional records (0):
When run with the -json
commandline option DNS packets will be output as JSON. The -pretty
option will cause the JSON to be "pretty printed":
% DNSMonitor.app/Contents/MacOS/DNSMonitor -json -pretty
[{
"Process" : {
"processPath" : "\/usr\/bin\/nslookup",
"processSigningID" : "com.apple.nslookup",
"processID" : 17493
},
"Packet" : {
"Opcode" : "Standard",
"QR" : "Query",
"Questions" : [
{
"Question Name" : "objective-see.org",
"Question Class" : "IN",
"Question Type" : "A "
}
],
"RA" : "No recursion available",
"Rcode" : "No error",
"RD" : "Recursion desired",
"XID" : 63159,
"TC" : "Non-Truncated",
"AA" : "Non-Authoritative"
}
},
...
Via the -block
flag, you can specify the path to file containing domains and IP addresses that DNSMonitor will block. The format of this file should be a JSON array. For example, if you wanted to block DNS resolutions of google either by name or by (one of) its IP addresses:
[
"google.com",
"172.217.175.46"
]
Now, once DNSMonitor is off and running with this blocklist (e.g. DNSMonitor.app/Contents/MacOS/DNSMonitor -block blocklist.json
), requests, for example to google.com will be blocked, and thus the request will simply timeout:
% nslookup google.com
;; connection timed out; no servers could be reached
Note that by default, to block a DNS query or response, the network flow is simply closed out. However, if you execute DNSMonitor with the -nx
commandline option, it will instead return an "NX" response, indicating that the domain does not exist.
You can also dump DNSMonitor's 'cache', by sending it a -USR1
signal to com.objective-see.dnsmonitor.extension
:
# kill -USR1 <pid of com.objective-see.dnsmonitor.extension>
% DNSMonitor.app/Contents/MacOS/DNSMonitor
Received signal: USR1
Dumping DNS Cache:
google.com:(
"142.250.176.14"
)
objective-see.org:(
"185.199.109.153",
"185.199.110.153"
)
gateway.icloud.com:(
"17.248.245.38",
"17.248.245.43",
"17.248.245.45",
...
)
Note:
Though DNSMonitor is distributed as an application (in order to satisfy Apple's codesigning, notarization, and System/Network extension requirements), it is a CLI utility. As such, it should be executed from the commandline, by specifying the path to its application binary:
DNSMonitor.app/Contents/MacOS/DNSMonitor
Moreover, it must remain in its application bundle (which contains required codesigining and provisioning profile information).
DNSMonitor leverages Apple's System/Network Extensions Framework to capture system-wide DNS events. Apple places several restrictions on such extensions. Specifically such extensions must first be copied to the /Applications
directory. And the user must manually approve any extension before it is allowed to begin capturing (network) events.
Thus, to run DNSMonitor.app
, you must:
- Ensure the application bundle
DNSMonitor.app
, has been copied into the /Applications
directory. If not an error will be displayed:
% ~/Downloads/DNSMonitor.app/Contents/MacOS/DNSMonitor
...
ERROR: As DNSMonitor uses a System Extension,
Apple requires it must be located in /Applications
- Approve the System Extension. First, macOS will display a prompt:
Click "Open Security Preferences" to open the System Preferences application (it should load the "Security & Privacy" pane).
Click "Allow", then authenticate to allow the DNSMonitor
extension to load:
- Once the extension has been approved it will load. However, macOS will then request approval to allow it to monitor DNS traffic.
Click "Allow" to allow DNSMonitor
to monitor DNS traffic.
Now, all DNS requests and response will be displayed in the terminal.
To terminate DNSMonitor
, simply hit control+c
((^+c)
). This will trigger a prompt from the operating system to unload the extension (unless the monitor with -daemon
commandline option):
...authenticate by entering your user name password and click "OK". This will remove DNSMonitor
's extension and cause it to cleanly terminate.
Note:
To avoid having to (re)approve the extension each time, run the monitor with the
-daemon commandline option. This will leave the extension component running even when the monitor exits.
To unload the extension (re)run DNSMonitor with the -unload commandline option. Or, if you run it again without the -daemon option, the extension will be unloaded when the monitor exits.