chore: replace homegrown public IP lookup with library

This commit is contained in:
Jan Christian Grünhage 2023-01-15 13:33:05 +01:00
parent 9a7fefc16c
commit 8b906b777a
Signed by: jcgruenhage
GPG Key ID: EEC1170CE56FA2ED
4 changed files with 378 additions and 70 deletions

365
Cargo.lock generated
View File

@ -124,7 +124,7 @@ dependencies = [
"cloudflare",
"env_logger",
"log",
"reqwest",
"public-ip",
"serde",
"serde_yaml",
"tokio",
@ -200,14 +200,38 @@ dependencies = [
"syn",
]
[[package]]
name = "darling"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
dependencies = [
"darling_core 0.10.2",
"darling_macro 0.10.2",
]
[[package]]
name = "darling"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa"
dependencies = [
"darling_core",
"darling_macro",
"darling_core 0.14.2",
"darling_macro 0.14.2",
]
[[package]]
name = "darling_core"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim 0.9.3",
"syn",
]
[[package]]
@ -220,7 +244,18 @@ dependencies = [
"ident_case",
"proc-macro2",
"quote",
"strsim",
"strsim 0.10.0",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
dependencies = [
"darling_core 0.10.2",
"quote",
"syn",
]
@ -230,11 +265,54 @@ version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e"
dependencies = [
"darling_core",
"darling_core 0.14.2",
"quote",
"syn",
]
[[package]]
name = "data-encoding"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"
[[package]]
name = "derive_builder"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
dependencies = [
"darling 0.10.2",
"derive_builder_core",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "derive_builder_core"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
dependencies = [
"darling 0.10.2",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "dns-lookup"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53ecafc952c4528d9b51a458d1a8904b81783feff9fde08ab6ed2545ff396872"
dependencies = [
"cfg-if",
"libc",
"socket2",
"winapi",
]
[[package]]
name = "encoding_rs"
version = "0.8.31"
@ -244,6 +322,24 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "endian-type"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
[[package]]
name = "enum-as-inner"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "env_logger"
version = "0.10.0"
@ -317,6 +413,21 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "futures"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.25"
@ -324,6 +435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@ -332,12 +444,34 @@ version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
[[package]]
name = "futures-executor"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
[[package]]
name = "futures-macro"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.25"
@ -356,8 +490,11 @@ version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
@ -401,6 +538,12 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.1.19"
@ -489,6 +632,20 @@ dependencies = [
"want",
]
[[package]]
name = "hyper-system-resolver"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6eea26c5d0b6ab9d72219f65000af310f042a740926f7b2fa3553e774036e2e7"
dependencies = [
"derive_builder",
"dns-lookup",
"hyper",
"tokio",
"tower-service",
"tracing",
]
[[package]]
name = "hyper-tls"
version = "0.5.0"
@ -532,6 +689,17 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "idna"
version = "0.3.0"
@ -641,6 +809,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "matches"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "memchr"
version = "2.5.0"
@ -683,6 +857,15 @@ dependencies = [
"tempfile",
]
[[package]]
name = "nibble_vec"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43"
dependencies = [
"smallvec",
]
[[package]]
name = "num-integer"
version = "0.1.45"
@ -769,6 +952,26 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "pin-project"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
@ -787,6 +990,12 @@ version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.49"
@ -796,6 +1005,27 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "public-ip"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4c40db5262d93298c363a299f8bc1b3a956a78eecddba3bc0e58b76e2f419a"
dependencies = [
"dns-lookup",
"futures-core",
"futures-util",
"http",
"hyper",
"hyper-system-resolver",
"pin-project-lite",
"thiserror",
"tokio",
"tracing",
"tracing-futures",
"trust-dns-client",
"trust-dns-proto",
]
[[package]]
name = "quote"
version = "1.0.23"
@ -805,6 +1035,46 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "radix_trie"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd"
dependencies = [
"endian-type",
"nibble_vec",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -1012,7 +1282,7 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3452b4c0f6c1e357f73fdb87cd1efabaa12acf328c7a528e252893baeb3f4aa"
dependencies = [
"darling",
"darling 0.14.2",
"proc-macro2",
"quote",
"syn",
@ -1040,6 +1310,12 @@ dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "socket2"
version = "0.4.7"
@ -1050,6 +1326,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "strsim"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]]
name = "strsim"
version = "0.10.0"
@ -1230,9 +1512,21 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [
"cfg-if",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.30"
@ -1242,6 +1536,63 @@ dependencies = [
"once_cell",
]
[[package]]
name = "tracing-futures"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
dependencies = [
"futures",
"futures-task",
"pin-project",
"tracing",
]
[[package]]
name = "trust-dns-client"
version = "0.20.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b4ef9b9bde0559b78a4abb00339143750085f05e5a453efb7b8bef1061f09dc"
dependencies = [
"cfg-if",
"data-encoding",
"futures-channel",
"futures-util",
"lazy_static",
"log",
"radix_trie",
"rand",
"thiserror",
"time 0.3.17",
"tokio",
"trust-dns-proto",
]
[[package]]
name = "trust-dns-proto"
version = "0.20.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31"
dependencies = [
"async-trait",
"cfg-if",
"data-encoding",
"enum-as-inner",
"futures-channel",
"futures-io",
"futures-util",
"idna 0.2.3",
"ipnet",
"lazy_static",
"log",
"rand",
"smallvec",
"thiserror",
"tinyvec",
"tokio",
"url",
]
[[package]]
name = "try-lock"
version = "0.2.3"
@ -1288,7 +1639,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
dependencies = [
"form_urlencoded",
"idna",
"idna 0.3.0",
"percent-encoding",
]

View File

@ -13,7 +13,6 @@ documentation = "https://git.jcg.re/jcgruenhage/cloudflare-ddns-service"
readme = "README.md"
[dependencies]
reqwest= { version = "0.11.13", features = ["blocking", "json"] }
serde = { version = "1.0.152", features = ["derive"] }
anyhow = "1.0.68"
env_logger = "0.10.0"
@ -22,3 +21,4 @@ tokio = { version = "1.24.1", features = ["time", "macros", "rt-multi-thread"] }
serde_yaml = "0.9.16"
#cloudflare = "0.10.1"
cloudflare = { git = "https://github.com/jcgruenhage/cloudflare-rs.git", branch = "make-owner-fields-optional" }
public-ip = "0.2.2"

View File

@ -12,7 +12,7 @@
mod network;
use anyhow::{Context, Result};
use network::{get_current_ipv4, get_current_ipv6, get_record, get_zone, update_record};
use network::{get_record, get_zone, update_record};
use serde::{Deserialize, Serialize};
use serde_yaml::{from_str, to_writer};
use std::{
@ -25,11 +25,8 @@ use tokio::time::interval;
use cloudflare::{
endpoints::dns::DnsContent,
framework::{
async_api::Client as CfClient, auth::Credentials, Environment, HttpApiClientConfig,
},
framework::{async_api::Client, auth::Credentials, Environment, HttpApiClientConfig},
};
use reqwest::Client as ReqwClient;
#[derive(Serialize, Deserialize)]
struct Config {
@ -68,8 +65,7 @@ async fn main() -> Result<()> {
};
let mut interval = interval(Duration::new(config.interval, 0));
let mut reqw_client = ReqwClient::new();
let mut cf_client = CfClient::new(
let mut client = Client::new(
Credentials::UserAuthToken {
token: config.api_token.clone(),
},
@ -77,20 +73,11 @@ async fn main() -> Result<()> {
Environment::Production,
)
.context("Failed to initiate cloudflare API client")?;
let zone = get_zone(config.zone.clone(), &mut cf_client)
let zone = get_zone(config.zone.clone(), &mut client)
.await
.context("Failed to get zone")?;
loop {
if let Err(error) = update(
&config,
&mut cache,
&cache_path,
&zone,
&mut reqw_client,
&mut cf_client,
)
.await
{
if let Err(error) = update(&config, &mut cache, &cache_path, &zone, &mut client).await {
log::error!("Failed to update record: {}", error);
}
interval.tick().await;
@ -102,11 +89,10 @@ async fn update(
cache: &mut Cache,
cache_path: &PathBuf,
zone: &str,
reqw_client: &mut ReqwClient,
cf_client: &mut CfClient,
client: &mut Client,
) -> Result<()> {
if config.ipv4 {
let current = get_current_ipv4(reqw_client)
let current = public_ip::addr_v4()
.await
.context("Failed to query current IPv4 address")?;
log::debug!("fetched current IP: {}", current.to_string());
@ -116,7 +102,7 @@ async fn update(
}
_ => {
log::info!("ipv4 changed, setting record");
let rid = get_record(zone, config.domain.clone(), network::A_RECORD, cf_client)
let rid = get_record(zone, config.domain.clone(), network::A_RECORD, client)
.await
.context("couldn't find record!")?;
log::debug!("got record ID {}", rid);
@ -125,7 +111,7 @@ async fn update(
&rid,
&config.domain,
DnsContent::A { content: current },
cf_client,
client,
)
.await
.context("Failed to set DNS record")?;
@ -136,7 +122,7 @@ async fn update(
}
}
if config.ipv6 {
let current = get_current_ipv6(reqw_client)
let current = public_ip::addr_v6()
.await
.context("Failed to query current IPv4 address")?;
log::debug!("fetched current IP: {}", current.to_string());
@ -146,7 +132,7 @@ async fn update(
}
_ => {
log::info!("ipv6 changed, setting record");
let rid = get_record(zone, config.domain.clone(), network::AAAA_RECORD, cf_client)
let rid = get_record(zone, config.domain.clone(), network::AAAA_RECORD, client)
.await
.context("couldn't find record!")?;
log::debug!("got record ID {}", rid);
@ -155,7 +141,7 @@ async fn update(
&rid,
&config.domain,
DnsContent::AAAA { content: current },
cf_client,
client,
)
.await
.context("Failed to set DNS record")?;

View File

@ -20,9 +20,8 @@ use cloudflare::{
},
zone::{ListZones, ListZonesParams},
},
framework::async_api::Client as CfClient,
framework::async_api::Client,
};
use reqwest::Client as ReqwClient;
pub const A_RECORD: DnsContent = DnsContent::A {
content: Ipv4Addr::UNSPECIFIED,
@ -31,36 +30,8 @@ pub const AAAA_RECORD: DnsContent = DnsContent::AAAA {
content: Ipv6Addr::UNSPECIFIED,
};
pub async fn get_current_ipv4(client: &mut ReqwClient) -> Result<Ipv4Addr> {
client
.get("https://ipv4.icanhazip.com")
.send()
.await
.context("Failed to query current IPv4 from ipv4.icanhazip.com")?
.text()
.await
.context("Failed to read text body")?
.trim()
.parse()
.context("Failed to parse IPv4 address returned by ipv4.icanhazip.com")
}
pub async fn get_current_ipv6(client: &mut ReqwClient) -> Result<Ipv6Addr> {
client
.get("https://ipv6.icanhazip.com")
.send()
.await
.context("Failed to query current IPv6 from ipv6.icanhazip.com")?
.text()
.await
.context("Failed to read text body")?
.trim()
.parse()
.context("Failed to parse IPv6 address returned by ipv6.icanhazip.com")
}
pub async fn get_zone(domain: String, cf_client: &mut CfClient) -> Result<String> {
Ok(cf_client
pub async fn get_zone(domain: String, client: &mut Client) -> Result<String> {
Ok(client
.request_handle(&ListZones {
params: ListZonesParams {
name: Some(domain),
@ -83,9 +54,9 @@ pub async fn get_record(
zone_identifier: &str,
domain: String,
r#type: DnsContent,
cf_client: &mut CfClient,
client: &mut Client,
) -> Result<String> {
Ok(cf_client
Ok(client
.request_handle(&ListDnsRecords {
zone_identifier,
params: ListDnsRecordsParams {
@ -113,9 +84,9 @@ pub async fn update_record(
identifier: &str,
name: &str,
content: DnsContent,
cf_client: &mut CfClient,
client: &mut Client,
) -> Result<()> {
cf_client
client
.request_handle(&UpdateDnsRecord {
zone_identifier,
identifier,