mirror of
https://codeberg.org/slatian/service.echoip-slatecave.git
synced 2025-07-17 14:33:27 +02:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
f9753ccbfc | |||
a9512d7d4d | |||
6a57780490 | |||
51f27be997 | |||
554c788488 | |||
6d7e5ac18f | |||
3bcf8fde39 |
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -372,6 +372,7 @@ dependencies = [
|
|||||||
"idna 0.3.0",
|
"idna 0.3.0",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"maxminddb",
|
"maxminddb",
|
||||||
|
"parking_lot",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"tera",
|
"tera",
|
||||||
|
@ -13,6 +13,7 @@ clap = { version = "4", features = ["derive"] }
|
|||||||
governor = "0.5"
|
governor = "0.5"
|
||||||
idna = "0.3"
|
idna = "0.3"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
parking_lot = "0.12"
|
||||||
regex = "1.7"
|
regex = "1.7"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
@ -44,6 +44,12 @@ The default templates should make use of everything exposed to the templating pa
|
|||||||
|
|
||||||
The templates are covered by the AGPL as well, please share them with your users if you modified them.
|
The templates are covered by the AGPL as well, please share them with your users if you modified them.
|
||||||
|
|
||||||
|
### GeoLite2 database
|
||||||
|
|
||||||
|
For geolocation to work you need a MaxMind format database, for full functionality you need the GeoLite2-ASN and GeoLite2-City databses. Unfortunately you have to sign up with [MaxMind](https://maxmind.com) to obtain them. Once you have a license key there is a helper script in [contrib/maxmind-download.sh](contrib/maxmind-download.sh) that helps you with keeping the databse updated.
|
||||||
|
|
||||||
|
Since v1.0 echoip-slatecave reloads the databses when it rececieves a `USR1` signal.
|
||||||
|
|
||||||
## Security Considerations
|
## Security Considerations
|
||||||
|
|
||||||
### Information disclosure
|
### Information disclosure
|
||||||
@ -59,7 +65,7 @@ For a public service you should use a reverse proxy like Caddy, apache2 or nginx
|
|||||||
### Denail of Service
|
### Denail of Service
|
||||||
|
|
||||||
`echoip-slatecave` has some simle ratelimiting built in (see the `[ratelimit]` section in the configuration file) this should help you with too frequest automated requests causung high load.
|
`echoip-slatecave` has some simle ratelimiting built in (see the `[ratelimit]` section in the configuration file) this should help you with too frequest automated requests causung high load.
|
||||||
The default configuration is pretty liberal so that the average human probably won't notice the rate limit, but a misbehavin bot will be limited to one request every 3 seconds after 15 requests.
|
The default configuration is pretty liberal so that the average human probably won't notice the rate limit, but a misbehavingig bot will be limited to one request every 3 seconds after 15 requests.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
174
contrib/maxmind-download.sh
Normal file
174
contrib/maxmind-download.sh
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Settings variables go here
|
||||||
|
GEOIP_LICENSE_KEY="$GEOIP_LICENSE_KEY"
|
||||||
|
PRODUCTS=()
|
||||||
|
DESTINATION_DIRECTORY="."
|
||||||
|
DOWNLOAD_LOCATION=""
|
||||||
|
COLOR_OUTPUT=""
|
||||||
|
[ -t 1 ] && COLOR_OUTPUT="y"
|
||||||
|
|
||||||
|
msg() {
|
||||||
|
COLOR=""
|
||||||
|
COLOR_RST=""
|
||||||
|
if [ -n "$COLOR_OUTPUT" ] ; then
|
||||||
|
COLOR_RST="\e[00m"
|
||||||
|
case "$2" in
|
||||||
|
error|init_error) COLOR="\e[01;31m" ;;
|
||||||
|
success) COLOR="\e[32m" ;;
|
||||||
|
*) ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
printf "$COLOR%s$COLOR_RST\n" "$1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: maxmind-download.sh [OPTIONS]...
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
--license-key <key>
|
||||||
|
Set the licencse key that is unfortunately
|
||||||
|
needed for a successful download.
|
||||||
|
--product <id>
|
||||||
|
Which product to download
|
||||||
|
maxmind calls this the EditionID
|
||||||
|
--GeoLite2-mmdb-all
|
||||||
|
Selects all the GeoLite2 Products in mmdb
|
||||||
|
format, hoefully saves some headaces.
|
||||||
|
Will download:
|
||||||
|
* GeoLite2-ASN
|
||||||
|
* GeoLite2-City
|
||||||
|
* GeoLite2-Country
|
||||||
|
--to <destination>
|
||||||
|
Directory to place the downloded files in.
|
||||||
|
Filename will be <product>.(mmdb|csv)
|
||||||
|
--download-to <destination>
|
||||||
|
Directory to download to.
|
||||||
|
If specified, the files in the --to directory
|
||||||
|
will only be replaced if the download was successful.
|
||||||
|
--color
|
||||||
|
--no-color Explicitly enable or disable colored output.
|
||||||
|
--help Show this help message
|
||||||
|
|
||||||
|
ENVOIRNMENT
|
||||||
|
GEOIP_LICENSE_KEY can be used to set the licencse key.
|
||||||
|
|
||||||
|
EXIT CODES
|
||||||
|
1 Invalid paramters or filesystem envoirnment
|
||||||
|
2 Download failed
|
||||||
|
3 Expected file not found in download
|
||||||
|
4 Failed to extract download
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--license-key) GEOIP_LICENSE_KEY="$2"; shift 2;;
|
||||||
|
--product) PRODUCTS+=("$2"); shift 2;;
|
||||||
|
--GeoLite2-mmdb-all)
|
||||||
|
PRODUCTS+=("GeoLite2-ASN")
|
||||||
|
PRODUCTS+=("GeoLite2-City")
|
||||||
|
PRODUCTS+=("GeoLite2-Country")
|
||||||
|
shift 1;;
|
||||||
|
--to) DESTINATION_DIRECTORY="$2"; shift 2;;
|
||||||
|
--download-to) DOWNLOAD_LOCATION="$2"; shift 2;;
|
||||||
|
--color) COLOR_OUTPUT="y"; shift 1;;
|
||||||
|
--no-color) COLOR_OUTPUT=""; shift 1;;
|
||||||
|
|
||||||
|
--help) show_help; exit 0;;
|
||||||
|
*) printf "Unknown option: %s\n" "$1"; exit 1;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$GEOIP_LICENSE_KEY" ] ; then
|
||||||
|
msg "No License Key specified, the download won't work this way." init_error
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$DOWNLOAD_LOCATION" ] || DOWNLOAD_LOCATION="$DESTINATION_DIRECTORY"
|
||||||
|
|
||||||
|
if [ -d "$DESTINATION_DIRECTORY" ] || mkdir -p "$DESTINATION_DIRECTORY" ; then
|
||||||
|
true
|
||||||
|
else
|
||||||
|
msg "Destination is not a directory and can't be created!" init_error
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$DOWNLOAD_LOCATION" ] || mkdir -p "$DOWNLOAD_LOCATION" ; then
|
||||||
|
true
|
||||||
|
else
|
||||||
|
msg "Dowload location is not a directory and can't be created!" init_error
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${#PRODUCTS[@]}" -eq "0" ] ; then
|
||||||
|
msg "No products specified, nothing to do." init_error
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
get_product_file_ext() {
|
||||||
|
if printf "%s" "$1" | grep -q 'CSV$' ; then
|
||||||
|
echo csv
|
||||||
|
else
|
||||||
|
echo mmdb
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# PrductID,DOWNLOAD_LOCATION
|
||||||
|
download_maxmind_db() {
|
||||||
|
msg "Downloading Database $1 …" progess
|
||||||
|
# the path to download to
|
||||||
|
dl="$2/$1.tar.gz"
|
||||||
|
curl -fsSL -m 40 "https://download.maxmind.com/app/geoip_download?edition_id=$1&license_key=$GEOIP_LICENSE_KEY&suffix=tar.gz" > "$dl"
|
||||||
|
if [ "_$?" != "_0" ] ; then
|
||||||
|
msg "Databse download of $1 failed!" error
|
||||||
|
rm "$dl"
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
EXT="$(get_product_file_ext "$1")"
|
||||||
|
FILE_TO_EXTRACT="$(tar -tzf "$dl" | grep "/$1\.$EXT$")"
|
||||||
|
if [ -z "$FILE_TO_EXTRACT" ] ; then
|
||||||
|
msg "No .$EXT file found in the downloaded data!" error
|
||||||
|
rm "$dl"
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
msg "Extracting $FILE_TO_EXTRACT from downloaded archive …" progess
|
||||||
|
if tar -C "$2" --strip-components=1 -xzf "$dl" "$FILE_TO_EXTRACT" ; then
|
||||||
|
msg "File extracted successfully." success
|
||||||
|
rm "$dl"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
msg "File extraction failed!" error
|
||||||
|
rm "$dl"
|
||||||
|
return 4
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
EXIT_CODE=""
|
||||||
|
MSG_OUTPUT_TO_LOG="y"
|
||||||
|
for product in "${PRODUCTS[@]}" ; do
|
||||||
|
download_maxmind_db "$product" "$DOWNLOAD_LOCATION"
|
||||||
|
RETCODE="$?"
|
||||||
|
|
||||||
|
if [ "_$RETCODE" = "_0" ] ; then
|
||||||
|
filename="$product.$(get_product_file_ext "$product")"
|
||||||
|
if [ "_$DOWNLOAD_LOCATION" != "_$DESTINATION_DIRECTORY" ] ; then
|
||||||
|
msg "Moving destination file …" progess
|
||||||
|
if [ -e "$DESTINATION_DIRECTORY/$filename" ] ; then
|
||||||
|
[ -e "$DESTINATION_DIRECTORY/$filename.bak" ] && rm "$DESTINATION_DIRECTORY/$filename.bak"
|
||||||
|
mv "$DESTINATION_DIRECTORY/$filename" "$DESTINATION_DIRECTORY/$filename.bak"
|
||||||
|
fi
|
||||||
|
if mv "$DOWNLOAD_LOCATION/$filename" "$DESTINATION_DIRECTORY/$filename" ; then
|
||||||
|
msg "File $filename installed successfully." success
|
||||||
|
else
|
||||||
|
msg "Failed to install $filename!" error
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
[ -n "$EXIT_CODE" ] && [ "$EXIT_CODE" -lt "$RETCODE" ] || export EXIT_CODE="$RETCODE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $EXIT_CODE
|
35
src/geoip.rs
35
src/geoip.rs
@ -6,6 +6,8 @@
|
|||||||
use maxminddb;
|
use maxminddb;
|
||||||
use maxminddb::geoip2;
|
use maxminddb::geoip2;
|
||||||
|
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -47,8 +49,9 @@ pub struct AsnResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct MMDBCarrier {
|
pub struct MMDBCarrier {
|
||||||
pub mmdb: Option<maxminddb::Reader<Vec<u8>>>,
|
pub mmdb: RwLock<Option<maxminddb::Reader<Vec<u8>>>>,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait QueryLocation {
|
pub trait QueryLocation {
|
||||||
@ -122,7 +125,8 @@ pub fn geoip2_subdivision_to_named_location(item: geoip2::city::Subdivision, lan
|
|||||||
|
|
||||||
impl QueryAsn for MMDBCarrier {
|
impl QueryAsn for MMDBCarrier {
|
||||||
fn query_asn_for_ip(&self, address: &IpAddr) -> Option<AsnResult> {
|
fn query_asn_for_ip(&self, address: &IpAddr) -> Option<AsnResult> {
|
||||||
match &self.mmdb {
|
let mmdb = self.mmdb.read();
|
||||||
|
match &*mmdb {
|
||||||
Some(mmdb) => {
|
Some(mmdb) => {
|
||||||
match mmdb.lookup::<geoip2::Asn>(*address) {
|
match mmdb.lookup::<geoip2::Asn>(*address) {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
@ -144,7 +148,8 @@ impl QueryAsn for MMDBCarrier {
|
|||||||
|
|
||||||
impl QueryLocation for MMDBCarrier {
|
impl QueryLocation for MMDBCarrier {
|
||||||
fn query_location_for_ip(&self, address: &IpAddr, languages: &Vec<&String>) -> Option<LocationResult> {
|
fn query_location_for_ip(&self, address: &IpAddr, languages: &Vec<&String>) -> Option<LocationResult> {
|
||||||
match &self.mmdb {
|
let mmdb = self.mmdb.read();
|
||||||
|
match &*mmdb {
|
||||||
Some(mmdb) => {
|
Some(mmdb) => {
|
||||||
match mmdb.lookup::<geoip2::City>(*address) {
|
match mmdb.lookup::<geoip2::City>(*address) {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
@ -210,22 +215,38 @@ impl QueryLocation for MMDBCarrier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MMDBCarrier {
|
impl MMDBCarrier {
|
||||||
pub fn load_database_from_path(&mut self, path: &Path) -> Result<(),maxminddb::MaxMindDBError> {
|
pub fn new(name: String, path: Option<String>) -> MMDBCarrier {
|
||||||
|
MMDBCarrier {
|
||||||
|
mmdb: RwLock::new(None),
|
||||||
|
name: name,
|
||||||
|
path: path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reload_database(&self) -> Result<(),maxminddb::MaxMindDBError> {
|
||||||
|
match &self.path {
|
||||||
|
Some(path) => self.load_database_from_path(Path::new(&path)),
|
||||||
|
None => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_database_from_path(&self, path: &Path) -> Result<(),maxminddb::MaxMindDBError> {
|
||||||
|
let mut mmdb = self.mmdb.write();
|
||||||
println!("Loading {} from '{}' ...", &self.name, path.display());
|
println!("Loading {} from '{}' ...", &self.name, path.display());
|
||||||
match maxminddb::Reader::open_readfile(path) {
|
match maxminddb::Reader::open_readfile(path) {
|
||||||
Ok(reader) => {
|
Ok(reader) => {
|
||||||
let wording = if self.mmdb.is_some() {
|
let wording = if mmdb.is_some() {
|
||||||
"Replaced old"
|
"Replaced old"
|
||||||
} else {
|
} else {
|
||||||
"Loaded new"
|
"Loaded new"
|
||||||
};
|
};
|
||||||
self.mmdb = Some(reader);
|
*mmdb = Some(reader);
|
||||||
println!("{} {} with new one.", wording, &self.name);
|
println!("{} {} with new one.", wording, &self.name);
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error while reading {}: {}", &self.name, &e);
|
println!("Error while reading {}: {}", &self.name, &e);
|
||||||
if self.mmdb.is_some() {
|
if mmdb.is_some() {
|
||||||
println!("Not replacing old database.");
|
println!("Not replacing old database.");
|
||||||
}
|
}
|
||||||
Err(e)
|
Err(e)
|
||||||
|
55
src/main.rs
55
src/main.rs
@ -27,10 +27,15 @@ use trust_dns_resolver::{
|
|||||||
// config::ResolverConfig,
|
// config::ResolverConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use tokio::signal::unix::{
|
||||||
|
signal,
|
||||||
|
SignalKind,
|
||||||
|
};
|
||||||
|
use tokio::task;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod geoip;
|
mod geoip;
|
||||||
@ -205,23 +210,19 @@ async fn main() {
|
|||||||
|
|
||||||
// Initalize GeoIP Database
|
// Initalize GeoIP Database
|
||||||
|
|
||||||
let mut asn_db = geoip::MMDBCarrier {
|
let asn_db = geoip::MMDBCarrier::new(
|
||||||
mmdb: None,
|
"GeoIP ASN Database".to_string(),
|
||||||
name: "GeoIP ASN Database".to_string(),
|
config.geoip.asn_database.clone()
|
||||||
};
|
);
|
||||||
match &config.geoip.asn_database {
|
|
||||||
Some(path) => { asn_db.load_database_from_path(Path::new(&path)).ok(); },
|
|
||||||
None => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut location_db = geoip::MMDBCarrier {
|
asn_db.reload_database().ok();
|
||||||
mmdb: None,
|
|
||||||
name: "GeoIP Location Database".to_string(),
|
let location_db = geoip::MMDBCarrier::new(
|
||||||
};
|
"GeoIP Location Database".to_string(),
|
||||||
match &config.geoip.location_database {
|
config.geoip.location_database.clone()
|
||||||
Some(path) => { location_db.load_database_from_path(Path::new(&path)).ok(); },
|
);
|
||||||
None => {},
|
|
||||||
}
|
location_db.reload_database().ok();
|
||||||
|
|
||||||
// Initalize DNS resolver with os defaults
|
// Initalize DNS resolver with os defaults
|
||||||
println!("Initalizing dns resolver ...");
|
println!("Initalizing dns resolver ...");
|
||||||
@ -250,6 +251,26 @@ async fn main() {
|
|||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let signal_usr1_handlers_state = shared_state.clone();
|
||||||
|
|
||||||
|
task::spawn(async move {
|
||||||
|
println!("Trying to register USR1 signal for reloading geoip databases");
|
||||||
|
let mut signal_stream = match signal(SignalKind::user_defined1()) {
|
||||||
|
Ok(signal_stream) => signal_stream,
|
||||||
|
Err(e) => {
|
||||||
|
println!("Error while registring signal handler: {e}");
|
||||||
|
println!("Continuing without ...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loop {
|
||||||
|
if None == signal_stream.recv().await { return; }
|
||||||
|
println!("Received signal USR1, reloading geoip databses!");
|
||||||
|
signal_usr1_handlers_state.location_db.reload_database().ok();
|
||||||
|
signal_usr1_handlers_state.asn_db.reload_database().ok();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Initalize axum server
|
// Initalize axum server
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/", get(handle_default_route))
|
.route("/", get(handle_default_route))
|
||||||
|
@ -18,6 +18,8 @@ use trust_dns_resolver::{
|
|||||||
TokioAsyncResolver,
|
TokioAsyncResolver,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use tokio::join;
|
||||||
|
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
|
|
||||||
|
|
||||||
@ -211,34 +213,50 @@ pub async fn lookup(
|
|||||||
name: &String,
|
name: &String,
|
||||||
do_full_lookup: bool,
|
do_full_lookup: bool,
|
||||||
) -> DnsLookupResult {
|
) -> DnsLookupResult {
|
||||||
let ipv4_lookup_res = resolver.lookup(name, RecordType::A);
|
let (
|
||||||
let ipv6_lookup_res = resolver.lookup(name, RecordType::AAAA);
|
ipv4_lookup_res,
|
||||||
let cname_lookup_res = resolver.lookup(name, RecordType::CNAME);
|
ipv6_lookup_res,
|
||||||
let aname_lookup_res = resolver.lookup(name, RecordType::ANAME);
|
cname_lookup_res,
|
||||||
|
aname_lookup_res
|
||||||
|
) = join!(
|
||||||
|
resolver.lookup(name, RecordType::A),
|
||||||
|
resolver.lookup(name, RecordType::AAAA),
|
||||||
|
resolver.lookup(name, RecordType::CNAME),
|
||||||
|
resolver.lookup(name, RecordType::ANAME),
|
||||||
|
);
|
||||||
|
|
||||||
// initlize an empty lookup result
|
// initlize an empty lookup result
|
||||||
let mut dig_result: DnsLookupResult = Default::default();
|
let mut dig_result: DnsLookupResult = Default::default();
|
||||||
|
|
||||||
integrate_lookup_result(&mut dig_result, ipv4_lookup_res.await);
|
integrate_lookup_result(&mut dig_result, ipv4_lookup_res);
|
||||||
integrate_lookup_result(&mut dig_result, ipv6_lookup_res.await);
|
integrate_lookup_result(&mut dig_result, ipv6_lookup_res);
|
||||||
integrate_lookup_result(&mut dig_result, cname_lookup_res.await);
|
integrate_lookup_result(&mut dig_result, cname_lookup_res);
|
||||||
integrate_lookup_result(&mut dig_result, aname_lookup_res.await);
|
integrate_lookup_result(&mut dig_result, aname_lookup_res);
|
||||||
|
|
||||||
//Don't do an extented lookup if the domain seemingly doesn't exist
|
//Don't do an extented lookup if the domain seemingly doesn't exist
|
||||||
if do_full_lookup && !dig_result.nxdomain {
|
if do_full_lookup && !dig_result.nxdomain {
|
||||||
let mx_lookup_res = resolver.lookup(name, RecordType::MX);
|
let (
|
||||||
let ns_lookup_res = resolver.lookup(name, RecordType::NS);
|
mx_lookup_res,
|
||||||
let soa_lookup_res = resolver.lookup(name, RecordType::SOA);
|
ns_lookup_res,
|
||||||
let caa_lookup_res = resolver.lookup(name, RecordType::CAA);
|
soa_lookup_res,
|
||||||
let srv_lookup_res = resolver.lookup(name, RecordType::SRV);
|
caa_lookup_res,
|
||||||
let txt_lookup_res = resolver.lookup(name, RecordType::TXT);
|
srv_lookup_res,
|
||||||
|
txt_lookup_res
|
||||||
|
) = join!(
|
||||||
|
resolver.lookup(name, RecordType::MX),
|
||||||
|
resolver.lookup(name, RecordType::NS),
|
||||||
|
resolver.lookup(name, RecordType::SOA),
|
||||||
|
resolver.lookup(name, RecordType::CAA),
|
||||||
|
resolver.lookup(name, RecordType::SRV),
|
||||||
|
resolver.lookup(name, RecordType::TXT),
|
||||||
|
);
|
||||||
|
|
||||||
integrate_lookup_result(&mut dig_result, mx_lookup_res.await);
|
integrate_lookup_result(&mut dig_result, mx_lookup_res);
|
||||||
integrate_lookup_result(&mut dig_result, ns_lookup_res.await);
|
integrate_lookup_result(&mut dig_result, ns_lookup_res);
|
||||||
integrate_lookup_result(&mut dig_result, soa_lookup_res.await);
|
integrate_lookup_result(&mut dig_result, soa_lookup_res);
|
||||||
integrate_lookup_result(&mut dig_result, caa_lookup_res.await);
|
integrate_lookup_result(&mut dig_result, caa_lookup_res);
|
||||||
integrate_lookup_result(&mut dig_result, srv_lookup_res.await);
|
integrate_lookup_result(&mut dig_result, srv_lookup_res);
|
||||||
integrate_lookup_result(&mut dig_result, txt_lookup_res.await);
|
integrate_lookup_result(&mut dig_result, txt_lookup_res);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if r.cname %}
|
{% if r.cname %}
|
||||||
<p>This domain has a cname set, this means its contents are full replaced by the linked record.</p>
|
<p>This domain has a <code>CNAME</code> set, this means its contents are full replaced by the linked record.</p>
|
||||||
|
|
||||||
<p class="button-paragraph">{{ helper::dig(extra=extra, name=r.cname[0]) }}</p>
|
<p class="button-paragraph">{{ helper::dig(extra=extra, name=r.cname[0]) }}</p>
|
||||||
|
|
||||||
@ -194,7 +194,7 @@
|
|||||||
<h2>Programatic Lookup</h2>
|
<h2>Programatic Lookup</h2>
|
||||||
<p>If you want to look up this information in another program the short answer is <b>don't, look up the names using your local DNS!</b></p>
|
<p>If you want to look up this information in another program the short answer is <b>don't, look up the names using your local DNS!</b></p>
|
||||||
<p>On most systems on the commandline you have commands like <code>host</code> and <code>dig</code> even when not present you can probably use <code>ping</code> as a workaround as it resolves the name and gives you the IP-Address it is pinging.</p>
|
<p>On most systems on the commandline you have commands like <code>host</code> and <code>dig</code> even when not present you can probably use <code>ping</code> as a workaround as it resolves the name and gives you the IP-Address it is pinging.</p>
|
||||||
<h3>Why queryting this service is still useful</h3>
|
<h3>Why querying this service is still useful</h3>
|
||||||
<p>This service most probably doesn't share its cache with your local resolver, this way you have a way to see if your DNS-change had the effect it should have.</p>
|
<p>This service most probably doesn't share its cache with your local resolver, this way you have a way to see if your DNS-change had the effect it should have.</p>
|
||||||
<p>It may also be useful for debugging other dns problems or to get around a local resolver that is lying to you because your ISP is a <i>something</i>.</p>
|
<p>It may also be useful for debugging other dns problems or to get around a local resolver that is lying to you because your ISP is a <i>something</i>.</p>
|
||||||
<h3>How?</h3>
|
<h3>How?</h3>
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if r.location.coordinates %}
|
{% if r.location.coordinates %}
|
||||||
<dt>Coordinates</dt>
|
<dt>Coordinates</dt>
|
||||||
<dd><a href="{{ links::map_link(lat=r.location.coordinates.lat, lon=r.location.coordinates.lon)}}">lat: {{r.location.coordinates.lat}}, lon: {{r.location.coordinates.lon}}</a></dd>
|
<dd><a target="_blank" href="{{ links::map_link(lat=r.location.coordinates.lat, lon=r.location.coordinates.lon)}}">lat: {{r.location.coordinates.lat}}, lon: {{r.location.coordinates.lon}}</a></dd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</dl>
|
</dl>
|
||||||
<!--We have to put that there to comply with maxminds licensing-->
|
<!--We have to put that there to comply with maxminds licensing-->
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<ul class="link-list">
|
<ul class="link-list">
|
||||||
<li><a target="_blank" href="https://apps.db.ripe.net/db-web-ui/query?bflag=true&dflag=false&rflag=true&searchtext={{ address }}&source=RIPE">… in the RIPE Database</a></li>
|
<li><a target="_blank" href="https://apps.db.ripe.net/db-web-ui/query?bflag=true&dflag=false&rflag=true&searchtext={{ address }}&source=RIPE">… in the RIPE Database</a></li>
|
||||||
<li><a target="_blank" href="https://apps.db.ripe.net/db-web-ui/query?bflag=true&dflag=false&rflag=true&searchtext={{ address }}&source=GRS">… in the RIPE Global Resources Service</a></li>
|
<li><a target="_blank" href="https://apps.db.ripe.net/db-web-ui/query?bflag=true&dflag=false&rflag=true&searchtext={{ address }}&source=GRS">… in the RIPE Global Resources Service</a></li>
|
||||||
|
<li><a target="_blank" href="https://client.rdap.org/?type=ip&object={{ address }}">… on client.rdap.org <small>(a modern whois, make sure to allow xhr to 3rd parties)</small></a></li>
|
||||||
<li><a target="_blank" href="https://www.shodan.io/host/{{ address }}">… on shodan.io <small>(limited querys per day, wants an account)</small></a></li>
|
<li><a target="_blank" href="https://www.shodan.io/host/{{ address }}">… on shodan.io <small>(limited querys per day, wants an account)</small></a></li>
|
||||||
<li><a target="_blank" href="https://search.censys.io/search?resource=hosts&sort=RELEVANCE&per_page=25&virtual_hosts=EXCLUDE&q=ip%3D{{ address }}">… on search.censys.io <small>(10 querys per day, wants an account)</small></a></li>
|
<li><a target="_blank" href="https://search.censys.io/search?resource=hosts&sort=RELEVANCE&per_page=25&virtual_hosts=EXCLUDE&q=ip%3D{{ address }}">… on search.censys.io <small>(10 querys per day, wants an account)</small></a></li>
|
||||||
{% if not address is matching(":") %}
|
{% if not address is matching(":") %}
|
||||||
@ -18,6 +19,9 @@
|
|||||||
<li><a target="_blank" href="https://www.shodan.io/domain/{{ name }}">… on shodan.io <small>(limited querys per day, wants an account)</small></a></li>
|
<li><a target="_blank" href="https://www.shodan.io/domain/{{ name }}">… on shodan.io <small>(limited querys per day, wants an account)</small></a></li>
|
||||||
<li><a target="_blank" href="https://search.censys.io/search?resource=hosts&sort=RELEVANCE&per_page=25&virtual_hosts=EXCLUDE&q={{ name }}">… on search.censys.io <small>(10 querys per day, wants an account)</small></a></li>
|
<li><a target="_blank" href="https://search.censys.io/search?resource=hosts&sort=RELEVANCE&per_page=25&virtual_hosts=EXCLUDE&q={{ name }}">… on search.censys.io <small>(10 querys per day, wants an account)</small></a></li>
|
||||||
<li><a target="_blank" href="https://www.virustotal.com/gui/domain/{{ name }}">… on virustotal.com</a></li>
|
<li><a target="_blank" href="https://www.virustotal.com/gui/domain/{{ name }}">… on virustotal.com</a></li>
|
||||||
|
<li><a target="_blank" href="https://observatory.mozilla.org/analyze/{{ name }}">… on the Mozilla Observatory (http and tls checks)</a></li>
|
||||||
|
<li><a target="_blank" href="https://internet.nl/site/{{ name }}">… on the Internet.nl Website test</a></li>
|
||||||
|
<li><a target="_blank" href="https://client.rdap.org/?type=domain&object={{ name }}">… on client.rdap.org <small>(a modern whois, make sure to allow xhr to 3rd parties)</small></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endmacro domain_name_links %}
|
{% endmacro domain_name_links %}
|
||||||
|
|
||||||
@ -27,7 +31,8 @@
|
|||||||
<li><a target="_blank" href="https://bgp.he.net/AS{{asn}}">… on Hurricane Electric BGP Toolkit</a></li>
|
<li><a target="_blank" href="https://bgp.he.net/AS{{asn}}">… on Hurricane Electric BGP Toolkit</a></li>
|
||||||
<li><a target="_blank" href="https://radar.qrator.net/as{{asn}}">… on radar.qrator.net (BGP Tool)</a></li>
|
<li><a target="_blank" href="https://radar.qrator.net/as{{asn}}">… on radar.qrator.net (BGP Tool)</a></li>
|
||||||
<li><a target="_blank" href="https://search.censys.io/search?resource=hosts&sort=RELEVANCE&per_page=25&virtual_hosts=EXCLUDE&q=autonomous_system.asn%3D{{asn}}">… on search.censys.io <small>(10 querys per day, wants an account)</small></a></li>
|
<li><a target="_blank" href="https://search.censys.io/search?resource=hosts&sort=RELEVANCE&per_page=25&virtual_hosts=EXCLUDE&q=autonomous_system.asn%3D{{asn}}">… on search.censys.io <small>(10 querys per day, wants an account)</small></a></li>
|
||||||
<li><a target="_blank" href="https://query.wikidata.org/#%23Select%20Wikipedia%20articles%20that%20belong%20to%20a%20given%20asn%0ASELECT%20DISTINCT%20%3Fitem%20%3Fwebsite%20%3FitemLabel%20%3FitemDescription%20%3Flang%20%3Farticle%20WHERE%20%7B%0A%20%20VALUES%20%3Fasn%20%7B%0A%20%20%20%20%22{{ asn }}%22%0A%20%20%7D%0A%20%20%3Fasn%20%5Ewdt%3AP3797%20%3Fitem.%0A%20%20OPTIONAL%20%7B%20%3Fitem%20wdt%3AP856%20%3Fwebsite.%20%7D%0A%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fitem%20%5Eschema%3Aabout%20%3Farticle.%0A%20%20%20%20%3Farticle%20schema%3AisPartOf%20_%3Ab64.%0A%20%20%20%20_%3Ab64%20wikibase%3AwikiGroup%20%22wikipedia%22.%0A%20%20%20%20%3Farticle%20schema%3AinLanguage%20%3Flang%3B%0A%20%20%20%20%20%20schema%3Aname%20%3Farticlename.%0A%20%20%20%20FILTER(((%3Flang%20%3D%20%22%5BAUTO_LANGUAGE%5D%22)%20%7C%7C%20(%3Flang%20%3D%20%22en%22))%20%7C%7C%20(%3Flang%20%3D%20%22de%22))%0A%20%20%7D%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%0A%20%20%20%20bd%3AserviceParam%20wikibase%3Alanguage%20%22%5BAUTO_LANGUAGE%5D%2Cen%22.%0A%20%20%20%20%3Fitem%20rdfs%3Alabel%20%3FitemLabel%3B%0A%20%20%20%20%20%20schema%3Adescription%20%3FitemDescription.%0A%20%20%7D%0A%7D%0AORDER%20BY%20(UCASE(%3FitemLabel))">… on Wikidata and Wikipedia <small>(Press the run buttonin the sidebar to get results)</small></a></li>
|
<li><a target="_blank" href="https://client.rdap.org/?type=autnum&object={{ asn }}">… on client.rdap.org <small>(a modern whois, make sure to allow xhr to 3rd parties)</small></a></li>
|
||||||
|
<li><a target="_blank" href="https://query.wikidata.org/#%23Select%20Wikipedia%20articles%20that%20belong%20to%20a%20given%20asn%0ASELECT%20DISTINCT%20%3Fitem%20%3Fwebsite%20%3FitemLabel%20%3FitemDescription%20%3Flang%20%3Farticle%20WHERE%20%7B%0A%20%20VALUES%20%3Fasn%20%7B%0A%20%20%20%20%22{{ asn }}%22%0A%20%20%7D%0A%20%20%3Fasn%20%5Ewdt%3AP3797%20%3Fitem.%0A%20%20OPTIONAL%20%7B%20%3Fitem%20wdt%3AP856%20%3Fwebsite.%20%7D%0A%20%20OPTIONAL%20%7B%0A%20%20%20%20%3Fitem%20%5Eschema%3Aabout%20%3Farticle.%0A%20%20%20%20%3Farticle%20schema%3AisPartOf%20_%3Ab64.%0A%20%20%20%20_%3Ab64%20wikibase%3AwikiGroup%20%22wikipedia%22.%0A%20%20%20%20%3Farticle%20schema%3AinLanguage%20%3Flang%3B%0A%20%20%20%20%20%20schema%3Aname%20%3Farticlename.%0A%20%20%20%20FILTER(((%3Flang%20%3D%20%22%5BAUTO_LANGUAGE%5D%22)%20%7C%7C%20(%3Flang%20%3D%20%22en%22))%20%7C%7C%20(%3Flang%20%3D%20%22de%22))%0A%20%20%7D%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%0A%20%20%20%20bd%3AserviceParam%20wikibase%3Alanguage%20%22%5BAUTO_LANGUAGE%5D%2Cen%22.%0A%20%20%20%20%3Fitem%20rdfs%3Alabel%20%3FitemLabel%3B%0A%20%20%20%20%20%20schema%3Adescription%20%3FitemDescription.%0A%20%20%7D%0A%7D%0AORDER%20BY%20(UCASE(%3FitemLabel))">… on Wikidata and Wikipedia <small>(Press the run button in the sidebar to get results)</small></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endmacro asn_links %}
|
{% endmacro asn_links %}
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
User-agent: *
|
User-agent: *
|
||||||
Disallow: /*?
|
Disallow: /ip/
|
||||||
|
Disallow: /dig/
|
Reference in New Issue
Block a user