Set up configuration for dns blocking of private domains.

This commit is contained in:
Slatian 2023-02-19 10:37:57 +01:00
parent 645a0eed69
commit ee19071a3d
4 changed files with 149 additions and 18 deletions

42
echoip_full.toml Normal file
View File

@ -0,0 +1,42 @@
[server]
# What port to listen on and where request are supposed to come from
listen_on = "127.0.0.1:3000"
# What header your reverse proxy sets that contains the real ip-address
# Possible Values: Every Vaiation of SecureClientIpSource in the axum_client_ip package
# https://docs.rs/axum-client-ip/latest/axum_client_ip/enum.SecureClientIpSource.html
#ip_header = "RightmostXForwardedFor"
# When you don't want to use a proxy server:
ip_header = "ConnectInfo"
[dns]
# Enable the /dig enpoint
allow_forward_lookup = true
# Enable reverse lookup, make sure to configure the hidden_suffixes
# to contain your locally used domains, to prevent onformation leakage
allow_reverse_lookup = true
# Hide anything that has to do with private ip ranges
# Useful dor public services, disable if you want it
# on your internal network for some reason
#hide_private_range_ips = true
# echoip-sltecave will pretend that domains
# that end with one of these suffixes don't exist
hidden_suffixes = [".com"]
[geoip]
# Path to geoip databses
# Currently only the mmdb format is supported
# Official databases can be obtained from maxmind.com
#asn_database = "mmdb/GeoLite2-ASN.mmdb"
#location_database = "mmdb/GeoLite2-City.mmdb"
# If anyone knows a free (as in freedom) groip database
# please open an issue so I can integrate it
# https://codeberg.org/slatian/service.echoip-slatecave
[template]
# Path to the template directory, can contain glob patterns
#template_location = "templates"

42
echoip_test.toml Normal file
View File

@ -0,0 +1,42 @@
[server]
# What port to listen on and where request are supposed to come from
listen_on = "127.0.0.1:3000"
# What header your reverse proxy sets that contains the real ip-address
# Possible Values: Every Vaiation of SecureClientIpSource in the axum_client_ip package
# https://docs.rs/axum-client-ip/latest/axum_client_ip/enum.SecureClientIpSource.html
#ip_header = "RightmostXForwardedFor"
# When you don't want to use a proxy server:
ip_header = "ConnectInfo"
[dns]
# Enable the /dig enpoint
allow_forward_lookup = true
# Enable reverse lookup, make sure to configure the hidden_suffixes
# to contain your locally used domains, to prevent onformation leakage
allow_reverse_lookup = true
# Hide anything that has to do with private ip ranges
# Useful dor public services, disable if you want it
# on your internal network for some reason
hide_private_range_ips = true
# echoip-sltecave will pretend that domains
# that end with one of these suffixes don't exist
hidden_suffixes = [".com"]
[geoip]
# Path to geoip databses
# Currently only the mmdb format is supported
# Official databases can be obtained from maxmind.com
#asn_database = "mmdb/GeoLite2-ASN.mmdb"
#location_database = "mmdb/GeoLite2-City.mmdb"
# If anyone knows a free (as in freedom) groip database
# please open an issue so I can integrate it
# https://codeberg.org/slatian/service.echoip-slatecave
[template]
# Path to the template directory, can contain glob patterns
template_location = "templates"

View File

@ -59,7 +59,6 @@ pub struct IpResult {
location: Option<LocationResult>, location: Option<LocationResult>,
} }
struct ServiceSharedState { struct ServiceSharedState {
templating_engine: templating_engine::Engine, templating_engine: templating_engine::Engine,
dns_resolver: TokioAsyncResolver, dns_resolver: TokioAsyncResolver,
@ -79,6 +78,17 @@ struct CliArgs {
templates: Option<String>, templates: Option<String>,
} }
fn match_domain_hidden_list(domain: &String, hidden_list: &Vec<String>) -> bool {
let name = domain.trim_end_matches(".");
for suffix in hidden_list {
if name.ends_with(suffix) {
println!("Blocked {name}");
return true;
}
}
return false;
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
// Parse Command line arguments // Parse Command line arguments
@ -92,7 +102,8 @@ async fn main() {
match toml::from_str(&config_text) { match toml::from_str(&config_text) {
Ok(c) => c, Ok(c) => c,
Err(e) => { Err(e) => {
panic!("Unable to parse configuration file: {e}"); println!("Unable to parse configuration file:\n{e}");
::std::process::exit(1);
} }
} }
}, },
@ -139,7 +150,10 @@ async fn main() {
// Initalize DNS resolver with os defaults // Initalize DNS resolver with os defaults
println!("Initalizing dns resolver ..."); println!("Initalizing dns resolver ...");
let res = TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default());
println!("Using System configuration ...");
let res = TokioAsyncResolver::tokio_from_system_conf();
//let res = TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default());
let dns_resolver = match res { let dns_resolver = match res {
Ok(resolver) => resolver, Ok(resolver) => resolver,
Err(e) => { Err(e) => {
@ -257,13 +271,28 @@ async fn handle_ip_request(
arc_state: Arc<ServiceSharedState>, arc_state: Arc<ServiceSharedState>,
) -> Response { ) -> Response {
let address = ip_query.ip; let state = Arc::clone(&arc_state);
let result = get_ip_result(&ip_query, &state).await;
let format = ip_query.format.unwrap_or(ResponseFormat::TextHtml); let format = ip_query.format.unwrap_or(ResponseFormat::TextHtml);
let state = Arc::clone(&arc_state); state.templating_engine.render_view(
format,
View::Ip{query: ip_query, result: result}
).await
}
async fn get_ip_result(
ip_query: &IpQuery,
state: &ServiceSharedState,
) -> IpResult {
let address = ip_query.ip;
// do reverse lookup // do reverse lookup
let hostname = simple_dns::reverse_lookup(&state.dns_resolver, &address); let hostname = if state.config.dns.allow_reverse_lookup {
simple_dns::reverse_lookup(&state.dns_resolver, &address).await
} else {
None
};
// asn lookup // asn lookup
let asn_result = state.asn_db.query_asn_for_ip(address); let asn_result = state.asn_db.query_asn_for_ip(address);
@ -274,16 +303,23 @@ async fn handle_ip_request(
&vec![&ip_query.lang.as_ref().unwrap_or(&"en".to_string()), &"en".to_string()] &vec![&ip_query.lang.as_ref().unwrap_or(&"en".to_string()), &"en".to_string()]
); );
let result = IpResult{ // filter reverse lookup
hostname: hostname.await, let final_hostname = match hostname {
asn: asn_result, Some(name) => {
location: location_result, if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) {
None
} else {
Some(name.to_owned())
}
},
None => None,
}; };
state.templating_engine.render_view( IpResult{
format, hostname: final_hostname,
View::Ip{query: ip_query, result: result} asn: asn_result,
).await location: location_result,
}
} }
async fn handle_dig_route( async fn handle_dig_route(
@ -310,14 +346,25 @@ async fn handle_dig_request(
) -> Response { ) -> Response {
let state = Arc::clone(&arc_state); let state = Arc::clone(&arc_state);
let name = &dig_query.name;
let format = dig_query.format.unwrap_or(ResponseFormat::TextHtml); let format = dig_query.format.unwrap_or(ResponseFormat::TextHtml);
let dig_result = simple_dns::lookup(&state.dns_resolver, name, true).await; let dig_result = get_dig_result(&dig_query, &state).await;
state.templating_engine.render_view( state.templating_engine.render_view(
format, format,
View::Dig{ query: dig_query, result: dig_result} View::Dig{ query: dig_query, result: dig_result}
).await ).await
} }
async fn get_dig_result(
dig_query: &DigQuery,
state: &ServiceSharedState,
) -> simple_dns::DnsLookupResult {
let name = &dig_query.name.trim().trim_end_matches(".").to_string();
if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) {
Default::default()
} else {
simple_dns::lookup(&state.dns_resolver, name, true).await
}
}

View File

@ -12,7 +12,7 @@
<dl> <dl>
{% if r.hostname %} {% if r.hostname %}
<dh>Hostname</dh> <dh>Hostname</dh>
<dd><a href="/dig?name={{r.hostname}}">{{r.hostname}}</a></dd> <dd><a href="/dig?name={{r.hostname|trim_end_matches(pat=".")}}">{{r.hostname|trim_end_matches(pat=".")}}</a></dd>
{% endif %} {% endif %}
{% if r.asn %} {% if r.asn %}
<dh><abbr="Autonomous System Number">ASN</abbr></dh> <dh><abbr="Autonomous System Number">ASN</abbr></dh>