mirror of
https://github.com/timothymiller/cloudflare-ddns.git
synced 2026-03-24 07:58:56 -03:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2913ce379c |
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -139,7 +139,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloudflare-ddns"
|
name = "cloudflare-ddns"
|
||||||
version = "2.0.9"
|
version = "2.0.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"idna",
|
"idna",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cloudflare-ddns"
|
name = "cloudflare-ddns"
|
||||||
version = "2.0.9"
|
version = "2.0.10"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Access your home network remotely via a custom domain name without a static IP"
|
description = "Access your home network remotely via a custom domain name without a static IP"
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ This project handles **Cloudflare API tokens** that grant DNS editing privileges
|
|||||||
|
|
||||||
- The Docker image runs as a **static binary from scratch** with zero runtime dependencies, which minimizes the attack surface.
|
- The Docker image runs as a **static binary from scratch** with zero runtime dependencies, which minimizes the attack surface.
|
||||||
- Use `security_opt: no-new-privileges:true` in Docker Compose deployments.
|
- Use `security_opt: no-new-privileges:true` in Docker Compose deployments.
|
||||||
- Pin image tags to a specific version (e.g., `timothyjmiller/cloudflare-ddns:v2.0.9`) rather than using `latest` in production.
|
- Pin image tags to a specific version (e.g., `timothyjmiller/cloudflare-ddns:v2.0.10`) rather than using `latest` in production.
|
||||||
|
|
||||||
### Network Security
|
### Network Security
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ pub async fn update_once(
|
|||||||
let mut notify = false; // NEW: track meaningful events
|
let mut notify = false; // NEW: track meaningful events
|
||||||
|
|
||||||
if config.legacy_mode {
|
if config.legacy_mode {
|
||||||
all_ok = update_legacy(config, cf_cache, ppfmt, noop_reported, detection_client).await;
|
let (ok, legacy_msgs, legacy_notify) =
|
||||||
|
update_legacy(config, cf_cache, ppfmt, noop_reported, detection_client).await;
|
||||||
|
all_ok = ok;
|
||||||
|
messages = legacy_msgs;
|
||||||
|
notify = legacy_notify;
|
||||||
} else {
|
} else {
|
||||||
// Detect IPs for each provider
|
// Detect IPs for each provider
|
||||||
let mut detected_ips: HashMap<IpType, Vec<IpAddr>> = HashMap::new();
|
let mut detected_ips: HashMap<IpType, Vec<IpAddr>> = HashMap::new();
|
||||||
@@ -251,10 +255,10 @@ async fn update_legacy(
|
|||||||
ppfmt: &PP,
|
ppfmt: &PP,
|
||||||
noop_reported: &mut HashSet<String>,
|
noop_reported: &mut HashSet<String>,
|
||||||
detection_client: &Client,
|
detection_client: &Client,
|
||||||
) -> bool {
|
) -> (bool, Vec<Message>, bool) {
|
||||||
let legacy = match &config.legacy_config {
|
let legacy = match &config.legacy_config {
|
||||||
Some(l) => l,
|
Some(l) => l,
|
||||||
None => return false,
|
None => return (false, Vec::new(), false),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ddns = LegacyDdnsClient {
|
let ddns = LegacyDdnsClient {
|
||||||
@@ -341,16 +345,17 @@ async fn update_legacy(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ddns.update_ips(
|
let (msgs, should_notify) = ddns
|
||||||
&ips,
|
.update_ips(
|
||||||
&legacy.cloudflare,
|
&ips,
|
||||||
legacy.ttl,
|
&legacy.cloudflare,
|
||||||
legacy.purge_unknown_records,
|
legacy.ttl,
|
||||||
noop_reported,
|
legacy.purge_unknown_records,
|
||||||
)
|
noop_reported,
|
||||||
.await;
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
true
|
(true, msgs, should_notify)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete records on stop (for env var mode).
|
/// Delete records on stop (for env var mode).
|
||||||
@@ -499,11 +504,19 @@ impl LegacyDdnsClient {
|
|||||||
ttl: i64,
|
ttl: i64,
|
||||||
purge_unknown_records: bool,
|
purge_unknown_records: bool,
|
||||||
noop_reported: &mut HashSet<String>,
|
noop_reported: &mut HashSet<String>,
|
||||||
) {
|
) -> (Vec<Message>, bool) {
|
||||||
|
let mut messages = Vec::new();
|
||||||
|
let mut notify = false;
|
||||||
for ip in ips.values() {
|
for ip in ips.values() {
|
||||||
self.commit_record(ip, config, ttl, purge_unknown_records, noop_reported)
|
let (msgs, changed) = self
|
||||||
|
.commit_record(ip, config, ttl, purge_unknown_records, noop_reported)
|
||||||
.await;
|
.await;
|
||||||
|
messages.extend(msgs);
|
||||||
|
if changed {
|
||||||
|
notify = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
(messages, notify)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn commit_record(
|
async fn commit_record(
|
||||||
@@ -513,7 +526,9 @@ impl LegacyDdnsClient {
|
|||||||
ttl: i64,
|
ttl: i64,
|
||||||
purge_unknown_records: bool,
|
purge_unknown_records: bool,
|
||||||
noop_reported: &mut HashSet<String>,
|
noop_reported: &mut HashSet<String>,
|
||||||
) {
|
) -> (Vec<Message>, bool) {
|
||||||
|
let mut messages = Vec::new();
|
||||||
|
let mut changed = false;
|
||||||
for entry in config {
|
for entry in config {
|
||||||
let zone_resp: Option<LegacyCfResponse<LegacyZoneResult>> = self
|
let zone_resp: Option<LegacyCfResponse<LegacyZoneResult>> = self
|
||||||
.cf_api(
|
.cf_api(
|
||||||
@@ -592,6 +607,7 @@ impl LegacyDdnsClient {
|
|||||||
if let Some(ref id) = identifier {
|
if let Some(ref id) = identifier {
|
||||||
if modified {
|
if modified {
|
||||||
noop_reported.remove(&noop_key);
|
noop_reported.remove(&noop_key);
|
||||||
|
changed = true;
|
||||||
if self.dry_run {
|
if self.dry_run {
|
||||||
println!("[DRY RUN] Would update record {fqdn} -> {}", ip.ip);
|
println!("[DRY RUN] Would update record {fqdn} -> {}", ip.ip);
|
||||||
} else {
|
} else {
|
||||||
@@ -602,6 +618,10 @@ impl LegacyDdnsClient {
|
|||||||
.cf_api(&update_endpoint, "PUT", entry, Some(&record))
|
.cf_api(&update_endpoint, "PUT", entry, Some(&record))
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
messages.push(Message::new_ok(&format!(
|
||||||
|
"Updated {fqdn} -> {}",
|
||||||
|
ip.ip
|
||||||
|
)));
|
||||||
} else if noop_reported.insert(noop_key) {
|
} else if noop_reported.insert(noop_key) {
|
||||||
if self.dry_run {
|
if self.dry_run {
|
||||||
println!("[DRY RUN] Record {fqdn} is up to date");
|
println!("[DRY RUN] Record {fqdn} is up to date");
|
||||||
@@ -611,6 +631,7 @@ impl LegacyDdnsClient {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
noop_reported.remove(&noop_key);
|
noop_reported.remove(&noop_key);
|
||||||
|
changed = true;
|
||||||
if self.dry_run {
|
if self.dry_run {
|
||||||
println!("[DRY RUN] Would add new record {fqdn} -> {}", ip.ip);
|
println!("[DRY RUN] Would add new record {fqdn} -> {}", ip.ip);
|
||||||
} else {
|
} else {
|
||||||
@@ -620,6 +641,10 @@ impl LegacyDdnsClient {
|
|||||||
.cf_api(&create_endpoint, "POST", entry, Some(&record))
|
.cf_api(&create_endpoint, "POST", entry, Some(&record))
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
messages.push(Message::new_ok(&format!(
|
||||||
|
"Created {fqdn} -> {}",
|
||||||
|
ip.ip
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if purge_unknown_records {
|
if purge_unknown_records {
|
||||||
@@ -638,6 +663,7 @@ impl LegacyDdnsClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(messages, changed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user