feat: DNS-free WAN IP detection + add calibre to records
Use Cloudflare 1.1.1.1/cdn-cgi/trace as primary IP source (fixed IP, no resolver dependency — survives AdGuard/upstream DNS outages). Add calibre to DNS_RECORDS: its A record points at the dynamic WAN IP but was not guarded, so it would go stale on the next WAN change.
This commit is contained in:
parent
b8e865c83e
commit
4f9b2c064e
3 changed files with 15 additions and 8 deletions
|
|
@ -15,7 +15,7 @@ MATRIX_TOKEN_FILE=/home/aiaiaiaiagent/whatsed-new/secrets/sherpa-token
|
|||
MATRIX_ROOM_FILE=/home/aiaiaiaiagent/whatsed-new/secrets/eddy-report-room
|
||||
|
||||
# DNS records to update (comma-separated, use domain name for apex)
|
||||
DNS_RECORDS=example.com,git,www,weegschaal,whatsed,auth.whatsed
|
||||
DNS_RECORDS=example.com,git,nextcloud,plausible,weegschaal,www,whatsed,auth.whatsed,calibre
|
||||
|
||||
# EuroDynDNS (domeinen in de EuroDNS-zone, bv. eddydev.ink)
|
||||
# Gebruikt de EuroDNS site-login / site-password (dyndns2), NIET een API-key.
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ sudo systemctl enable --now wan-ip-guard.timer
|
|||
| `MATRIX_API_ENDPOINT` | Matrix homeserver API | `https://whatsed.eddydevink.nl` |
|
||||
| `MATRIX_TOKEN_FILE` | Bestand met Sherpa compat-token | `/home/aiaiaiaiagent/whatsed-new/secrets/sherpa-token` |
|
||||
| `MATRIX_ROOM_FILE` | Bestand met DM-room voor Eddy | `/home/aiaiaiaiagent/whatsed-new/secrets/eddy-report-room` |
|
||||
| `DNS_RECORDS` | Komma-gescheiden records | `example.com,git,www` |
|
||||
| `DNS_RECORDS` | Komma-gescheiden records | `example.com,git,www,whatsed,auth.whatsed,calibre` |
|
||||
| `EURODYNDNS_USER` | EuroDNS site-login (dyndns2) | `your_login` |
|
||||
| `EURODYNDNS_PASS` | EuroDNS site-password (dyndns2) | `your_password` |
|
||||
| `EURODYNDNS_HOSTS` | EuroDynDNS-hostnames (domeinen in EuroDNS-zone) | `eddydev.ink,www.eddydev.ink` |
|
||||
|
|
@ -116,7 +116,7 @@ wan-ip-guard.service: Failed to spawn 'start' task: Permission denied
|
|||
|
||||
## Hoe het werkt
|
||||
|
||||
1. **IP detectie:** Haalt het WAN IP op via `ifconfig.me` met fallback naar `api.ipify.org` en `icanhazip.com`
|
||||
1. **IP detectie:** Haalt het WAN IP op via `https://1.1.1.1/cdn-cgi/trace` (Cloudflare, DNS-vrij — werkt als de lokale resolver uitvalt) met fallback naar `ifconfig.me`, `api.ipify.org` en `icanhazip.com`
|
||||
2. **State vergelijking:** Vergelijkt met het laatst opgeslagen IP in de state file
|
||||
3. **DNS update:** Voor elke record worden eerst alle bestaande A-records met de exacte oude waarde verwijderd en daarna één nieuw A-record toegevoegd via DirectAdmin API. De delete-aanroep gebruikt `action=select` en een URL-gecodeerde waarde `name=<recordnaam>&value=<oude-ip>` in parameter `arecs0`. De waarde moet dus niet `recordnaam=ip` zijn.
|
||||
4. **EuroDynDNS:** Hostnames in `EURODYNDNS_HOSTS` (domeinen die in de EuroDNS-zone staan, bv. `eddydev.ink`) worden bij een IP-wijziging via de EuroDynDNS-update-URL bijgewerkt: `https://update.eurodyndns.org/update/?hostname=<fqdn>&myip=<ip>` met HTTP Basic auth (`EURODYNDNS_USER`/`EURODYNDNS_PASS`, de EuroDNS site-login/password). Een antwoord `good`/`nochg` telt als succes; een foutcode (`badauth`, `!yours`, `notfqdn`, …) als mislukking.
|
||||
|
|
|
|||
17
index.js
17
index.js
|
|
@ -43,16 +43,23 @@ async function fetchWithTimeout(url, options = {}, timeout = 15000) {
|
|||
}
|
||||
|
||||
async function getWanIp() {
|
||||
// Primary source is DNS-free: Cloudflare's 1.1.1.1 serves /cdn-cgi/trace over
|
||||
// HTTPS on a fixed IP, so detection keeps working when the local resolver
|
||||
// (AdGuard on this host) is down. The echo services below are fallbacks.
|
||||
const services = [
|
||||
'https://ifconfig.me',
|
||||
'https://api.ipify.org',
|
||||
'https://icanhazip.com',
|
||||
{
|
||||
url: 'https://1.1.1.1/cdn-cgi/trace',
|
||||
parse: t => (t.split('\n').find(l => l.startsWith('ip=')) || '').split('=')[1],
|
||||
},
|
||||
{ url: 'https://ifconfig.me', parse: t => t },
|
||||
{ url: 'https://api.ipify.org', parse: t => t },
|
||||
{ url: 'https://icanhazip.com', parse: t => t },
|
||||
];
|
||||
for (const url of services) {
|
||||
for (const { url, parse } of services) {
|
||||
try {
|
||||
const resp = await fetchWithTimeout(url, {}, 10000);
|
||||
if (resp.ok) {
|
||||
const ip = (await resp.text()).trim();
|
||||
const ip = (parse(await resp.text()) || '').trim();
|
||||
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(ip)) {
|
||||
log(`WAN IP obtained from ${url}: ${ip}`);
|
||||
return ip;
|
||||
|
|
|
|||
Loading…
Reference in a new issue