mirror of
https://codeberg.org/slatian/service.echoip-slatecave.git
synced 2025-07-16 22:13:30 +02:00
Compare commits
12 Commits
v1.4
...
8d055682b6
Author | SHA1 | Date | |
---|---|---|---|
8d055682b6 | |||
ff8d86ff1d | |||
ce7632d443 | |||
cf82db3e87 | |||
fecbe68c7a | |||
2e5a2408b4 | |||
3b4e6eba4b | |||
708fb9c0b3 | |||
0d711648a8 | |||
1863af50f8 | |||
52d2834e98 | |||
da391003e4 |
1230
Cargo.lock
generated
1230
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
15
Cargo.toml
15
Cargo.toml
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "echoip-slatecave"
|
||||
version = "1.2.4"
|
||||
version = "1.5.2"
|
||||
edition = "2021"
|
||||
authors = ["Slatian <baschdel@disroot.org>"]
|
||||
|
||||
@ -13,19 +13,18 @@ axum = { version = "0.7", features = ["macros"] }
|
||||
axum-extra = { version = "0.9", features = ["cookie", "typed-header"] }
|
||||
axum-client-ip = "0.6"
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
governor = "0.6"
|
||||
idna = "0.5"
|
||||
lazy_static = "1.4.0"
|
||||
governor = "0.8"
|
||||
idna = "1.0"
|
||||
parking_lot = "0.12"
|
||||
regex = "1.10"
|
||||
regex = "1.11"
|
||||
serde = { version = "1", features = ["derive","rc"] }
|
||||
tokio = { version = "1", features = ["macros","signal"] }
|
||||
tera = "1"
|
||||
toml = "0.8"
|
||||
tower = "0.4"
|
||||
tower-http = { version = "0.5", features = ["fs"] }
|
||||
tower = "0.5"
|
||||
tower-http = { version = "0.6", features = ["fs"] }
|
||||
hickory-proto = "0.24"
|
||||
hickory-resolver = { version = "0.24", features = ["dns-over-rustls","dns-over-https","dns-over-quic","native-certs"] }
|
||||
maxminddb = "0.24"
|
||||
mime = "0.3"
|
||||
http = "1.1"
|
||||
http = "1.2"
|
||||
|
21
README.md
21
README.md
@ -1,9 +1,20 @@
|
||||
# echoip-slatecave
|
||||
|
||||
This is a service inspired by ifconfig.co, but built from scratch with a more useful feature set (in rust !!1!).
|
||||
This is a service inspired by ifconfig.co, but built from scratch with a more useful feature set. Currently live on [echoip.slatecave.net](https://echoip.slatecave.net).
|
||||
|
||||
It is Licensed under the AGPL-v3 license.
|
||||
|
||||
## Maintainence Mode
|
||||
|
||||
This project is in maintanance mode.
|
||||
|
||||
This means the following will happen:
|
||||
* Dependency updates
|
||||
* Bugfixes
|
||||
* Small quality of life improvements
|
||||
|
||||
But no active feature development by Slatian.
|
||||
|
||||
## Building
|
||||
|
||||
Simply run `cargo build` after cloning. The binary should be called `target/debug/echoip-slatecave`.
|
||||
@ -63,10 +74,16 @@ In addition to that the following fields are accessible from inside the template
|
||||
|
||||
The templates are covered by the AGPL as well, please share them with your users if you modified them.
|
||||
|
||||
### GeoLite2 database
|
||||
### Geolocation databases
|
||||
|
||||
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.
|
||||
|
||||
As an alternative to MaxMind there is also [DB-IP who offer their free databases without a login](https://db-ip.com/db/lite.php). You want the City and ASN databases in mmdb format.
|
||||
|
||||
**Don't forget to set the atttribution in the template configuration appropriately.**
|
||||
|
||||
See the file `templates/extra.toml`.
|
||||
|
||||
Since v1.0 echoip-slatecave reloads the databses when it rececieves a `USR1` signal.
|
||||
|
||||
## Security Considerations
|
||||
|
@ -23,7 +23,6 @@ pub struct ServerConfig {
|
||||
pub ip_header: SecureClientIpSource,
|
||||
|
||||
pub allow_private_ip_lookup: bool,
|
||||
pub static_location: Option<String>,
|
||||
}
|
||||
|
||||
|
||||
@ -53,7 +52,6 @@ impl Default for ServerConfig {
|
||||
listen_on: "127.0.0.1:3000".parse().unwrap(),
|
||||
ip_header: SecureClientIpSource::ConnectInfo,
|
||||
allow_private_ip_lookup: false,
|
||||
static_location: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
14
src/main.rs
14
src/main.rs
@ -17,7 +17,6 @@ use axum_client_ip::SecureClientIp;
|
||||
use axum_extra::headers;
|
||||
use axum_extra::TypedHeader;
|
||||
use clap::Parser;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize,Serialize};
|
||||
use tower::ServiceBuilder;
|
||||
@ -33,7 +32,9 @@ use tokio::task;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::net::IpAddr;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use lib_humus::TemplateEngineLoader;
|
||||
use lib_humus::read_toml_from_file;
|
||||
@ -121,7 +122,7 @@ struct CliArgs {
|
||||
#[arg(short, long)]
|
||||
config: Option<String>,
|
||||
#[arg(short, long)]
|
||||
listen_on: Option<String>,
|
||||
listen_on: Option<SocketAddr>,
|
||||
#[arg(short, long)]
|
||||
template_location: Option<String>,
|
||||
#[arg(short,long)]
|
||||
@ -243,7 +244,7 @@ async fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let listen_on = config.server.listen_on;
|
||||
let listen_on = cli_args.listen_on.unwrap_or(config.server.listen_on);
|
||||
let ip_header = config.server.ip_header.clone();
|
||||
|
||||
// Initialize shared state
|
||||
@ -443,6 +444,8 @@ async fn handle_default_route(
|
||||
)
|
||||
}
|
||||
|
||||
static ASN_REGEX: LazyLock<Regex> = LazyLock::new(|| { Regex::new(r"^[Aa][Ss][Nn]?\s*(\d{1,7})$").unwrap() });
|
||||
static VIA_REGEX: LazyLock<Regex> = LazyLock::new(|| { Regex::new(r"[Vv][Ii][Aa]\s+(\S+)").unwrap() });
|
||||
|
||||
async fn handle_search_request(
|
||||
search_query: String,
|
||||
@ -455,11 +458,6 @@ async fn handle_search_request(
|
||||
let mut search_query = search_query.trim().to_string();
|
||||
let mut settings = settings;
|
||||
|
||||
lazy_static!{
|
||||
static ref ASN_REGEX: Regex = Regex::new(r"^[Aa][Ss][Nn]?\s*(\d{1,7})$").unwrap();
|
||||
static ref VIA_REGEX: Regex = Regex::new(r"[Vv][Ii][Aa]\s+(\S+)").unwrap();
|
||||
}
|
||||
|
||||
//If someone asked for an asn, give an asn answer
|
||||
if let Some(asn_cap) = ASN_REGEX.captures(&search_query) {
|
||||
if let Some(asn) = asn_cap.get(1).map_or(None, |m| m.as_str().parse::<u32>().ok()) {
|
||||
|
@ -5,6 +5,9 @@
|
||||
<meta charset="utf-8">
|
||||
<title>{% block title %}{{ extra[view].title | default(value="…") }}{% endblock %} | {{extra.site_name|default(value="echoip")}}</title>
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport">
|
||||
<meta name="color-scheme" content="echoip-slatecave <https://codeberg.org/slatian/service.echoip-slatecave>">
|
||||
{% block robots_meta %}
|
||||
{% endblock robots_meta %}
|
||||
<!-- Open-Graph -->
|
||||
{% block metadata %}
|
||||
<meta name="description" property="og:description" content="{% block description %}{{ extra[view].description | default(value="One of the best echoip services") | escape_xml }}{% endblock %}" />
|
||||
|
@ -2,6 +2,8 @@
|
||||
{% import "helpers.html" as helper %}
|
||||
{% import "links.html" as links %}
|
||||
|
||||
{% block robots_meta %}<meta name="robots" content="noindex,nofollow">{% endblock %}
|
||||
|
||||
{% block title %}dig {{ data.query }}{% endblock %}
|
||||
{% block og_title %}dig {{ data.query }}{% endblock %}
|
||||
{% block h1 %}dig <code>{{ helper::breadcrumb_domain(extra=extra, name=data.query) }}</code> <small>via <a href="{{extra.base_url}}/dns_resolver/{{data.result.used_dns_resolver}}">{{data.result.used_dns_resolver}}</a></small>{% endblock %}
|
||||
|
@ -21,6 +21,13 @@ display_icon = "/icon_64.png"
|
||||
v4_url="http://v4.localhost:3000/"
|
||||
v6_url="http://v6.localhost:3000/"
|
||||
|
||||
# Geolocation Attribution for MaxMind
|
||||
#geo_attribution_html="The Geolocation and ASN information is provided by the GeoLite2 database created by <a href='https://www.maxmind.com/'>MaxMind</a>."
|
||||
|
||||
# Geolocation Attribution for DB-IP
|
||||
#geo_attribution_html="The Geolocation and ASN information is provided by <a href='https://db-ip.com/'>DB-IP</a>."
|
||||
|
||||
|
||||
[404]
|
||||
# configure the 404 page, this is available for other pages too!
|
||||
# Use the template name as the section name.
|
||||
|
@ -1,6 +1,8 @@
|
||||
{% extends "ip.html" %}
|
||||
{% import "helpers.html" as helper %}
|
||||
|
||||
{% block robots_meta %}{# Allow indexing for landing page #}{% endblock %}
|
||||
|
||||
{% block title %}Your IP: {{ data.result.address }}{% endblock %}
|
||||
{% block og_title %}What is my IP-Address?{% endblock %}
|
||||
{% block h1 %}Your IPv{% if data.result.ip_info.is_v6_address %}6{% else %}4{% endif %}: <code>{{ data.result.address }}</code>{% endblock %}
|
||||
|
@ -2,6 +2,8 @@
|
||||
{% import "helpers.html" as helper %}
|
||||
{% import "links.html" as links %}
|
||||
|
||||
{% block robots_meta %}<meta name="robots" content="noindex,nofollow">{% endblock %}
|
||||
|
||||
{% block title %}{{ data.result.address }}{% endblock %}
|
||||
{% block og_title %}Lookup {{ data.result.address }}{% endblock %}
|
||||
{% block h1 %}Lookup <code>{{ data.result.address }}</code>{% endblock %}
|
||||
@ -34,43 +36,44 @@
|
||||
{% if r.location %}
|
||||
<section>
|
||||
<h2>Geolocation</h2>
|
||||
<dl>
|
||||
{{ 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="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") }}
|
||||
{% endif %}
|
||||
{% if r.location.subdivisions %}
|
||||
{% for sd in r.location.subdivisions %}
|
||||
{{ helper::place_dl(place=sd, label="Subdivision", iso_code_prefix=r.location.country.iso_code|default(value="")) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{{ helper::place_dl(place=r.location.city, label="City") }}
|
||||
{% if r.location.postal_code %}
|
||||
<dt>Postal Code</dt>
|
||||
<dd>{{r.location.postal_code}}</dd>
|
||||
{% endif %}
|
||||
{% if r.location.time_zone %}
|
||||
<dt>Timezone</dt>
|
||||
<dd>{{r.location.time_zone}}</dd>
|
||||
{% endif %}
|
||||
{% if r.location.accuracy %}
|
||||
<dt>Accuracy</dt>
|
||||
<dd>~{{r.location.accuracy}}km</dd>
|
||||
{% endif %}
|
||||
{% if r.location.coordinates %}
|
||||
<dt>Coordinates</dt>
|
||||
<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 GeoIP and ASN information is provided by the GeoLite2 database created by
|
||||
<a target="_blank" href="https://www.maxmind.com">MaxMind</a>.
|
||||
</small></p>
|
||||
{% if extra.geo_attribution_html %}
|
||||
<dl>
|
||||
{{ 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="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") }}
|
||||
{% endif %}
|
||||
{% if r.location.subdivisions %}
|
||||
{% for sd in r.location.subdivisions %}
|
||||
{{ helper::place_dl(place=sd, label="Subdivision", iso_code_prefix=r.location.country.iso_code|default(value="")) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{{ helper::place_dl(place=r.location.city, label="City") }}
|
||||
{% if r.location.postal_code %}
|
||||
<dt>Postal Code</dt>
|
||||
<dd>{{r.location.postal_code}}</dd>
|
||||
{% endif %}
|
||||
{% if r.location.time_zone %}
|
||||
<dt>Timezone</dt>
|
||||
<dd>{{r.location.time_zone}}</dd>
|
||||
{% endif %}
|
||||
{% if r.location.accuracy %}
|
||||
<dt>Accuracy</dt>
|
||||
<dd>~{{r.location.accuracy}}km</dd>
|
||||
{% endif %}
|
||||
{% if r.location.coordinates %}
|
||||
<dt>Coordinates</dt>
|
||||
<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>
|
||||
<p><small>{{extra.geo_attribution_html | safe}}</small></p>
|
||||
{% else %}
|
||||
<p><strong style="font-size: 2em">Please configure the <code>geo_attribution_html</code> key in the template extra configuration!</strong></p>
|
||||
<p>The geolocation information will then become visible.</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endif %}
|
||||
{% block extra_content %}{% endblock %}
|
||||
|
@ -59,7 +59,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 GeoIP and ASN information is provided by the GeoLite2 database created by MaxMind.
|
||||
{{ extra.geo_attribution_html | default(value="Please configure the geo_attribution_html key in the template extra configuration.") | striptags }}
|
||||
{% endif -%}
|
||||
|
||||
{%- block extra_content %}{% endblock -%}
|
||||
|
Reference in New Issue
Block a user