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 | |
---|---|---|---|
c9d0c44985 | |||
f9753ccbfc | |||
a9512d7d4d | |||
6a57780490 | |||
51f27be997 | |||
554c788488 | |||
6d7e5ac18f |
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -372,6 +372,7 @@ dependencies = [
|
||||
"idna 0.3.0",
|
||||
"lazy_static",
|
||||
"maxminddb",
|
||||
"parking_lot",
|
||||
"regex",
|
||||
"serde",
|
||||
"tera",
|
||||
|
@ -13,6 +13,7 @@ clap = { version = "4", features = ["derive"] }
|
||||
governor = "0.5"
|
||||
idna = "0.3"
|
||||
lazy_static = "1.4.0"
|
||||
parking_lot = "0.12"
|
||||
regex = "1.7"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
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.
|
||||
|
||||
### 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
|
||||
|
||||
### Information disclosure
|
||||
@ -59,7 +65,7 @@ For a public service you should use a reverse proxy like Caddy, apache2 or nginx
|
||||
### 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.
|
||||
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
|
||||
|
||||
|
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::geoip2;
|
||||
|
||||
use parking_lot::RwLock;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::net::IpAddr;
|
||||
use std::path::Path;
|
||||
@ -47,8 +49,9 @@ pub struct AsnResult {
|
||||
}
|
||||
|
||||
pub struct MMDBCarrier {
|
||||
pub mmdb: Option<maxminddb::Reader<Vec<u8>>>,
|
||||
pub mmdb: RwLock<Option<maxminddb::Reader<Vec<u8>>>>,
|
||||
pub name: String,
|
||||
pub path: Option<String>,
|
||||
}
|
||||
|
||||
pub trait QueryLocation {
|
||||
@ -122,7 +125,8 @@ pub fn geoip2_subdivision_to_named_location(item: geoip2::city::Subdivision, lan
|
||||
|
||||
impl QueryAsn for MMDBCarrier {
|
||||
fn query_asn_for_ip(&self, address: &IpAddr) -> Option<AsnResult> {
|
||||
match &self.mmdb {
|
||||
let mmdb = self.mmdb.read();
|
||||
match &*mmdb {
|
||||
Some(mmdb) => {
|
||||
match mmdb.lookup::<geoip2::Asn>(*address) {
|
||||
Ok(res) => {
|
||||
@ -144,7 +148,8 @@ impl QueryAsn for MMDBCarrier {
|
||||
|
||||
impl QueryLocation for MMDBCarrier {
|
||||
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) => {
|
||||
match mmdb.lookup::<geoip2::City>(*address) {
|
||||
Ok(res) => {
|
||||
@ -210,22 +215,38 @@ impl QueryLocation for 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());
|
||||
match maxminddb::Reader::open_readfile(path) {
|
||||
Ok(reader) => {
|
||||
let wording = if self.mmdb.is_some() {
|
||||
let wording = if mmdb.is_some() {
|
||||
"Replaced old"
|
||||
} else {
|
||||
"Loaded new"
|
||||
};
|
||||
self.mmdb = Some(reader);
|
||||
*mmdb = Some(reader);
|
||||
println!("{} {} with new one.", wording, &self.name);
|
||||
Ok(())
|
||||
},
|
||||
Err(e) => {
|
||||
println!("Error while reading {}: {}", &self.name, &e);
|
||||
if self.mmdb.is_some() {
|
||||
if mmdb.is_some() {
|
||||
println!("Not replacing old database.");
|
||||
}
|
||||
Err(e)
|
||||
|
55
src/main.rs
55
src/main.rs
@ -27,10 +27,15 @@ use trust_dns_resolver::{
|
||||
// config::ResolverConfig,
|
||||
};
|
||||
|
||||
use tokio::signal::unix::{
|
||||
signal,
|
||||
SignalKind,
|
||||
};
|
||||
use tokio::task;
|
||||
|
||||
use std::fs;
|
||||
use std::net::IpAddr;
|
||||
use std::sync::Arc;
|
||||
use std::path::Path;
|
||||
|
||||
mod config;
|
||||
mod geoip;
|
||||
@ -205,23 +210,19 @@ async fn main() {
|
||||
|
||||
// Initalize GeoIP Database
|
||||
|
||||
let mut asn_db = geoip::MMDBCarrier {
|
||||
mmdb: None,
|
||||
name: "GeoIP ASN Database".to_string(),
|
||||
};
|
||||
match &config.geoip.asn_database {
|
||||
Some(path) => { asn_db.load_database_from_path(Path::new(&path)).ok(); },
|
||||
None => {},
|
||||
}
|
||||
let asn_db = geoip::MMDBCarrier::new(
|
||||
"GeoIP ASN Database".to_string(),
|
||||
config.geoip.asn_database.clone()
|
||||
);
|
||||
|
||||
let mut location_db = geoip::MMDBCarrier {
|
||||
mmdb: None,
|
||||
name: "GeoIP Location Database".to_string(),
|
||||
};
|
||||
match &config.geoip.location_database {
|
||||
Some(path) => { location_db.load_database_from_path(Path::new(&path)).ok(); },
|
||||
None => {},
|
||||
}
|
||||
asn_db.reload_database().ok();
|
||||
|
||||
let location_db = geoip::MMDBCarrier::new(
|
||||
"GeoIP Location Database".to_string(),
|
||||
config.geoip.location_database.clone()
|
||||
);
|
||||
|
||||
location_db.reload_database().ok();
|
||||
|
||||
// Initalize DNS resolver with os defaults
|
||||
println!("Initalizing dns resolver ...");
|
||||
@ -250,6 +251,26 @@ async fn main() {
|
||||
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
|
||||
let app = Router::new()
|
||||
.route("/", get(handle_default_route))
|
||||
|
@ -43,7 +43,7 @@
|
||||
<footer>
|
||||
<p>You can find the <a href="https://codeberg.org/slatian/service.echoip-slatecave">echoip-slatecave sourcecode on Codeberg</a>. If you found a bug or have an idea, feature, etc. please get in touch (I also accept E-Mails!).</p>
|
||||
<!-- If you made your own template, link to it here -->
|
||||
<p>This service works in its current form because nobody is abusing it, please keep that in mind. If you want to do frequent automated requests please host your own instace. Thank you for being awesome!</p>
|
||||
<p>This service works in its current form because nobody is abusing it, please keep that in mind. If you want to do frequent automated requests please host your own instance. Thank you for being awesome!</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -10,7 +10,7 @@ You can get the json version:
|
||||
{%- if view == "404" %}
|
||||
## Usage
|
||||
|
||||
You can query this service using the folowing endpoints …
|
||||
You can query this service using the following endpoints …
|
||||
=> {{ extra.base_url }}/ip/<address> … to query for an ip-address
|
||||
=> {{ extra.base_url }}/dig/<name> … to query for a domain-name
|
||||
=> {{ extra.base_url }}/ua … to get your user agent
|
||||
@ -21,5 +21,5 @@ You can find the echoip-slatecave sourcecode on Codeberg.
|
||||
=> https://codeberg.org/slatian/service.echoip-slatecave
|
||||
If you found a bug or have an idea, feature, etc. please get in touch (I also accept E-Mails!).
|
||||
|
||||
This service works in its current form because nobody is abusing it, please keep that in mind. If you want to do frequent automated requests please host your own instace. Thank you for being awesome!
|
||||
This service works in its current form because nobody is abusing it, please keep that in mind. If you want to do frequent automated requests please host your own instance. Thank you for being awesome!
|
||||
{% endif %}
|
||||
|
@ -13,7 +13,7 @@
|
||||
{% set idn = data.result.idn %}
|
||||
<section>
|
||||
<h2>Internationalized Domain Names</h2>
|
||||
<p>Because of some limitations the DNS has, Unicode caracters need a special encoding.</p>
|
||||
<p>Because of some limitations the DNS has, Unicode characters need a special encoding.</p>
|
||||
{% if idn.original_was == "unicode" %}
|
||||
<p>Your Unicode query has been encoded as the <i>IDN</i> <code>{{ idn.idn }}</code> to generate the results below.</p>
|
||||
{% else %}
|
||||
@ -39,11 +39,11 @@
|
||||
{% endif %}
|
||||
|
||||
{% 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>Usually you get the <code>A</code> and <code>AAAA</code> records for the linked record to avoid uneccessary requests. If anything else resolves, that is a violation of the DNS specification.</p>
|
||||
</p>Usually you get the <code>A</code> and <code>AAAA</code> records for the linked record to avoid unnecessary requests. If anything else resolves, that is a violation of the DNS specification.</p>
|
||||
|
||||
{% if r.cname | length > 1 %}
|
||||
<p>This domain resolves to multiple <code>CNAME</code>s, this is not allowed by the DNS specification!</p>
|
||||
@ -191,15 +191,15 @@
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Programatic Lookup</h2>
|
||||
<h2>Programmatic 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>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>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>
|
||||
<p>You can choose between the <code>html</code>, <code>text</code> and <code>json</code> format.</p>
|
||||
<p>An example of an url could be: <code>{{ extra.base_url }}/dig/example.org?format=json</code></p>
|
||||
<p>An example of an URL could be: <code>{{ extra.base_url }}/dig/example.org?format=json</code></p>
|
||||
</section>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -9,7 +9,7 @@
|
||||
{%- set idn = data.result.idn -%}
|
||||
## Internationalized Domain Names
|
||||
|
||||
Because of some limitations the DNS has, Unicode caracters need a special encoding.
|
||||
Because of some limitations the DNS has, Unicode characters need a special encoding.
|
||||
{%- if idn.original_was == "unicode" -%}
|
||||
Your Unicode query has been encoded as an IDN to generate the results below.
|
||||
```
|
||||
@ -43,7 +43,7 @@ This domain has a cname set, this means its contents are full replaced by the li
|
||||
|
||||
{{ r.cname[0] }}
|
||||
|
||||
Usually you get the A and AAAA records for the linked record to avoid uneccessary requests. If anything else resolves, that is a violation of the DNS specification.
|
||||
Usually you get the A and AAAA records for the linked record to avoid unnecessary requests. If anything else resolves, that is a violation of the DNS specification.
|
||||
{% if r.cname | length > 1 -%}
|
||||
This domain resolves to multiple CNAMEs, this is not allowed by the DNS specification!
|
||||
{%- endif %}
|
||||
|
@ -1,23 +1,24 @@
|
||||
site_name="echoip-slatecave"
|
||||
base_url="http://localhost:3000"
|
||||
|
||||
# Url to the deafult opengraph preview image
|
||||
# Url to the default opengraph preview image
|
||||
# og_image=""
|
||||
|
||||
# Url to your stylesheet
|
||||
# URL to your stylesheet
|
||||
stylesheet = "/style.css"
|
||||
|
||||
#Url to and mimetype of your favicon
|
||||
# URL to and mimetype of your favicon
|
||||
# favicon = ""
|
||||
# favicon_mimetype = "image/png"
|
||||
# favicon_mimetype = "image/jpeg"
|
||||
|
||||
# Urls to look up v4 and v6 addresses explicitly
|
||||
# URLs to look up v4 and v6 addresses explicitly
|
||||
# If you have not configured them, comment them out, the button will stay hidden
|
||||
v4_url="http://v4.localhost:3000/"
|
||||
v6_url="http://v6.localhost:3000/"
|
||||
|
||||
[404]
|
||||
# configure the 404 page, this is available for other pages too!
|
||||
# Use the template name as the section name.
|
||||
title = "Nothing here"
|
||||
description = "Page not found"
|
||||
|
@ -6,7 +6,7 @@
|
||||
{% block h1 %}Your IPv{% if data.result.ip_info.is_v6_address %}6{% else %}4{% endif %}: <code>{{ data.result.address }}</code>{% endblock %}
|
||||
|
||||
{% block description %}
|
||||
Look up Your and others public IP-Adresses. - {{ data.result.address }}
|
||||
Look up Your and others public IP-Addresses. - {{ data.result.address }}
|
||||
{% endblock %}
|
||||
|
||||
{% block og_path %}/{% endblock %}
|
||||
@ -27,7 +27,7 @@
|
||||
<section>
|
||||
<h2>Your User Agent</h2>
|
||||
<p>The program you were using to download this page <a href="https://en.wikipedia.org/wiki/User_agent">identified itself</a> as <code>{{ data.user_agent }}</code></p>
|
||||
<p>While this doesn't have to do anything with your public IP-Adress this might be useful information.</p>
|
||||
<p>While this doesn't have to do anything with your public IP-Address this might be useful information.</p>
|
||||
<p>You can use the <code><a href="{{ extra.base_url}}/ua">/ua</a></code> endpoint to fetch this information with any client.</p>
|
||||
</section>
|
||||
<section>
|
||||
|
@ -1,5 +1,5 @@
|
||||
{% extends "ip.txt" %}
|
||||
|
||||
{% block title -%}
|
||||
Your IP-Adress is: {{ data.result.address }}
|
||||
Your IP-Address is: {{ data.result.address }}
|
||||
{%- endblock %}
|
||||
|
@ -35,7 +35,7 @@
|
||||
{{ helper::place_dl(place=r.location.continent, label="Continent") }}
|
||||
{{ helper::place_dl(place=r.location.country, label="Country") }}
|
||||
{% if r.location.country.iso_code | default(value="") != r.location.registered_country.iso_code | default(value="") %}
|
||||
{{ helper::place_dl(place=r.location.registered_country, label="Registred in") }}
|
||||
{{ helper::place_dl(place=r.location.registered_country, label="Registered in") }}
|
||||
{% endif %}
|
||||
{% if r.location.country.iso_code | default(value="") != r.location.represented_country.iso_code | default(value="")%}
|
||||
{{ helper::place_dl(place=r.location.represented_country, label="Represents") }}
|
||||
@ -55,17 +55,17 @@
|
||||
<dd>{{r.location.time_zone}}</dd>
|
||||
{% endif %}
|
||||
{% if r.location.accuracy %}
|
||||
<dt>Accuaracy</dt>
|
||||
<dt>Accuracy</dt>
|
||||
<dd>~{{r.location.accuracy}}km</dd>
|
||||
{% endif %}
|
||||
{% if r.location.coordinates %}
|
||||
<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 %}
|
||||
</dl>
|
||||
<!--We have to put that there to comply with maxminds licensing-->
|
||||
<p><small>
|
||||
The GeopIP and ASN information is provided by the GeoLite2 database created by
|
||||
The GeoIP and ASN information is provided by the GeoLite2 database created by
|
||||
<a target="_blank" href="https://www.maxmind.com">MaxMind</a>.
|
||||
</small></p>
|
||||
</section>
|
||||
@ -80,11 +80,11 @@
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>Programatic Lookup</h2>
|
||||
<h2>Programmatic Lookup</h2>
|
||||
<p>If you want to look up this IP-Address Information in another program that is okay as long as you are civil about it … (ratelimit)</p>
|
||||
<h3>How?</h3>
|
||||
<p>You can choose between the <code>html</code>, <code>text</code> and <code>json</code> format.</p>
|
||||
<p>An example of an url could be: <code>{{ extra.base_url }}/ip/1.2.3.4?format=json</code></p>
|
||||
<p>An example of an URL could be: <code>{{ extra.base_url }}/ip/1.2.3.4?format=json</code></p>
|
||||
<p>To look up your IP-Address as json: <code>{{ extra.base_url }}/?format=json</code></p>
|
||||
</section>
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
{{ helper::place_dl(place=r.location.continent, label="Continent") -}}
|
||||
{{ helper::place_dl(place=r.location.country, label="Country") -}}
|
||||
{%- if r.location.country.iso_code | default(value="") != r.location.registered_country.iso_code | default(value="") -%}
|
||||
{{- helper::place_dl(place=r.location.registered_country, label="Registred in") -}}
|
||||
{{- helper::place_dl(place=r.location.registered_country, label="Registered in") -}}
|
||||
{%- endif -%}
|
||||
{%- if r.location.country.iso_code | default(value="") != r.location.represented_country.iso_code | default(value="") -%}
|
||||
{{- helper::place_dl(place=r.location.represented_country, label="Represents") -}}
|
||||
@ -44,7 +44,7 @@
|
||||
* Timezone: {{r.location.time_zone}}
|
||||
{% endif -%}
|
||||
{%- if r.location.accuracy -%}
|
||||
* Accuaracy: ~{{r.location.accuracy}}km
|
||||
* Accuracy: ~{{r.location.accuracy}}km
|
||||
{% endif %}
|
||||
{%- if r.location.coordinates %}
|
||||
### Coordinates
|
||||
@ -52,7 +52,7 @@ lat: {{r.location.coordinates.lat}}, lon: {{r.location.coordinates.lon}}
|
||||
=> {{ links::map_link(lat=r.location.coordinates.lat, lon=r.location.coordinates.lon)}}
|
||||
{%- endif %}
|
||||
|
||||
The GeopIP and ASN information is provided by the GeoLite2 database created by MaxMind.
|
||||
The GeoIP and ASN information is provided by the GeoLite2 database created by MaxMind.
|
||||
{% endif -%}
|
||||
|
||||
{%- block extra_content %}{% endblock -%}
|
||||
|
@ -3,8 +3,9 @@
|
||||
<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=GRS">… in the RIPE Global Resources Service</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://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 queries 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 query per day, wants an account)</small></a></li>
|
||||
{% if not address is matching(":") %}
|
||||
{# v4 only #}
|
||||
<li><a target="_blank" href="https://www.virustotal.com/gui/ip-address/{{ address }}">… on virustotal.com</a></li>
|
||||
@ -15,9 +16,12 @@
|
||||
{% macro domain_name_links(name) %}
|
||||
<p>Look up <code>{{name}}</code></p>
|
||||
<ul class="link-list">
|
||||
<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://www.shodan.io/domain/{{ name }}">… on shodan.io <small>(limited query's 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 query's 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://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>
|
||||
{% endmacro domain_name_links %}
|
||||
|
||||
@ -26,8 +30,9 @@
|
||||
<ul class="link-list">
|
||||
<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://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://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 query's per day, wants an account)</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>
|
||||
{% endmacro asn_links %}
|
||||
|
||||
|
@ -1,2 +1,3 @@
|
||||
User-agent: *
|
||||
Disallow: /*?
|
||||
Disallow: /ip/
|
||||
Disallow: /dig/
|
Reference in New Issue
Block a user