blob: b4e114ea47d155c75706d2ae1105c116960ef0a9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
use hyper::{Client, Uri};
use once_cell::sync::Lazy;
use serde::de::DeserializeOwned;
use tokio_rustls::rustls::ClientConfig;
use crate::{AmIMullvad, Error};
const LE_ROOT_CERT: &[u8] = include_bytes!("../../../mullvad-api/le_root_cert.pem");
static CLIENT_CONFIG: Lazy<ClientConfig> = Lazy::new(|| {
ClientConfig::builder()
.with_safe_default_cipher_suites()
.with_safe_default_kx_groups()
.with_safe_default_protocol_versions()
.unwrap()
.with_root_certificates(read_cert_store())
.with_no_client_auth()
});
pub async fn geoip_lookup(mullvad_host: String) -> Result<AmIMullvad, Error> {
let uri = Uri::try_from(format!("https://ipv4.am.i.{mullvad_host}/json"))
.map_err(|_| Error::InvalidUrl)?;
http_get(uri).await
}
pub async fn http_get<T: DeserializeOwned>(url: Uri) -> Result<T, Error> {
log::debug!("GET {url}");
let https = hyper_rustls::HttpsConnectorBuilder::new()
.with_tls_config(CLIENT_CONFIG.clone())
.https_only()
.enable_http1()
.build();
let client: Client<_, hyper::Body> = Client::builder().build(https);
let body = client
.get(url)
.await
.map_err(|error| Error::HttpRequest(error.to_string()))?
.into_body();
// TODO: limit length
let bytes = hyper::body::to_bytes(body).await.map_err(|error| {
log::error!("Failed to convert body to bytes buffer: {}", error);
Error::DeserializeBody
})?;
serde_json::from_slice(&bytes).map_err(|error| {
log::error!("Failed to deserialize response: {}", error);
Error::DeserializeBody
})
}
fn read_cert_store() -> tokio_rustls::rustls::RootCertStore {
let mut cert_store = tokio_rustls::rustls::RootCertStore::empty();
let certs = rustls_pemfile::certs(&mut std::io::BufReader::new(LE_ROOT_CERT))
.expect("Failed to parse pem file");
let (num_certs_added, num_failures) = cert_store.add_parsable_certificates(&certs);
if num_failures > 0 || num_certs_added != 1 {
panic!("Failed to add root cert");
}
cert_store
}
|