mirror of
https://github.com/timothymiller/cloudflare-ddns.git
synced 2026-03-21 22:48:57 -03:00
Filter Cloudflare IPs in legacy mode
Add support for REJECT_CLOUDFLARE_IPS in legacy config and fetch Cloudflare IP ranges to drop matching detected addresses. Improve IP detection in legacy mode by using literal-IP primary trace URLs with hostname fallbacks, binding dedicated IPv4/IPv6 HTTP clients, and setting a Host override for literal-IP trace endpoints so TLS SNI works. Expose build_split_client and update tests accordingly.
This commit is contained in:
26
README.md
26
README.md
@@ -369,6 +369,32 @@ Some ISP provided modems only allow port forwarding over IPv4 or IPv6. Disable t
|
|||||||
| `purgeUnknownRecords` | bool | `false` | Delete stale/duplicate DNS records |
|
| `purgeUnknownRecords` | bool | `false` | Delete stale/duplicate DNS records |
|
||||||
| `ttl` | int | `300` | DNS record TTL in seconds (30-86400, values < 30 become auto) |
|
| `ttl` | int | `300` | DNS record TTL in seconds (30-86400, values < 30 become auto) |
|
||||||
|
|
||||||
|
### 🚫 Cloudflare IP Rejection (Legacy Mode)
|
||||||
|
|
||||||
|
The `REJECT_CLOUDFLARE_IPS` environment variable is supported in legacy config mode. Set it alongside your `config.json`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
REJECT_CLOUDFLARE_IPS=true cloudflare-ddns
|
||||||
|
```
|
||||||
|
|
||||||
|
Or in Docker Compose:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
environment:
|
||||||
|
- REJECT_CLOUDFLARE_IPS=true
|
||||||
|
volumes:
|
||||||
|
- ./config.json:/config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🔍 IP Detection (Legacy Mode)
|
||||||
|
|
||||||
|
Legacy mode uses [Cloudflare's `/cdn-cgi/trace`](https://www.cloudflare.com/cdn-cgi/trace) endpoint for IP detection. To ensure the correct address family is detected on dual-stack hosts:
|
||||||
|
|
||||||
|
- **Primary:** Literal IP URLs (`1.0.0.1` for IPv4, `[2606:4700:4700::1001]` for IPv6) — guarantees the connection uses the correct address family
|
||||||
|
- **Fallback:** Hostname URL (`api.cloudflare.com`) — works when literal IPs are intercepted (e.g. Cloudflare WARP or Zero Trust)
|
||||||
|
|
||||||
|
Each address family uses a dedicated HTTP client bound to the correct local address (`0.0.0.0` for IPv4, `[::]` for IPv6), preventing the wrong address type from being returned on dual-stack networks.
|
||||||
|
|
||||||
Each zone entry contains:
|
Each zone entry contains:
|
||||||
|
|
||||||
| Key | Type | Description |
|
| Key | Type | Description |
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ fn legacy_to_app_config(legacy: LegacyConfig, dry_run: bool, repeat: bool) -> Ap
|
|||||||
managed_waf_comment_regex: None,
|
managed_waf_comment_regex: None,
|
||||||
detection_timeout: Duration::from_secs(5),
|
detection_timeout: Duration::from_secs(5),
|
||||||
update_timeout: Duration::from_secs(30),
|
update_timeout: Duration::from_secs(30),
|
||||||
reject_cloudflare_ips: false,
|
reject_cloudflare_ips: getenv_bool("REJECT_CLOUDFLARE_IPS", false),
|
||||||
dry_run,
|
dry_run,
|
||||||
emoji: false,
|
emoji: false,
|
||||||
quiet: false,
|
quiet: false,
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ async fn fetch_trace_ip(
|
|||||||
/// Build an HTTP client that only connects via the given IP family.
|
/// Build an HTTP client that only connects via the given IP family.
|
||||||
/// Binding to 0.0.0.0 forces IPv4-only; binding to [::] forces IPv6-only.
|
/// Binding to 0.0.0.0 forces IPv4-only; binding to [::] forces IPv6-only.
|
||||||
/// This ensures the trace endpoint sees the correct address family.
|
/// This ensures the trace endpoint sees the correct address family.
|
||||||
fn build_split_client(ip_type: IpType, timeout: Duration) -> Client {
|
pub fn build_split_client(ip_type: IpType, timeout: Duration) -> Client {
|
||||||
let local_addr: IpAddr = match ip_type {
|
let local_addr: IpAddr = match ip_type {
|
||||||
IpType::V4 => Ipv4Addr::UNSPECIFIED.into(),
|
IpType::V4 => Ipv4Addr::UNSPECIFIED.into(),
|
||||||
IpType::V6 => Ipv6Addr::UNSPECIFIED.into(),
|
IpType::V6 => Ipv6Addr::UNSPECIFIED.into(),
|
||||||
|
|||||||
105
src/updater.rs
105
src/updater.rs
@@ -229,7 +229,7 @@ pub async fn update_once(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Run legacy mode update (using the original cloudflare-ddns logic with zone_id-based config).
|
/// Run legacy mode update (using the original cloudflare-ddns logic with zone_id-based config).
|
||||||
async fn update_legacy(config: &AppConfig, _ppfmt: &PP) -> bool {
|
async fn update_legacy(config: &AppConfig, ppfmt: &PP) -> 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,
|
||||||
@@ -243,20 +243,23 @@ async fn update_legacy(config: &AppConfig, _ppfmt: &PP) -> bool {
|
|||||||
let ddns = LegacyDdnsClient {
|
let ddns = LegacyDdnsClient {
|
||||||
client,
|
client,
|
||||||
cf_api_base: "https://api.cloudflare.com/client/v4".to_string(),
|
cf_api_base: "https://api.cloudflare.com/client/v4".to_string(),
|
||||||
|
// Literal IPs primary (guarantees correct address family on dual-stack hosts),
|
||||||
|
// hostname fallback (works when literal IPs are intercepted by WARP/Zero Trust).
|
||||||
ipv4_urls: vec![
|
ipv4_urls: vec![
|
||||||
"https://api.cloudflare.com/cdn-cgi/trace".to_string(),
|
|
||||||
"https://1.0.0.1/cdn-cgi/trace".to_string(),
|
"https://1.0.0.1/cdn-cgi/trace".to_string(),
|
||||||
|
"https://api.cloudflare.com/cdn-cgi/trace".to_string(),
|
||||||
],
|
],
|
||||||
ipv6_urls: vec![
|
ipv6_urls: vec![
|
||||||
"https://api.cloudflare.com/cdn-cgi/trace".to_string(),
|
|
||||||
"https://[2606:4700:4700::1001]/cdn-cgi/trace".to_string(),
|
"https://[2606:4700:4700::1001]/cdn-cgi/trace".to_string(),
|
||||||
|
"https://api.cloudflare.com/cdn-cgi/trace".to_string(),
|
||||||
],
|
],
|
||||||
|
detection_timeout: config.detection_timeout,
|
||||||
dry_run: config.dry_run,
|
dry_run: config.dry_run,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut warnings = LegacyWarningState::default();
|
let mut warnings = LegacyWarningState::default();
|
||||||
|
|
||||||
let ips = ddns
|
let mut ips = ddns
|
||||||
.get_ips(
|
.get_ips(
|
||||||
legacy.a,
|
legacy.a,
|
||||||
legacy.aaaa,
|
legacy.aaaa,
|
||||||
@@ -266,6 +269,38 @@ async fn update_legacy(config: &AppConfig, _ppfmt: &PP) -> bool {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
// Filter out Cloudflare IPs if enabled
|
||||||
|
if config.reject_cloudflare_ips {
|
||||||
|
let detection_client = Client::builder()
|
||||||
|
.timeout(config.detection_timeout)
|
||||||
|
.build()
|
||||||
|
.unwrap_or_default();
|
||||||
|
if let Some(cf_filter) =
|
||||||
|
CloudflareIpFilter::fetch(&detection_client, config.detection_timeout, ppfmt).await
|
||||||
|
{
|
||||||
|
ips.retain(|key, ip_info| {
|
||||||
|
if let Ok(addr) = ip_info.ip.parse::<std::net::IpAddr>() {
|
||||||
|
if cf_filter.contains(&addr) {
|
||||||
|
ppfmt.warningf(
|
||||||
|
pp::EMOJI_WARNING,
|
||||||
|
&format!(
|
||||||
|
"Rejected {}: matches Cloudflare IP range ({})",
|
||||||
|
ip_info.ip, key
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ppfmt.warningf(
|
||||||
|
pp::EMOJI_WARNING,
|
||||||
|
"Could not fetch Cloudflare IP ranges; skipping filter",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ddns.update_ips(
|
ddns.update_ips(
|
||||||
&ips,
|
&ips,
|
||||||
&legacy.cloudflare,
|
&legacy.cloudflare,
|
||||||
@@ -346,9 +381,19 @@ struct LegacyDdnsClient {
|
|||||||
cf_api_base: String,
|
cf_api_base: String,
|
||||||
ipv4_urls: Vec<String>,
|
ipv4_urls: Vec<String>,
|
||||||
ipv6_urls: Vec<String>,
|
ipv6_urls: Vec<String>,
|
||||||
|
detection_timeout: Duration,
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a Host header override for literal-IP trace URLs so TLS SNI works.
|
||||||
|
fn legacy_host_override(url: &str) -> Option<&'static str> {
|
||||||
|
if url.contains("1.0.0.1") || url.contains("2606:4700:4700::1001") {
|
||||||
|
Some("one.one.one.one")
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LegacyDdnsClient {
|
impl LegacyDdnsClient {
|
||||||
async fn get_ips(
|
async fn get_ips(
|
||||||
&self,
|
&self,
|
||||||
@@ -361,8 +406,11 @@ impl LegacyDdnsClient {
|
|||||||
let mut ips = HashMap::new();
|
let mut ips = HashMap::new();
|
||||||
|
|
||||||
if ipv4_enabled {
|
if ipv4_enabled {
|
||||||
|
// Use an IPv4-bound client so the trace endpoint sees the correct address family.
|
||||||
|
let v4_client = crate::provider::build_split_client(IpType::V4, self.detection_timeout);
|
||||||
let a = self
|
let a = self
|
||||||
.try_trace_urls(
|
.try_trace_urls(
|
||||||
|
&v4_client,
|
||||||
&self.ipv4_urls,
|
&self.ipv4_urls,
|
||||||
&mut warnings.shown_ipv4,
|
&mut warnings.shown_ipv4,
|
||||||
&mut warnings.shown_ipv4_secondary,
|
&mut warnings.shown_ipv4_secondary,
|
||||||
@@ -385,8 +433,11 @@ impl LegacyDdnsClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ipv6_enabled {
|
if ipv6_enabled {
|
||||||
|
// Use an IPv6-bound client so the trace endpoint sees the correct address family.
|
||||||
|
let v6_client = crate::provider::build_split_client(IpType::V6, self.detection_timeout);
|
||||||
let aaaa = self
|
let aaaa = self
|
||||||
.try_trace_urls(
|
.try_trace_urls(
|
||||||
|
&v6_client,
|
||||||
&self.ipv6_urls,
|
&self.ipv6_urls,
|
||||||
&mut warnings.shown_ipv6,
|
&mut warnings.shown_ipv6,
|
||||||
&mut warnings.shown_ipv6_secondary,
|
&mut warnings.shown_ipv6_secondary,
|
||||||
@@ -413,6 +464,7 @@ impl LegacyDdnsClient {
|
|||||||
|
|
||||||
async fn try_trace_urls(
|
async fn try_trace_urls(
|
||||||
&self,
|
&self,
|
||||||
|
trace_client: &Client,
|
||||||
urls: &[String],
|
urls: &[String],
|
||||||
shown_primary: &mut bool,
|
shown_primary: &mut bool,
|
||||||
shown_secondary: &mut bool,
|
shown_secondary: &mut bool,
|
||||||
@@ -420,7 +472,11 @@ impl LegacyDdnsClient {
|
|||||||
expect_v4: bool,
|
expect_v4: bool,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
for (i, url) in urls.iter().enumerate() {
|
for (i, url) in urls.iter().enumerate() {
|
||||||
match self.client.get(url).send().await {
|
let mut req = trace_client.get(url);
|
||||||
|
if let Some(host) = legacy_host_override(url) {
|
||||||
|
req = req.header("Host", host);
|
||||||
|
}
|
||||||
|
match req.send().await {
|
||||||
Ok(resp) => {
|
Ok(resp) => {
|
||||||
if let Some(ip) =
|
if let Some(ip) =
|
||||||
crate::provider::parse_trace_ip(&resp.text().await.unwrap_or_default())
|
crate::provider::parse_trace_ip(&resp.text().await.unwrap_or_default())
|
||||||
@@ -1718,12 +1774,13 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![format!("{}/trace", server.uri())],
|
ipv4_urls: vec![format!("{}/trace", server.uri())],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let mut shown_primary = false;
|
let mut shown_primary = false;
|
||||||
let mut shown_secondary = false;
|
let mut shown_secondary = false;
|
||||||
let result = ddns
|
let result = ddns
|
||||||
.try_trace_urls(&ddns.ipv4_urls, &mut shown_primary, &mut shown_secondary, "IPv4", true)
|
.try_trace_urls(&ddns.client, &ddns.ipv4_urls, &mut shown_primary, &mut shown_secondary, "IPv4", true)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(result, Some("198.51.100.1".to_string()));
|
assert_eq!(result, Some("198.51.100.1".to_string()));
|
||||||
}
|
}
|
||||||
@@ -1748,12 +1805,13 @@ mod tests {
|
|||||||
format!("{}/fallback", server.uri()),
|
format!("{}/fallback", server.uri()),
|
||||||
],
|
],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let mut shown_primary = false;
|
let mut shown_primary = false;
|
||||||
let mut shown_secondary = false;
|
let mut shown_secondary = false;
|
||||||
let result = ddns
|
let result = ddns
|
||||||
.try_trace_urls(&ddns.ipv4_urls, &mut shown_primary, &mut shown_secondary, "IPv4", true)
|
.try_trace_urls(&ddns.client, &ddns.ipv4_urls, &mut shown_primary, &mut shown_secondary, "IPv4", true)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(result, Some("198.51.100.2".to_string()));
|
assert_eq!(result, Some("198.51.100.2".to_string()));
|
||||||
assert!(shown_primary);
|
assert!(shown_primary);
|
||||||
@@ -1769,12 +1827,13 @@ mod tests {
|
|||||||
"http://127.0.0.1:1/fail2".to_string(),
|
"http://127.0.0.1:1/fail2".to_string(),
|
||||||
],
|
],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let mut shown_primary = false;
|
let mut shown_primary = false;
|
||||||
let mut shown_secondary = false;
|
let mut shown_secondary = false;
|
||||||
let result = ddns
|
let result = ddns
|
||||||
.try_trace_urls(&ddns.ipv4_urls, &mut shown_primary, &mut shown_secondary, "IPv4", true)
|
.try_trace_urls(&ddns.client, &ddns.ipv4_urls, &mut shown_primary, &mut shown_secondary, "IPv4", true)
|
||||||
.await;
|
.await;
|
||||||
assert!(result.is_none());
|
assert!(result.is_none());
|
||||||
assert!(shown_primary);
|
assert!(shown_primary);
|
||||||
@@ -1797,6 +1856,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let entry = crate::config::LegacyCloudflareEntry {
|
let entry = crate::config::LegacyCloudflareEntry {
|
||||||
@@ -1831,6 +1891,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let entry = crate::config::LegacyCloudflareEntry {
|
let entry = crate::config::LegacyCloudflareEntry {
|
||||||
@@ -1862,6 +1923,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let entry = crate::config::LegacyCloudflareEntry {
|
let entry = crate::config::LegacyCloudflareEntry {
|
||||||
@@ -1886,6 +1948,7 @@ mod tests {
|
|||||||
cf_api_base: "http://localhost".to_string(),
|
cf_api_base: "http://localhost".to_string(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let entry = crate::config::LegacyCloudflareEntry {
|
let entry = crate::config::LegacyCloudflareEntry {
|
||||||
@@ -1918,6 +1981,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let entry = crate::config::LegacyCloudflareEntry {
|
let entry = crate::config::LegacyCloudflareEntry {
|
||||||
@@ -1955,6 +2019,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![format!("{}/trace", server.uri())],
|
ipv4_urls: vec![format!("{}/trace", server.uri())],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let mut warnings = LegacyWarningState::default();
|
let mut warnings = LegacyWarningState::default();
|
||||||
@@ -1967,6 +2032,8 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_legacy_get_ips_ipv6_enabled() {
|
async fn test_legacy_get_ips_ipv6_enabled() {
|
||||||
|
// Test the IPv6 trace URL parsing via try_trace_urls directly, since
|
||||||
|
// get_ips creates an IPv6-bound client that can't reach IPv4-only mock servers.
|
||||||
let server = MockServer::start().await;
|
let server = MockServer::start().await;
|
||||||
Mock::given(method("GET"))
|
Mock::given(method("GET"))
|
||||||
.and(path("/trace6"))
|
.and(path("/trace6"))
|
||||||
@@ -1982,14 +2049,15 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![format!("{}/trace6", server.uri())],
|
ipv6_urls: vec![format!("{}/trace6", server.uri())],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let mut warnings = LegacyWarningState::default();
|
let mut shown_primary = false;
|
||||||
let config: Vec<crate::config::LegacyCloudflareEntry> = vec![];
|
let mut shown_secondary = false;
|
||||||
let ips = ddns.get_ips(false, true, false, &config, &mut warnings).await;
|
let result = ddns
|
||||||
assert!(ips.contains_key("ipv6"));
|
.try_trace_urls(&ddns.client, &ddns.ipv6_urls, &mut shown_primary, &mut shown_secondary, "IPv6", false)
|
||||||
assert_eq!(ips["ipv6"].ip, "2001:db8::1");
|
.await;
|
||||||
assert_eq!(ips["ipv6"].record_type, "AAAA");
|
assert_eq!(result, Some("2001:db8::1".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
@@ -1999,6 +2067,7 @@ mod tests {
|
|||||||
cf_api_base: String::new(),
|
cf_api_base: String::new(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let mut warnings = LegacyWarningState::default();
|
let mut warnings = LegacyWarningState::default();
|
||||||
@@ -2045,6 +2114,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let ip = LegacyIpInfo {
|
let ip = LegacyIpInfo {
|
||||||
@@ -2103,6 +2173,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let ip = LegacyIpInfo {
|
let ip = LegacyIpInfo {
|
||||||
@@ -2147,6 +2218,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: true,
|
dry_run: true,
|
||||||
};
|
};
|
||||||
let ip = LegacyIpInfo {
|
let ip = LegacyIpInfo {
|
||||||
@@ -2200,6 +2272,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let ip = LegacyIpInfo {
|
let ip = LegacyIpInfo {
|
||||||
@@ -2257,6 +2330,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let ip = LegacyIpInfo {
|
let ip = LegacyIpInfo {
|
||||||
@@ -2308,6 +2382,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let mut ips = HashMap::new();
|
let mut ips = HashMap::new();
|
||||||
@@ -2354,6 +2429,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: false,
|
dry_run: false,
|
||||||
};
|
};
|
||||||
let config = vec![crate::config::LegacyCloudflareEntry {
|
let config = vec![crate::config::LegacyCloudflareEntry {
|
||||||
@@ -2388,6 +2464,7 @@ mod tests {
|
|||||||
cf_api_base: server.uri(),
|
cf_api_base: server.uri(),
|
||||||
ipv4_urls: vec![],
|
ipv4_urls: vec![],
|
||||||
ipv6_urls: vec![],
|
ipv6_urls: vec![],
|
||||||
|
detection_timeout: Duration::from_secs(5),
|
||||||
dry_run: true,
|
dry_run: true,
|
||||||
};
|
};
|
||||||
let config = vec![crate::config::LegacyCloudflareEntry {
|
let config = vec![crate::config::LegacyCloudflareEntry {
|
||||||
|
|||||||
Reference in New Issue
Block a user