Closed ScrumpyJack closed 1 year ago
That's an interesting idea. Beside the ssh approach, it can be done very easily with an external script aggregating output from different asn server instances, for example if you want textual traces from multiple servers, just add them to the $asnservers
variable and run the script below. It should output textual results on screen. Of course this can be obtained using html, or even aggregating the html in a nice looking page with, say, sections reporting the asn server source country for every result etc. - I think this all belongs to an external script, and it should be not be hard to make. Let me know if this is what you meant.
Thanks for the feedback!
#!/usr/bin/env bash
# change this to the list of your asn server instances, space separated
asnservers="127.0.0.1 1.2.3.4 5.6.7.8"
target="$1"
output=""
for asnserver in $asnservers; do
echo "Running asn lookup for '$target' on server $asnserver"
output+="$(curl -s "http://$asnserver:49200/asn_lookup&$target" | sed -n "s:.*id='tracedata'>\(.*\)</div>.*:\1:p" | base64 -d | gunzip)\n\n"
done
echo -e "$output" | less
The script above is meant to be invoked with the <target>
parameter on command line. For example ./multiasn 8.8.8.8
Clever. I hadn't thought of looping a curl.
How would you get that output back into a browser window with the pretty colours though? 😁
Well in the above script, I just extracted the tracedata
div content from the html - which is just a gzipped + base64-encoded version of the textual asn output, which I use when sharing the text-only version on termbin.
That means you can instead grab the full html (just take out the sed
part) and that should do the trick.
I reckon perhaps the above needs a clearer explanation: when I run a remote trace, I instruct the remote server to run a trace and convert the trace output to html (using your new friend aha ;-) in order to display it back to the client.
In the meantime, since I needed an easy way to share the text output on termbin if the client so decided, and since converting it from html back to text was rather stupid (since in the process I had the text server-side all along), I decided to append (on server side) a "text-only" version of the trace output to the output HTML, so that the client already had what it needed to feed to termbin. I needed a way that was lightweight (ie: gzip) and - since it had to be passed along in a web page - textual-only (no non-printable characters, ie: base64).
The method I used was to append a <div>
(having id=tracedata
) to the output HTML. That way I could generate the termbin-sharing code dynamically on the client side (or actually, I could hardcode it directly into the output html without any worries on the actual contents of the trace) and already have the termbin input to pass to the sharing function (which is just another GET from the remote server).
I just hacked together what I had in mind when I spoke about "sections". Output looks like this (sorry, I'm not a web designer :-P) :
Note: you need GNU sed for this to work. Make sure you have the coreutils package installed if running the following script on MacOS/FreeBSD.
#!/usr/bin/env bash
# change this to the list of your asn server instances, space separated
asnservers="127.0.0.1 1.2.3.4 5.6.7.8"
# output html filename
output_file="output.html"
# no changes needed below
target="$1"
[[ -z "$target" ]] && { echo "Usage: $0 <target>"; exit 1; }
green=$'\e[38;5;035m'
red=$'\e[38;5;203m'
default=$'\e[0m'
# make sure we use GNU sed if running on FreeBSD/MacOS
if [ -x "$(command -v gsed)" ]; then
sed() { gsed "$@"; }
export -f sed
fi
read -r -d '' output <<- END_OF_HTML_HEADER
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
END_OF_HTML_HEADER
# cheers https://www.cssscript.com/responsive-css-accordion-tabs-component/
read -r -d '' accordioncss <<- END_OF_ACCORDION_CSS
<style>
.tabs {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.tabs label {
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
-ms-flex-order: 1;
order: 1;
display: block;
padding: 0.5rem 2rem;
margin-right: 0.2rem;
cursor: pointer;
background: #d5d5d5;
-webkit-transition: background ease 0.2s;
transition: background ease 0.2s;
}
.tabs .tab {
-webkit-box-ordinal-group: 100;
-webkit-order: 99;
-ms-flex-order: 99;
order: 99;
-webkit-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex-positive: 1;
flex-grow: 1;
width: 100%;
display: none;
padding: 0.05rem;
background: #fafafa;
}
.tabs input[type="radio"] {
position: absolute;
opacity: 0;
}
.tabs input[type="radio"] + label { background: #999999; color: #404040; }
.tabs input[type="radio"]:checked + label { background: #fafafa; font-weight: bold; color: #1e1e1e; }
.tabs input[type="radio"]:checked + label + .tab { display: block; }
@media (max-width: 45em) {
.tabs .tab, .tabs label {
-webkit-box-ordinal-group: NaN;
-webkit-order: initial;
-ms-flex-order: initial;
order: initial;
}
.tabs label {
width: 100%;
margin-right: 0;
margin-top: 0.2rem;
}
}
</style>
END_OF_ACCORDION_CSS
first_run=true
srvnum=1
for asnserver in $asnservers; do
echo -en "${default}- Running asn lookup for '$target' on server $asnserver..."
tmp_output="$(curl -s "http://$asnserver:49200/asn_lookup&$target" | grep -v 'class="loader"')"
if [ -z "$tmp_output" ]; then
echo "${red}Error!${default}"
else
if [ "$first_run" = true ]; then
# grab the <head> tag from the first successful run, so to apply proper styling to the remaining results
htmlhead=$(sed -zn "s:.*<head>\(.*\)</head>.*:\1:p" <<<"$tmp_output")
output+="\n\n<head>\n$htmlhead\n$accordioncss\n</head>\n<body>\n\
<div style='text-align: center;'><hr>Multiple ASN trace to target:<br /><span style='color:#ff5f5f; font-size: 2em'>$target</span><br /><hr></div> \
<div class='tabs'>"
fi
# extract <body> content for this trace
htmlbody=$(sed -zn "s:.*<body>\(.*\)</body>.*:\1:p" <<<"$tmp_output")
# clean up the html by stripping unneeded js
htmlbody=$(\
sed -e "s/<script>window.scrollTo.*<\/script>//g" \
-e "s/<script>top.document.title.*<\/script>//g" <<<"$htmlbody"
)
# strip sharing-related html
htmlbody=$(sed -z "s/<span id='share-container'>.*/<\/div><\/pre>/" <<<"$htmlbody")
# extract asn server name from html
srvname=$(sed -n "s:.*running on \(.*\) in.*:\1:p" <<<"$htmlbody")
# extract server flag svg from html
srvflag=$(sed -n "s:.*\(http[s*]\://.*/flag-icon-css/.*svg\).*:\1:p" <<<"$htmlbody" | head -n1)
# create the output tab related to this trace
output+="<input type=\"radio\" name=\"tabs\" id=\"$srvnum\""
[[ "$first_run" = true ]] && { output+=" checked='checked'"; first_run=false; }
output+=">\n \
<label for=\"$srvnum\">${srvnum}. $srvname <img src='$srvflag' style='height:1.05em; border-radius: 0; vertical-align: middle;'></label> \
<div class=\"tab\"> \
$htmlbody \
</div>\n"
echo "${green}OK!${default}"
fi
(( srvnum++ ))
done
output+="\n</body>\n</html>"
echo -e "$output" > "$output_file"
echo -e "\nOutput written to file ${green}${output_file}${default}\n"
Oh my goodness that is amazing. I will try this out as
I changed
tmp_output="$(curl -s "http://$asnserver:49200/asn_lookup&$target" | grep -v 'class="loader"')"
to
tmp_output="$(curl -s "$asnserver/asn_lookup&$target" | grep -v 'class="loader"')"
as it allows variation on protocol and ports in the list of $asnservers
How and where would you add class="hidden_underline" to this script?
How and where would you add class="hidden_underline" to this script?
no need to, I just pushed v0.71.6 which implements hidden underlines out of the box. Try it with the newest version, should work just fine.
Would be awesome to add netcat listen to multiasn so that the hyperlinks would work. Hmm, seems complex though as the html output currently goes to a file instead of back out to the http client.
Actually, hrefs point to file:// URLs just because you open it from disk and they're relative links (therefore not able to figure out which site to point to). This could be easily bulk-translated on the fly in the multiasn script, to point to the current server's IP (as in, changing "/" to "$asnserver/") while being parsed before going out to the file. That way each tab would have proper hyperlinks pointing to the appropriate server instead of useless "file://" links pointing nowhere. Will add that as soon as I get a minute.
This oughta get you working hyperlinks (includes your protocol and port modification, even though for https to work I guess you'd have to place it behind a proxy as there's no ssl handling currently built into the script):
#!/usr/bin/env bash
# change this to the list of your asn server instances, space separated
asnservers="http://127.0.0.1:49200 http://1.2.3.4:49200 http://5.6.7.8:49200"
# output html filename
output_file="output.html"
# no changes needed below
target="$1"
[[ -z "$target" ]] && { echo "Usage: $0 <target>"; exit 1; }
green=$'\e[38;5;035m'
red=$'\e[38;5;203m'
default=$'\e[0m'
# make sure we use GNU sed if running on FreeBSD/MacOS
if [ -x "$(command -v gsed)" ]; then
sed() { gsed "$@"; }
export -f sed
fi
read -r -d '' output <<- END_OF_HTML_HEADER
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
END_OF_HTML_HEADER
# cheers https://www.cssscript.com/responsive-css-accordion-tabs-component/
read -r -d '' accordioncss <<- END_OF_ACCORDION_CSS
<style>
.tabs {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.tabs label {
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
-ms-flex-order: 1;
order: 1;
display: block;
padding: 0.5rem 2rem;
margin-right: 0.2rem;
cursor: pointer;
background: #d5d5d5;
-webkit-transition: background ease 0.2s;
transition: background ease 0.2s;
}
.tabs .tab {
-webkit-box-ordinal-group: 100;
-webkit-order: 99;
-ms-flex-order: 99;
order: 99;
-webkit-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex-positive: 1;
flex-grow: 1;
width: 100%;
display: none;
padding: 0.05rem;
background: #fafafa;
}
.tabs input[type="radio"] {
position: absolute;
opacity: 0;
}
.tabs input[type="radio"] + label { background: #999999; color: #404040; }
.tabs input[type="radio"]:checked + label { background: #fafafa; font-weight: bold; color: #1e1e1e; }
.tabs input[type="radio"]:checked + label + .tab { display: block; }
@media (max-width: 45em) {
.tabs .tab, .tabs label {
-webkit-box-ordinal-group: NaN;
-webkit-order: initial;
-ms-flex-order: initial;
order: initial;
}
.tabs label {
width: 100%;
margin-right: 0;
margin-top: 0.2rem;
}
}
</style>
END_OF_ACCORDION_CSS
first_run=true
srvnum=1
for asnserver in $asnservers; do
echo -en "${default}- Running asn lookup for '$target' on server $asnserver..."
tmp_output="$(curl -s "$asnserver/asn_lookup&$target" | grep -v 'class="loader"')"
if [ -z "$tmp_output" ]; then
echo "${red}Error!${default}"
else
if [ "$first_run" = true ]; then
# grab the <head> tag from the first successful run, so to apply proper styling to the remaining results
htmlhead=$(sed -zn "s:.*<head>\(.*\)</head>.*:\1:p" <<<"$tmp_output")
output+="\n\n<head>\n$htmlhead\n$accordioncss\n</head>\n<body>\n\
<div style='text-align: center;'><hr>Multiple ASN trace to target:<br /><span style='color:#ff5f5f; font-size: 2em'>$target</span><br /><hr></div> \
<div class='tabs'>"
fi
# extract <body> content for this trace
htmlbody=$(sed -zn "s:.*<body>\(.*\)</body>.*:\1:p" <<<"$tmp_output")
# clean up the html by stripping unneeded js
htmlbody=$(\
sed -e "s/<script>window.scrollTo.*<\/script>//g" \
-e "s/<script>top.document.title.*<\/script>//g" <<<"$htmlbody"
)
# fixup relative hyperlinks with absolute ones pointing to the right server
htmlbody=$(sed -E "s,<a href=\"/asn_lookup,<a href=\"$asnserver/asn_lookup," <<<"$htmlbody")
# strip sharing-related html
htmlbody=$(sed -z "s/<span id='share-container'>.*/<\/div><\/pre>/" <<<"$htmlbody")
# extract asn server name from html
srvname=$(sed -n "s:.*running on \(.*\) in.*:\1:p" <<<"$htmlbody")
# extract server flag svg from html
srvflag=$(sed -n "s:.*\(http[s*]\://.*/flag-icon-css/.*svg\).*:\1:p" <<<"$htmlbody" | head -n1)
# create the output tab related to this trace
output+="<input type=\"radio\" name=\"tabs\" id=\"$srvnum\""
[[ "$first_run" = true ]] && { output+=" checked='checked'"; first_run=false; }
output+=">\n \
<label for=\"$srvnum\">${srvnum}. $srvname <img src='$srvflag' style='height:1.05em; border-radius: 0; vertical-align: middle;'></label> \
<div class=\"tab\"> \
$htmlbody \
</div>\n"
echo "${green}OK!${default}"
fi
(( srvnum++ ))
done
output+="\n</body>\n</html>"
echo -e "$output" > "$output_file"
echo -e "\nOutput written to file ${green}${output_file}${default}\n"
This is very cool and work pretty well. You are now costing me a fortune on VMs dotted round the place used as remote looking glasses
This multiasn is my new favorite toy, but I can't help thinking that it would be cool to have a listener that could then farm out the lookups to $asnservers and then display the result in a browser, in the same way as asn does for itself, if that makes sense.
closing this issue to cleanup the repo a bit. Hope all is well over there. Have a nice day!
I've been using this a bit and I really like it in server mode. Excellent as a looking glass. Nice crisp, colourful output. And I've discovered aha, which is now my new favourite toy.
I can't help wondering if we could get this to execute on a bunch of remove machines (via ssh and keys) and output the results to the same page, one after the other. A bit like mtr.sh
What are you thoughts?