add IP and AS informations
This commit is contained in:
parent
0fcc49cf26
commit
376a34ddd5
|
@ -59,6 +59,19 @@ version = "1.7.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
||||
|
||||
[[package]]
|
||||
name = "asn-db2"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06cdaeaa434cbef439220bb84896ce0fd36b4452f0325f0a8e5cd21a08d98901"
|
||||
dependencies = [
|
||||
"csv",
|
||||
"ipnet",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.5"
|
||||
|
@ -307,6 +320,27 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
|
||||
dependencies = [
|
||||
"csv-core",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv-core"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
|
@ -408,6 +442,18 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dns-lookup"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5766087c2235fec47fafa4cfecc81e494ee679d0fd4a59887ea0919bfb0e4fc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"socket2",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.11.0"
|
||||
|
@ -1872,7 +1918,9 @@ dependencies = [
|
|||
name = "services"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"asn-db2",
|
||||
"diesel",
|
||||
"dns-lookup",
|
||||
"fluent-templates",
|
||||
"reqwest",
|
||||
"rocket",
|
||||
|
|
|
@ -8,6 +8,8 @@ name = "updater"
|
|||
path = "src/updater.rs"
|
||||
|
||||
[dependencies]
|
||||
asn-db2 = { version = "0.2", default-features = false }
|
||||
dns-lookup = { version = "2.0", default-features = false }
|
||||
rocket = { version = "0.5", default-features = false }
|
||||
rocket-accept-language = { version = "0.8", default-features = false }
|
||||
serde = { version = "1.0", default-features = false }
|
||||
|
|
|
@ -19,5 +19,12 @@ table-ipv6 = { -ipv6 }
|
|||
table-ipv4 = { -ipv4 }
|
||||
table-ipv6-availability = { -ipv6 } availability
|
||||
table-ipv4-availability = { -ipv4 } availability
|
||||
table-asn = IP info
|
||||
|
||||
dl-ipinfo =
|
||||
.subnet = Subnet
|
||||
.asn = <abbr title="Autonomous System Number">ASN</title>
|
||||
.as-owner = <abbr title="Autonomous System">AS</title> owner
|
||||
.country = Country
|
||||
|
||||
field-url = Service URL
|
||||
|
|
|
@ -17,7 +17,14 @@ table-server = Serveur
|
|||
table-time = Moment
|
||||
table-ipv6 = { -ipv6 }
|
||||
table-ipv4 = { -ipv4 }
|
||||
table-ipv6-availability = Disponibilité { -ipv6 }
|
||||
table-ipv4-availability = Disponibilité { -ipv4 }
|
||||
table-ipv6-availability = Dispo { -ipv6 }
|
||||
table-ipv4-availability = Dispo { -ipv4 }
|
||||
table-asn = Infos IP
|
||||
|
||||
dl-ipinfo =
|
||||
.subnet = Sous-réseau
|
||||
.asn = <abbr title="Autonomous System Number" lang="en">ASN</title>
|
||||
.as-owner = Propriétaire de l'<abbr title="Autonomous System" lang="en">AS</title>
|
||||
.country = Pays
|
||||
|
||||
field-url = URL du service
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE "services" DROP "address_ipv6";
|
||||
ALTER TABLE "services" DROP "address_ipv4";
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE "services" ADD COLUMN "address_ipv6" TEXT NOT NULL DEFAULT "";
|
||||
ALTER TABLE "services" ADD COLUMN "address_ipv4" TEXT NOT NULL DEFAULT "";
|
|
@ -81,6 +81,8 @@ pub async fn check(url: &str, ipv: Option<u8>) -> Result<Services, String> {
|
|||
ipv4: "".to_string(),
|
||||
availability_ipv6: "".to_string(),
|
||||
availability_ipv4: "".to_string(),
|
||||
address_ipv6: "".to_string(),
|
||||
address_ipv4: "".to_string(),
|
||||
})
|
||||
}
|
||||
Err(e) => Err(e.to_string()),
|
||||
|
|
99
src/main.rs
99
src/main.rs
|
@ -7,6 +7,7 @@ use services::{establish_connection, models::*, Software, DATABASE_URL};
|
|||
|
||||
use std::fs::File;
|
||||
|
||||
use asn_db2::{Ipv4Database, Ipv6Database};
|
||||
use diesel::prelude::*;
|
||||
use fluent_templates::FluentLoader;
|
||||
use rocket::{
|
||||
|
@ -18,7 +19,9 @@ use rocket::{
|
|||
Request, Response, State,
|
||||
};
|
||||
use rocket_accept_language::{language, AcceptLanguage, LanguageIdentifier};
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
use std::io::BufReader;
|
||||
use tera::{Context, Tera, Value};
|
||||
use unic_langid::{langid, subtags::Language};
|
||||
|
||||
|
@ -67,13 +70,30 @@ fn rocket() -> _ {
|
|||
let mut tera = Tera::new("templates/*.html.tera").unwrap();
|
||||
tera.register_function("fluent", FluentLoader::new(&*LOCALES));
|
||||
|
||||
let db6 = Ipv6Database::from_reader(BufReader::new(
|
||||
File::open("ip2asn-v6.tsv").expect("unable to open ip2asn-v6.tsv"),
|
||||
))
|
||||
.unwrap();
|
||||
let db4 = Ipv4Database::from_reader(BufReader::new(
|
||||
File::open("ip2asn-v4.tsv").expect("unable to open ip2asn-v4.tsv"),
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
rocket::build()
|
||||
.manage(tera)
|
||||
.manage(db6)
|
||||
.manage(db4)
|
||||
.attach(Shield::new().enable(Referrer::NoReferrer))
|
||||
.attach(HttpHeaders)
|
||||
.mount(
|
||||
"/",
|
||||
routes![list_services, list_scans, add_service_get, add_service_post, dl],
|
||||
routes![
|
||||
list_services,
|
||||
list_scans,
|
||||
add_service_get,
|
||||
add_service_post,
|
||||
dl
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -82,9 +102,30 @@ fn dl() -> File {
|
|||
File::open(DATABASE_URL).unwrap()
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct IpInfo {
|
||||
ip: String,
|
||||
subnet: String,
|
||||
asn: String,
|
||||
country: String,
|
||||
as_owner: String,
|
||||
}
|
||||
#[derive(Serialize, Debug)]
|
||||
struct TemplateServices {
|
||||
url: String,
|
||||
software: String,
|
||||
server: String,
|
||||
ipv6: String,
|
||||
ipv4: String,
|
||||
availability_ipv6: String,
|
||||
availability_ipv4: String,
|
||||
ip_info: Vec<IpInfo>,
|
||||
}
|
||||
#[get("/?<software>")]
|
||||
fn list_services(
|
||||
tera: &State<Tera>,
|
||||
db6: &State<Ipv6Database>,
|
||||
db4: &State<Ipv4Database>,
|
||||
al: &AcceptLanguage,
|
||||
software: Option<Strict<Software>>,
|
||||
) -> RawHtml<String> {
|
||||
|
@ -93,6 +134,55 @@ fn list_services(
|
|||
request =
|
||||
request.filter(services::schema::services::software.eq(s.to_string().to_lowercase()));
|
||||
}
|
||||
let services = request
|
||||
.limit(300)
|
||||
.select(Services::as_select())
|
||||
.load(&mut establish_connection())
|
||||
.unwrap();
|
||||
|
||||
let mut templates: Vec<TemplateServices> = vec![];
|
||||
for service in &services {
|
||||
let mut ip_info = vec![];
|
||||
service
|
||||
.address_ipv6
|
||||
.split(',')
|
||||
.filter(|ip| !ip.is_empty())
|
||||
.for_each(|ip| {
|
||||
let info = db6.lookup(ip.parse().unwrap()).unwrap();
|
||||
ip_info.push(IpInfo {
|
||||
ip: ip.to_string(),
|
||||
subnet: info.subnet.to_string(),
|
||||
asn: info.as_number.to_string(),
|
||||
country: info.country.to_string(),
|
||||
as_owner: info.owner.to_string(),
|
||||
})
|
||||
});
|
||||
service
|
||||
.address_ipv4
|
||||
.split(',')
|
||||
.filter(|ip| !ip.is_empty())
|
||||
.for_each(|ip| {
|
||||
let info = db4.lookup(ip.parse().unwrap()).unwrap();
|
||||
ip_info.push(IpInfo {
|
||||
ip: ip.to_string(),
|
||||
subnet: info.subnet.to_string(),
|
||||
asn: info.as_number.to_string(),
|
||||
country: info.country.to_string(),
|
||||
as_owner: info.owner.to_string(),
|
||||
})
|
||||
});
|
||||
|
||||
templates.push(TemplateServices {
|
||||
url: service.url.to_string(),
|
||||
software: service.software.to_string(),
|
||||
server: service.server.to_string(),
|
||||
ipv6: service.ipv6.to_string(),
|
||||
ipv4: service.ipv4.to_string(),
|
||||
availability_ipv6: service.availability_ipv6.to_string(),
|
||||
availability_ipv4: service.availability_ipv4.to_string(),
|
||||
ip_info,
|
||||
})
|
||||
}
|
||||
|
||||
RawHtml(
|
||||
tera.render(
|
||||
|
@ -100,10 +190,7 @@ fn list_services(
|
|||
&gen_context(
|
||||
al,
|
||||
json!({
|
||||
"services": &request.limit(300)
|
||||
.select(Services::as_select())
|
||||
.load(&mut establish_connection())
|
||||
.unwrap(),
|
||||
"services": &templates,
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
@ -193,6 +280,8 @@ async fn add_service_post(
|
|||
ipv4: "".to_string(),
|
||||
availability_ipv6: "".to_string(),
|
||||
availability_ipv4: "".to_string(),
|
||||
address_ipv6: "".to_string(),
|
||||
address_ipv4: "".to_string(),
|
||||
})
|
||||
.execute(&mut establish_connection())
|
||||
.unwrap();
|
||||
|
|
|
@ -12,6 +12,8 @@ pub struct Services {
|
|||
pub ipv4: String,
|
||||
pub availability_ipv6: String,
|
||||
pub availability_ipv4: String,
|
||||
pub address_ipv6: String,
|
||||
pub address_ipv4: String,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Insertable, Serialize, Debug)]
|
||||
|
|
|
@ -19,6 +19,8 @@ diesel::table! {
|
|||
ipv4 -> Text,
|
||||
availability_ipv6 -> Text,
|
||||
availability_ipv4 -> Text,
|
||||
address_ipv6 -> Text,
|
||||
address_ipv4 -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ use diesel::ExpressionMethods;
|
|||
use diesel::QueryDsl;
|
||||
use diesel::RunQueryDsl;
|
||||
use diesel::SelectableHelper;
|
||||
use dns_lookup::lookup_host;
|
||||
use std::net::IpAddr;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
@ -65,8 +67,24 @@ async fn main() {
|
|||
|
||||
let scans_nb = installation_scans.len();
|
||||
|
||||
let ips: Vec<std::net::IpAddr> =
|
||||
match lookup_host(reqwest::Url::parse(&service.url).unwrap().domain().unwrap()) {
|
||||
Ok(i) => i,
|
||||
Err(_) => vec![],
|
||||
};
|
||||
|
||||
let service_new = check(&service.url, None).await.unwrap_or(service);
|
||||
|
||||
let mut addr_ipv6 = vec![];
|
||||
let mut addr_ipv4 = vec![];
|
||||
|
||||
for ip in ips {
|
||||
match ip {
|
||||
IpAddr::V6(ip) => addr_ipv6.push(ip.to_string()),
|
||||
IpAddr::V4(ip) => addr_ipv4.push(ip.to_string()),
|
||||
};
|
||||
}
|
||||
|
||||
diesel::update(services.find(&service_new.url))
|
||||
.set((
|
||||
url.eq(&service_new.url),
|
||||
|
@ -78,6 +96,8 @@ async fn main() {
|
|||
.eq(((ipv6_successes as f32 / scans_nb as f32 * 100.0) as u8).to_string()),
|
||||
availability_ipv4
|
||||
.eq(((ipv4_successes as f32 / scans_nb as f32 * 100.0) as u8).to_string()),
|
||||
address_ipv6.eq(&addr_ipv6.join(",")),
|
||||
address_ipv4.eq(&addr_ipv4.join(",")),
|
||||
))
|
||||
.execute(connection)
|
||||
.unwrap();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<th>{{ fluent(key="table-ipv4", lang=ln) }}</th>
|
||||
<th>{{ fluent(key="table-ipv6-availability", lang=ln) }}</th>
|
||||
<th>{{ fluent(key="table-ipv4-availability", lang=ln) }}</th>
|
||||
<th>{{ fluent(key="table-asn", lang=ln) }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -28,6 +29,19 @@
|
|||
<td>{% if service.ipv4 == "ok" %}✓{% else %}—{% endif %}</td>
|
||||
<td>{% if service.ipv6 == "" %}—{% else %}{{ service.availability_ipv6 }} %{% endif %}</td>
|
||||
<td>{% if service.ipv4 == "" %}—{% else %}{{ service.availability_ipv4 }} %{% endif %}</td>
|
||||
<td>
|
||||
{% for ip_info in service.ip_info %}
|
||||
<details>
|
||||
<summary>{{ ip_info.ip }}</summary>
|
||||
<dl>
|
||||
<dt>{{ fluent(key="dl-ipinfo.subnet", lang=ln) }}</dt><dd>{{ ip_info.subnet }}<dd>
|
||||
<dt>{{ fluent(key="dl-ipinfo.asn", lang=ln) }}</dt><dd>{{ ip_info.asn }}</dd>
|
||||
<dt>{{ fluent(key="dl-ipinfo.as-owner", lang=ln) }}</dt><dd>{{ ip_info.as_owner }}<dd>
|
||||
<dt>{{ fluent(key="dl-ipinfo.country", lang=ln) }}</dt><dd>{{ ip_info.country }}<dd>
|
||||
</dl>
|
||||
</details>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
|
Loading…
Reference in New Issue