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>,
}
struct ServiceSharedState {
templating_engine: templating_engine::Engine,
dns_resolver: TokioAsyncResolver,
@ -79,6 +78,17 @@ struct CliArgs {
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]
async fn main() {
// Parse Command line arguments
@ -92,7 +102,8 @@ async fn main() {
match toml::from_str(&config_text) {
Ok(c) => c,
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
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 {
Ok(resolver) => resolver,
Err(e) => {
@ -257,13 +271,28 @@ async fn handle_ip_request(
arc_state: Arc<ServiceSharedState>,
) -> 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 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
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
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()]
);
let result = IpResult{
hostname: hostname.await,
asn: asn_result,
location: location_result,
// filter reverse lookup
let final_hostname = match hostname {
Some(name) => {
if match_domain_hidden_list(&name, &state.config.dns.hidden_suffixes) {
None
} else {
Some(name.to_owned())
}
},
None => None,
};
state.templating_engine.render_view(
format,
View::Ip{query: ip_query, result: result}
).await
IpResult{
hostname: final_hostname,
asn: asn_result,
location: location_result,
}
}
async fn handle_dig_route(
@ -310,14 +346,25 @@ async fn handle_dig_request(
) -> Response {
let state = Arc::clone(&arc_state);
let name = &dig_query.name;
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(
format,
View::Dig{ query: dig_query, result: dig_result}
).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>
{% if r.hostname %}
<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 %}
{% if r.asn %}
<dh><abbr="Autonomous System Number">ASN</abbr></dh>