Skip to content

Instantly share code, notes, and snippets.

@cunneen
Created May 26, 2025 09:50
Show Gist options
  • Save cunneen/bfbeb56d5868c81a3279a84af7a3c3ce to your computer and use it in GitHub Desktop.
Save cunneen/bfbeb56d5868c81a3279a84af7a3c3ce to your computer and use it in GitHub Desktop.
Bash function to reverse-lookup domain names for an IP Address via robtex.com
# WARNING: this is brittle as hell. It will break when robtex changes their website.
#
# reverseip
# A shell function to get a list of domain names associated with the given IP address, using Robtex.com
#
# Parameters:
# IP - IP address to reverse lookup
#
# Returns:
# List of domain names associated with the IP address
#
# Requires:
# curl
# jq
#
function reverseip() {
local IP=${1} # IP address as first parameter
# How this works:
# 1. Use curl to get the HTML from https://www.robtex.com/en/ip-lookup/${IP}
# 2. In the HTML body returned by Robtex, there is a reference to a plain-text data file for the IP address.
# We attempt to scrape the HTML to find the URL of the data file (using awk).
# 3. We use curl to fetch the data file from Robtex, and try to parse it to extract all the domain names
# using awk, sed and jq.
# print usage if no IP address is given, or --help is given
if [[ -z "${IP}" || "${IP}" == "--help" ]]; then
echo "Usage: reverseip [IP]"
echo "Parameters:"
echo " IP - IP address to reverse lookup"
echo "Example:"
echo " reverseip 207.204.43.124"
return 0
fi
# check for dependencies
command -v curl >/dev/null 2>&1 || {
echo "reverseIP: curl is required" >&2
return 1
}
command -v jq >/dev/null 2>&1 || {
echo "reverseIP: jq is required" >&2
return 1
}
local CURLPATH=$(where curl)
# ==== complex parsing rules ====
# Used to convert an IP address to a Robtex lookup URL component e.g. "207.204.43.124" becomes "207/204/43/124"
local SED_IP_WITH_SLASHES='s/\./\//g'
# Used to extract the URL of the Robtex data file from Robtexs initial HTML
local AWK_GET_ROBTEX_DATA_URL_FROM_ROBTEX_OUTPUT='/^< link: </{gsub(/[\<\>\;]/,"",$3); print $3; exit 0;}'
# Used to parse the Robtex data file, extracting the data from the line immediately following "id:21"
local AWK_PARSE_ROBTEX_DATA_OUTPUT='/^id:21\ndata: /{gsub(/^id:21\ndata: /,"",$0); gsub(/\>\</,"\>\\n\<",$0); print $0;}'
# Extracts the domain names from the HTML data
local SED_TIDY_ROBTEX_LINKS='s/^\<a href="https:\/\/www\.robtex\.com\/en\/dns-lookup\/[^"]*"\>(.+)\<.*$/\1/gp'
# Joins the domain names parts together, where there's a line ending in a dot
local AWK_JOIN_ROBTEX_DOMAIN_NAME_PARTS='/\.\n([^\n]+)/{gsub(/\.\n/,".",$0); printf("%s\n",$0);}'
# ==== main logic ====
echo ${IP} | \
sed "${SED_IP_WITH_SLASHES}" | \
xargs -I % "${CURLPATH}" -s -o /dev/null -v https://www.robtex.com/en/ip-lookup/% 2>&1 | \
awk "${AWK_GET_ROBTEX_DATA_URL_FROM_ROBTEX_OUTPUT}" | \
xargs curl -s | \
awk -v RS="\0" -v ORS="" "${AWK_PARSE_ROBTEX_DATA_OUTPUT}" | \
jq -r '.content0' | \
sed -n -E -e "${SED_TIDY_ROBTEX_LINKS}" | \
awk -v RS="\0" -v ORS="" "${AWK_JOIN_ROBTEX_DOMAIN_NAME_PARTS}"
}
@cunneen
Copy link
Author

cunneen commented May 26, 2025

Here's an example session, looking up robtex's records for a Cloudflare IP address shared by many domain names:

$ dig +short australiaawards.gov.au

104.21.48.1
104.21.16.1
104.21.64.1
104.21.32.1
104.21.112.1
104.21.80.1
104.21.96.1

$ dig -x 104.21.64.1

; <<>> DiG 9.10.6 <<>> -x 104.21.64.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 27077
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;1.64.21.104.in-addr.arpa.	IN	PTR

;; AUTHORITY SECTION:
21.104.in-addr.arpa.	2834	IN	SOA	cruz.ns.cloudflare.com. dns.cloudflare.com. 2288625502 10000 2400 604800 3600

;; Query time: 53 msec
;; SERVER: 1.0.0.1#53(1.0.0.1)
;; WHEN: Mon May 26 18:00:58 AWST 2025
;; MSG SIZE  rcvd: 115

$ reverseip 104.21.48.1 | sort

acseso.org
agentsforalchemy.com
alojaimagens.com
altu.pl
apps4phones.com
asdsj.com
asunhome.cn
auttvl.ac.in
bbsgxu.com
beetvapk.org
bionikmedia.com
bleckmannschulze.net
bni-secunderabad.in
bookmarkzap.com
brighter-tomorrows.org
clifftop.win
cloudhosting.biz.id
coodit.com
daiba.cx
dcconsult.be
dd946.com
deewp.co.uk
dody.fr
drhealth.md
earpopper.co.il
eija.org
exstopia.com
famart.com.br
fastedenda.com
fennsofficeinteriors.com
foccos.com.br
fotopoisk.com.ua
gam3-over.com
gavinwashburn.com
gizmoadvices.com
gnws.edu.in
h126.yuku.com
homeloans.property
indicare.org
ip-1-149.fountainhouse.voinetworks.ca
isl.com.mt
its-johannsen.de
jqha.cn
kitchenmart.com.au
kubeserv.com
liantop.cn
lifediscuss.com
lwbet.com
mail.idealha.ir
mail.popexpo.net
mail.tribunablog.com
maisonamerindienne.com
memorylosstest.com
mipanel.website
moneyaccounts.com
mvconline.org
namy.app
netfabric.nl
ofinterest.com
pa-pro.com
petererskine.com
petitmarche.biz
prescientmarkets.com
raybloc.info
redlisted.org
science.ph
searchonetime.com
securitycleaner.com
siec-ksa.com
skvallerbloggens.se
smarttechx.com
sodajerksrestaurant.com
stefano.fr
studioconcept.ru
szallashegyko.hu
tacklebullying.ie
thepatriots.us
tomparkerphotography.com
v-kulturascentrs.lv
volamtruyenky1.com
vsechat.ru
wordpress.ebotech.com
www.a4launcher.com
www.bakeys.com
www.brownsjewellers.com
www.bzhljx.com
www.drivinginstruct.com
www.fapchan.ru
www.healthfocuscentre.com.au
www.holmdelparents.org
www.igopost.ie
www.mts-mobile.ru
www.pizdenki.net
www.snuskhummer.com
www.spankitnow.com
www.theubj.com
yeahicandothat.com
yentob.com
zct.com.tw
zphc-forum.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment