Splunk Enterprise app search
The Search page is the standard Splunk Search Processing Language (SPL) interface. In the DomainTools App, you use it to run the custom search commands that call DomainTools APIs and to query the threat feed indexes you enable in advanced configuration.
Custom search commands
Section titled “Custom search commands”DomainTools custom search commands extend SPL with enrichment, investigation, passive DNS, WHOIS history, and RDAP lookups. Each command is a generating or transforming command that you pipe into a search. The commands below run against the DomainTools APIs and return results into your search pipeline.
Several commands also power dedicated UI pages: the DNSDB commands back Farsight DNSDB, dtwhoishistory backs WHOIS history, and dtparseddomainrdap backs Domain RDAP. The utility commands dtaccountinfo and dtidnadecode support the app’s internal pages. The threat feed commands and Iris Detect commands are grouped in their own sections below.
dtdomainextract
Section titled “dtdomainextract”Extracts a domain from a URL field using tldextract, so DomainTools APIs receive a valid domain as input.
- Syntax:
| dtdomainextract field_in=string field_out=string include_subdomains=bool debug=bool feature=string - Parameters:
field_in(required)field_out(required)include_subdomains(optional)debug(optional)feature(optional)
- Example:
... | dtdomainextract field_in=url field_out=domain
dtirisenrich
Section titled “dtirisenrich”Queries Iris Enrich for up to 100 comma-separated domains. Set inline_results=true to keep the event data inline with your results.
- Syntax:
| dtirisenrich domain=string inline_results=string feature=string - Parameters:
domain(required)inline_results(optional)feature(optional)
- Example:
| makeresults | eval domain="domaintools.com" | dtirisenrich domain=domain inline_results=true
dtirisinvestigate
Section titled “dtirisinvestigate”Queries Iris Investigate for up to 100 comma-separated domains supplied through domain, pivots on a domain attribute, or runs an IrisQL query. An IrisQL query returns up to 500 matching domains as Splunk events. The command doesn’t support pagination, so refine queries that match more than 500 domains.
You must provide irisql, domain, or both pivot_type and pivot_value. If you provide more than one input mode, the command uses irisql first, then domain. Review Query with IrisQL for formatting instructions.
- Syntax:
| dtirisinvestigate irisql=string domain=string pivot_type=string pivot_value=string feature=string no_cache=bool - Parameters:
irisql(optional) — a raw IrisQL query string. Must begin with the version header# IrisQL-1.0followed by\nand the query body. Always queries live and skips the cache, independent ofno_cache.domain(optional)pivot_type(required unless usingirisqlordomain)pivot_value(required unless usingirisqlordomain)feature(optional)no_cache(optional)
- Domain example:
| dtirisinvestigate domain="domaintools.com" - Pivot example:
| dtirisinvestigate pivot_type="ip" pivot_value="x.x.x.x" - IrisQL example:
| dtirisinvestigate irisql="# IrisQL-1.0\nDOMAIN CONTAINS \"phishing\""
dtformatinvestigate
Section titled “dtformatinvestigate”Formats the JSON returned by Iris Investigate into a row with named components.
- Syntax:
| dtformatinvestigate output=string feature=string - Parameters:
output(required)feature(optional)
- Example:
| dtirisinvestigate domain="domaintools.com" | dtformatinvestigate output=risk
dtparseddomainrdap
Section titled “dtparseddomainrdap”Returns Parsed Domain RDAP API results for a domain. This command supports only the domain parameter. The Parsed Domain RDAP API is a lookup service, separate from the Parsed Domain RDAP Feed. Enable it under Enable the Parsed Domain RDAP API, and view results in the Domain RDAP page.
- Syntax:
| dtparseddomainrdap domain=string - Parameters:
domain(required)
dtdnsdb
Section titled “dtdnsdb”Queries Farsight DNSDB for passive DNS information on an IP, domain, hostname, or subnet.
- Syntax:
| dtdnsdb target=ip/hostname type=rdata/rrset/raw rrtype=a/aaa/cname/etc time_first_before=time time_first_after=time time_last_before=time time_last_after=time target_type=auto/ip/name bailiwick=bailiwick - Parameters:
target(required)type(required)rrtype(required)bailiwick(optional)time_first_before(optional)time_first_after(optional)time_last_before(optional)time_last_after(optional)target_type(optional)
- Example:
| dtdnsdb target=domaintools.com target_type=domain type=rdata rrtype=CNAME
dtdnsdbflex
Section titled “dtdnsdbflex”Performs a Farsight DNSDB passive DNS flexible search.
- Syntax:
| dtdnsdbflex query_type=<rdata|rrnames> match_type=<glob|regex> query=<pattern> rrtype=A/mx/cname/etc bailiwick=bailiwick time_first_before=time time_first_after=time time_last_before=time time_last_after=time - Parameters:
query_type(required)match_type(required)query(required)rrtype(required)bailiwick(optional)time_first_before(optional)time_first_after(optional)time_last_before(optional)time_last_after(optional)
- Example:
| dtdnsdbflex query_type=rdata match_type=regex query="[0-9]{5,6}-ledger\.com\.$"
dtdnsdblimit
Section titled “dtdnsdblimit”Returns the DNSDB API query limit, queries remaining, and reset time.
- Syntax:
| dtdnsdblimit - Parameters: none
- Example:
| dtdnsdblimit
dtdnsdbenrich
Section titled “dtdnsdbenrich”Enriches Splunk events from a query with passive DNS information from Farsight DNSDB.
- Syntax:
| dtdnsdbenrich field_in=string field_type=domain/ip/raw lookup_type=rrset/rrdata max_count=int time_first_before=time time_first_after=time time_last_before=time time_last_after=time rrtype=any/A/ns/... bailiwick=string include_subdomains=bool - Parameters:
field_in(required)field_type(required)lookup_type(required)max_count(optional)rrtype(optional)bailiwick(optional)time_first_before(optional)time_first_after(optional)time_last_before(optional)time_last_after(optional)include_subdomains(optional)feature(optional)
- Example:
| dtdnsdbenrich field_in=domain field_type=domain lookup_type=rrset rrtype=A include_subdomains=true time_first_after=1593070040
dtwhoishistory
Section titled “dtwhoishistory”Performs a WHOIS history search on a domain using the WHOIS History API endpoint. This command backs the WHOIS history page.
- Syntax:
| dtwhoishistory domain=string mode=string - Parameters:
domain(required)mode(optional) — controls what the search returns:list(default) returns the matching WHOIS history records.check_existencereturns only the booleanhas_history_entries.countreturns the number of history entries.
- Example:
... | dtwhoishistory domain=domain - Example:
... | dtwhoishistory domain=domain mode="check_existence"
dtaccountinfo
Section titled “dtaccountinfo”Returns the provisioned DomainTools APIs and account status for your configured credentials. Each result row carries an id field (for example, iris-enrich, iris-investigate, iris-detect-monitors), so you can filter for a specific API. The app uses this command internally to drive the API Usage and Diagnostic Panel pages.
- Syntax:
| dtaccountinfo params=string feature=string - Parameters:
params(optional)feature(optional)
- Example:
| dtaccountinfo | search id="iris-enrich" | stats count
dtidnadecode
Section titled “dtidnadecode”Decodes internationalized domain names (IDNs) from Punycode into their Unicode form. Use it to add a decoded field to events before display or further processing.
- Syntax:
| dtidnadecode field_in=string field_out=string feature=string - Parameters:
field_in(required)field_out(required)feature(optional)
- Example:
| `dt_basesearch` | dtidnadecode field_in=domain field_out=decoded
dtformatenrich
Section titled “dtformatenrich”Formats the output returned by the Iris Enrich API into named components, the enrichment-side counterpart to dtformatinvestigate.
- Syntax:
| dtformatenrich - Parameters: none
- Example:
... | dtirisenrich domain=domain | dtformatenrich
dtexpirecache
Section titled “dtexpirecache”Removes expired rows from a DomainTools KV Store cache collection. Use it to clear entries older than a set number of days from a named collection.
- Syntax:
| dtexpirecache collection=string time_field=string num_days_back=int feature=string - Parameters:
collection(required)time_field(required)num_days_back(optional)feature(optional)
- Example:
| dtexpirecache collection="dt_iris_enrich_queue" time_field="queued" num_days_back=1
Query with IrisQL
Section titled “Query with IrisQL”IrisQL is a text-based query language for the Iris Investigate API. Use the irisql parameter on dtirisinvestigate to run IrisQL queries directly from Splunk SPL, without needing to build a pivot query.
Run your first IrisQL query
Section titled “Run your first IrisQL query”| dtirisinvestigate irisql="# IrisQL-1.0\nDOMAIN CONTAINS \"phishing\""This returns up to 500 domains in Iris Investigate that contain the word phishing. Each result row includes the domain name and the full raw JSON response from the API. The command doesn’t expose the API page_size or position parameters, so refine the query if more than 500 domains match.
Pipe the results into dtformatinvestigate for a formatted table:
| dtirisinvestigate irisql="# IrisQL-1.0\nDOMAIN CONTAINS \"phishing\"" | dtformatinvestigate output=riskQuery string format
Section titled “Query string format”An IrisQL query string has two parts, separated by a newline:
# IrisQL-1.0DOMAIN CONTAINS "x"- The
# IrisQL-1.0version header is required. A missing or malformed header returns anIrisQL header is invaliderror. - Use
\nto separate the header from the query body. The app converts\nto a real newline before sending the query to the API.
Combine conditions with AND on its own \n-separated line:
| dtirisinvestigate irisql="# IrisQL-1.0\nRISK_SCORE GREATER_THAN 70\nAND\nCREATE_DATE WITHIN \"The last 30 days\""For the full field and operator reference — supported fields, string/numeric/date operators, AND/OR logic, and the parsed_domain_rdap:/parsed_whois: data source prefixes — see IrisQL: Iris Query Language for API. Field names and operators are identical between the API and the Splunk command.
Example queries
Section titled “Example queries”Find high-risk domains registered in the last 30 days:
| dtirisinvestigate irisql="# IrisQL-1.0\nRISK_SCORE GREATER_THAN 70\nAND\nCREATE_DATE WITHIN \"The last 30 days\""Find domains sharing a registrant email — useful when investigating a known actor’s infrastructure:
| dtirisinvestigate irisql="# IrisQL-1.0\nREGISTRANT_CONTACT_EMAIL MATCHES \"badactor@example.com\""Find domains sharing an SSL certificate hash with a known malicious domain:
| dtirisinvestigate irisql="# IrisQL-1.0\nSSL_HASH MATCHES \"<sha1_hash>\""Save high-risk results to a lookup for alerting:
| dtirisinvestigate irisql="# IrisQL-1.0\nRISK_SCORE GREATER_THAN 90\nAND\nCREATE_DATE WITHIN \"The last 1 day\"" | table domain _raw | outputlookup append=true dt_high_risk_domains.csvMulti-variable pivot: attribution
Section titled “Multi-variable pivot: attribution”Combine registration identity, hosting subnet, and certificate fingerprint in a single query to correlate infrastructure. A domain matching all three conditions is very likely part of the same actor’s infrastructure:
| dtirisinvestigate irisql="# IrisQL-1.0\nREGISTRANT_CONTACT_EMAIL MATCHES \"badactor@example.com\"\nAND\nIP CONTAINS \"192.168.\"\nAND\nSSL_HASH MATCHES \"<sha1_hash>\""Threat feed commands
Section titled “Threat feed commands”The threat feed commands are generating commands that pull indicators directly from the DomainTools Threat Feeds API. Retrieve data with a time window, or use a session to continue from the position saved by a previous request.
For enabling and searching the ingested feed indexes instead, see Threat Feeds.
Time windows and sessions
Section titled “Time windows and sessions”Provide at least one of after, before, or sessionID:
after— start of the query window. Use a negative integer from-1through-432000for seconds before the current time, or an ISO 8601 UTC timestamp. For example,after=-60retrieves data from the last 60 seconds.before— end of the query window. It accepts the same relative-seconds and ISO 8601 formats asafter.sessionID— a case-sensitive identifier containing 1–64 letters, numbers, or hyphens. A new session starts with the most recent hour of data unless you also provide a time window orfromBeginning=true. Reuse the identifier to retrieve data added since the previous request.fromBeginning— set totrueon the first request for a newsessionIDto start at the beginning of retained feed data. Don’t reuse it with an existing session. The IP feed commands reject searches that combinefromBeginning=truewithafter.top— limits the response to an integer from1through1000000000.feature— optional app context passed with the request.
The domain feed commands also accept domain to filter results for one domain. The IP feed commands instead provide filters for hosting activity, threat percentages, and IP ownership.
IP feed filters
Section titled “IP feed filters”dtfeediphotlist and dtfeediprisk support the same filters. When you provide more than one filter, the feed applies each filter.
| Parameter | Accepted value | Filters for |
|---|---|---|
pdns_resolutions_min | Positive integer | At least this many passive DNS resolutions |
bad_pdns_resolutions_min | Positive integer | At least this many passive DNS resolutions for threatening domains |
total_domains_max | Positive integer | No more than this many hosted domains |
third_party_threats_min | Positive integer | At least this many domains identified by third-party threat intelligence |
all_threats_combined_percent_min | Integer from 0 through 100 | Minimum percentage of confirmed or predicted threatening domains |
combined_phishing_percent_min | Integer from 0 through 100 | Minimum percentage of confirmed or predicted phishing domains |
combined_malware_percent_min | Integer from 0 through 100 | Minimum percentage of confirmed or predicted malware domains |
combined_spam_percent_min | Integer from 0 through 100 | Minimum percentage of confirmed or predicted spam domains |
all_threats_percent_min | Integer from 0 through 100 | Minimum percentage of confirmed threatening domains |
percent_phishing_min | Integer from 0 through 100 | Minimum percentage of confirmed phishing domains |
percent_malware_min | Integer from 0 through 100 | Minimum percentage of confirmed malware domains |
percent_spam_min | Integer from 0 through 100 | Minimum percentage of confirmed spam domains |
asn | Integer without an AS prefix | Exact autonomous system number |
organization | String | Exact organization name; wildcards aren’t supported |
country_code | Two-letter ISO country code | IP geolocation country |
See the IP Hotlist API and IP Risk API for the complete response schemas and field definitions.
dtfeeddomaindiscovery
Section titled “dtfeeddomaindiscovery”New domains as they are discovered in domain registration information, observed by the DomainTools global sensor network, or reported by trusted third parties.
- Syntax:
| dtfeeddomaindiscovery after=string before=string sessionID=string fromBeginning=true domain=string top=int feature=string - Example:
| dtfeeddomaindiscovery after=-60
dtfeeddomainhotlist
Section titled “dtfeeddomainhotlist”High-risk, apex-level domains that the DomainTools global sensor network observes to be active within 24 hours.
- Syntax:
| dtfeeddomainhotlist after=string before=string sessionID=string fromBeginning=true domain=string top=int feature=string - Example:
| dtfeeddomainhotlist after=-60 | table timestamp domain phishing_risk malware_risk spam_risk proximity_risk overall_risk expires
dtfeeddomainrdap
Section titled “dtfeeddomainrdap”Changes to global domain registration information, populated by the Registration Data Access Protocol (RDAP). Complements the 5-Minute WHOIS Feed as registries and registrars move from WHOIS to RDAP.
- Syntax:
| dtfeeddomainrdap after=string before=string sessionID=string fromBeginning=true domain=string top=int feature=string - Example:
| dtfeeddomainrdap after=-60
dtfeeddomainrisk
Section titled “dtfeeddomainrisk”Real-time domain risk information for apex-level domains, regardless of observed traffic.
- Syntax:
| dtfeeddomainrisk after=string before=string sessionID=string fromBeginning=true domain=string top=int feature=string - Example:
| dtfeeddomainrisk after=-60 | table timestamp domain phishing_risk malware_risk spam_risk proximity_risk overall_risk
dtfeediphotlist
Section titled “dtfeediphotlist”Retrieves high-risk hosting IP addresses where more than half of hosted domains meet the IP Hotlist risk and recent-activity criteria.
- Syntax:
| dtfeediphotlist after=string before=string sessionID=string fromBeginning=true top=int feature=string [filter=value ...] - Example:
| dtfeediphotlist after=-60 top=5| table timestamp ip asn organization country total_domains all_threats_combined_count all_threats_combined_percentdtfeediprisk
Section titled “dtfeediprisk”Retrieves hosting IP addresses with domain activity, risk, ownership, geolocation, and threat-percentage context for investigation and filtering.
- Syntax:
| dtfeediprisk after=string before=string sessionID=string fromBeginning=true top=int feature=string [filter=value ...] - Example:
| dtfeediprisk after=-3600 all_threats_combined_percent_min=50 total_domains_max=1000 top=100| table timestamp ip asn organization country total_domains all_threats_combined_percent combined_phishing_percent combined_malware_percent combined_spam_percentdtfeednad
Section titled “dtfeednad”Apex-level domains (for example, example.com but not www.example.com) that DomainTools has newly observed to be active in its DNS sensor network.
- Syntax:
| dtfeednad after=string before=string sessionID=string fromBeginning=true domain=string top=int feature=string - Example:
| dtfeednad after=-60 | table timestamp domain
dtfeednod
Section titled “dtfeednod”Apex-level domains observed for the first time by the DomainTools sensor network, and which aren’t present in the DNSDB historical database.
- Syntax:
| dtfeednod after=string before=string sessionID=string fromBeginning=true domain=string top=int feature=string - Example:
| dtfeednod after=-60 | table timestamp domain
dtfeednoh
Section titled “dtfeednoh”Hostname resolutions observed for the first time by the DomainTools global DNS sensor network.
- Syntax:
| dtfeednoh after=string before=string sessionID=string fromBeginning=true domain=string top=int feature=string - Example:
| dtfeednoh after=-60 | table timestamp domain
Iris Detect commands
Section titled “Iris Detect commands”These commands back the app’s Iris Detect import and sync features. They run automatically as part of the app’s saved searches, but you can also run them directly.
dtimportirisdetectmonitors
Section titled “dtimportirisdetectmonitors”Imports the Iris Detect monitors configured on your DomainTools account.
- Syntax:
| dtimportirisdetectmonitors feature=string - Parameters:
feature(optional)
- Example:
| dtimportirisdetectmonitors
dtimportirisdetectresults
Section titled “dtimportirisdetectresults”Imports the current day’s Iris Detect results for a given list of monitor IDs. Pipe in the monitor IDs from the dt_iris_detect_monitors lookup.
- Syntax:
| dtimportirisdetectresults feature=string - Parameters:
feature(optional)
- Example:
| from inputlookup:dt_iris_detect_monitors | dtimportirisdetectresults
dtsyncirisdetectwatchlist
Section titled “dtsyncirisdetectwatchlist”Syncs the dt_iris_detect_results entries with the state watched into the dt_monitoring_list, keeping the Iris Detect watchlist aligned with your monitored domains.
- Syntax:
| dtsyncirisdetectwatchlist - Parameters: none
- Example:
| dtsyncirisdetectwatchlist
Example searches
Section titled “Example searches”Set up a recurring search with an Iris Investigate search hash
Section titled “Set up a recurring search with an Iris Investigate search hash”This example uses dtirisinvestigate to look up domains matching a search hash, parse the first-seen value into a table, and collect the results into a summary index. Save it as a report to run on a schedule.
| dtirisinvestigate pivot_type=search_hash pivot_value=YOUR_SEARCH_HASH no_cache=true| eval json = replace(_raw, "^[^\{]+", "")| spath input=json path=first_seen.value| rename first_seen.value as first_seen| table first_seen domain| collect index=summary_index_icloudFor how to schedule a report, see the Splunk Reporting Manual.
Set up a recurring search with a DNSDB flexible search
Section titled “Set up a recurring search with a DNSDB flexible search”This example uses dtdnsdbflex to look up domains matching a regular expression, last observed in DomainTools’ DNS sensor network over the past 30 days. Storing a relative Unix timestamp in a variable creates a relative time fence, so the window shifts with the schedule when you save this as a report.
| eval thirty_days_ago=relative_time(now(), "-30d@d")| eval thirty_days_ago_unix=thirty_days_ago| dtdnsdbflex query_type=rrnames match_type=regex query="-icloud\.(net|com)\.$" rrtype=A time_last_after=thirty_days_ago_unixFor how to write regular expressions for the DNSDB flexible search, see the regular expression user guide.
Index IP feed results on a schedule
Section titled “Index IP feed results on a schedule”Save an IP feed search as a Splunk report to write new feed results to an event index on a schedule. Create the destination index before you enable the report. Use a persistent sessionID. Each scheduled search continues from its prior request.
| dtfeediprisk sessionID="ip-risk-ingestion"| collect index=YOUR_IP_RISK_INDEXSave this search as a report and schedule it for the interval you need. The first request for a session starts with the most recent hour of feed data. To retrieve retained history, create a separate one-time search with fromBeginning=true, then reuse the same sessionID in the scheduled report without fromBeginning.
Use dtfeediphotlist instead of dtfeediprisk to get IP Hotlist data. Replace YOUR_IP_RISK_INDEX with the event index you created.
Threat Feeds
Section titled “Threat Feeds”Each feed saved search you enable in Enable Threat Feeds writes its results into a dedicated Splunk index that you create. Query that index directly from the Search page. The index names are fixed by the app:
| Feed | Index |
|---|---|
| Domain Discovery | dt_feed_domain_discovery |
| Domain Hotlist | dt_feed_domain_hotlist |
| Domain Risk | dt_feed_domainrisk |
| Newly Active Domains (NAD) | dt_feed_nad |
| Newly Observed Domains (NOD) | dt_feed_nod |
| Newly Observed Hostnames (NOH) | dt_feed_noh |
| Parsed Domain RDAP | dt_feed_rdap |
Every feed event carries a domain and a timestamp. The Domain Risk and Domain Hotlist feeds also carry the per-category risk scores (phishing_risk, malware_risk, spam_risk, proximity_risk, overall_risk), and Domain Hotlist adds expires.
View the 100 most recent domains from a feed:
index=dt_feed_nod| sort - _time| head 100| table _time, domainCheck whether a specific domain appeared in a feed:
index=dt_feed_nod domain="example.com"Find domains containing a keyword — useful for hunting a brand or term:
index=dt_feed_nod domain="*microsoft*"Review the highest-risk domains from the Domain Risk feed:
index=dt_feed_domainrisk| sort - overall_risk| table _time, domain, overall_risk, phishing_risk, malware_risk, spam_risk, proximity_riskFor threat feed parameter details, see Threat feed parameters.
Related resources
Section titled “Related resources”- DT Settings — enable saved searches and configure enrichment and alerting
- Advanced configuration — create feed indexes, enable Threat Feeds, and enable the Parsed Domain RDAP API
- Farsight DNSDB — the passive DNS search UI page
- WHOIS history — the WHOIS history UI page
- Domain RDAP — the Parsed Domain RDAP lookup UI page
- Configuration tables and troubleshooting — configuration file and KV store reference