roster-server 2.1.28 → 2.1.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roster-server",
3
- "version": "2.1.28",
3
+ "version": "2.1.32",
4
4
  "description": "👾 RosterServer - A domain host router to host multiple HTTPS.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -44,7 +44,7 @@ module.exports.create = function create(config = {}) {
44
44
  const challenger = legacyCli.create(config);
45
45
  const propagationDelay = Number.isFinite(config.propagationDelay)
46
46
  ? config.propagationDelay
47
- : 60000;
47
+ : 120000;
48
48
  const envAutoContinue = process.env.ROSTER_DNS_AUTO_CONTINUE;
49
49
  const parseAutoContinue = (value, fallback) => {
50
50
  if (value === undefined || value === null || value === '') return fallback;
@@ -76,16 +76,36 @@ module.exports.create = function create(config = {}) {
76
76
  : Number.isFinite(Number(process.env.ROSTER_DNS_POLL_INTERVAL_MS))
77
77
  ? Number(process.env.ROSTER_DNS_POLL_INTERVAL_MS)
78
78
  : 5000;
79
- const dnsPollTimeoutMs = Number.isFinite(config.dnsPollTimeoutMs)
80
- ? config.dnsPollTimeoutMs
81
- : Number.isFinite(Number(process.env.ROSTER_DNS_POLL_TIMEOUT_MS))
82
- ? Number(process.env.ROSTER_DNS_POLL_TIMEOUT_MS)
83
- : null;
84
- const dryRunPollTimeoutMs = Number.isFinite(config.dryRunPollTimeoutMs)
85
- ? config.dryRunPollTimeoutMs
86
- : Number.isFinite(Number(process.env.ROSTER_DNS_DRYRUN_POLL_TIMEOUT_MS))
87
- ? Number(process.env.ROSTER_DNS_DRYRUN_POLL_TIMEOUT_MS)
88
- : null;
79
+ const parseTimeoutMs = (value, fallback) => {
80
+ if (value === undefined || value === null || value === '') return fallback;
81
+ const normalized = String(value).trim().toLowerCase();
82
+ if (normalized === '-1' || normalized === 'inf' || normalized === 'infinite') return null;
83
+ const parsed = Number(normalized);
84
+ if (Number.isFinite(parsed) && parsed >= 0) return parsed;
85
+ return fallback;
86
+ };
87
+ const dnsPollTimeoutMs = config.dnsPollTimeoutMs !== undefined
88
+ ? parseTimeoutMs(config.dnsPollTimeoutMs, propagationDelay)
89
+ : parseTimeoutMs(process.env.ROSTER_DNS_POLL_TIMEOUT_MS, propagationDelay);
90
+ const dryRunPollTimeoutMs = config.dryRunPollTimeoutMs !== undefined
91
+ ? parseTimeoutMs(config.dryRunPollTimeoutMs, dryRunDelay)
92
+ : parseTimeoutMs(process.env.ROSTER_DNS_DRYRUN_POLL_TIMEOUT_MS, dryRunDelay);
93
+ const dnsPollDebug = config.dnsPollDebug !== undefined
94
+ ? parseBool(config.dnsPollDebug, true)
95
+ : parseBool(process.env.ROSTER_DNS_POLL_DEBUG, true);
96
+ const parseResolvers = (value) => String(value || '')
97
+ .split(',')
98
+ .map((s) => s.trim())
99
+ .filter(Boolean);
100
+ const configuredResolvers = Array.isArray(config.dnsResolvers)
101
+ ? config.dnsResolvers.map((s) => String(s).trim()).filter(Boolean)
102
+ : parseResolvers(process.env.ROSTER_DNS_RESOLVERS);
103
+ const effectiveResolvers = configuredResolvers.length > 0 ? configuredResolvers : ['1.1.1.1', '8.8.8.8'];
104
+ const resolverClients = effectiveResolvers.map((server) => {
105
+ const resolver = new dns.Resolver();
106
+ resolver.setServers([server]);
107
+ return { server, resolver };
108
+ });
89
109
 
90
110
  function sleep(ms) {
91
111
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -100,26 +120,48 @@ module.exports.create = function create(config = {}) {
100
120
  return candidate ? String(candidate).trim() : '';
101
121
  }
102
122
 
103
- async function hasDnsTxtToken(dnsHost, expectedToken) {
104
- if (!dnsHost || !expectedToken) return false;
105
- try {
106
- const records = await dns.resolveTxt(dnsHost);
107
- for (const recordParts of records || []) {
108
- const joined = (recordParts || []).map(normalizeTxtChunk).join('').trim();
109
- if (joined === expectedToken) return true;
123
+ async function resolveTxtRecords(dnsHost) {
124
+ const records = [];
125
+ const errors = [];
126
+
127
+ for (const { server, resolver } of resolverClients) {
128
+ try {
129
+ const result = await resolver.resolveTxt(dnsHost);
130
+ if (Array.isArray(result)) {
131
+ records.push(...result);
132
+ }
133
+ } catch (error) {
134
+ errors.push(`${server}:${error?.code || error?.message || error}`);
110
135
  }
111
- return false;
112
- } catch (_) {
113
- return false;
114
136
  }
137
+ return { records, errors };
115
138
  }
116
139
 
117
140
  async function waitForDnsTxtPropagation(dnsHost, expectedToken, timeoutMs) {
118
141
  const started = Date.now();
119
142
  const hasFiniteTimeout = Number.isFinite(timeoutMs) && timeoutMs >= 0;
120
143
  const maxWait = hasFiniteTimeout ? timeoutMs : null;
144
+ let attempt = 0;
121
145
  while (maxWait === null || (Date.now() - started) <= maxWait) {
122
- if (await hasDnsTxtToken(dnsHost, expectedToken)) return true;
146
+ attempt += 1;
147
+ const { records, errors } = await resolveTxtRecords(dnsHost);
148
+ const seenTokens = [];
149
+ let found = false;
150
+ for (const recordParts of records || []) {
151
+ const joined = (recordParts || []).map(normalizeTxtChunk).join('').trim();
152
+ if (joined) seenTokens.push(joined);
153
+ if (joined === expectedToken) {
154
+ found = true;
155
+ }
156
+ }
157
+
158
+ if (dnsPollDebug) {
159
+ const errorMsg = errors.length > 0 ? ` errors=[${errors.join(', ')}]` : '';
160
+ const seenMsg = seenTokens.length > 0 ? ` seen=[${seenTokens.join(', ')}]` : ' seen=[]';
161
+ log.info(`DNS poll attempt ${attempt} ${dnsHost}${seenMsg}${errorMsg}`);
162
+ }
163
+
164
+ if (found) return true;
123
165
  await sleep(Math.max(1000, dnsPollIntervalMs));
124
166
  }
125
167
  return false;
@@ -158,8 +200,8 @@ module.exports.create = function create(config = {}) {
158
200
  'DNS verification enabled. Continuing automatically when TXT appears at ' +
159
201
  dnsHost +
160
202
  ' (timeout ' +
161
- (effectiveTimeoutMs === null ? 'infinite' : effectiveTimeoutMs) +
162
- 'ms, poll ' +
203
+ (effectiveTimeoutMs === null ? 'infinite' : (effectiveTimeoutMs + 'ms')) +
204
+ ', poll ' +
163
205
  dnsPollIntervalMs +
164
206
  'ms).'
165
207
  );
@@ -169,7 +211,7 @@ module.exports.create = function create(config = {}) {
169
211
  return null;
170
212
  }
171
213
  log.warn(
172
- `DNS TXT not detected for ${dnsHost} within ${effectiveTimeoutMs}; ` +
214
+ `DNS TXT not detected for ${dnsHost} within ${effectiveTimeoutMs === null ? 'infinite' : (effectiveTimeoutMs + 'ms')}; ` +
173
215
  'continuing anyway (ACME preflight may still fail).'
174
216
  );
175
217
  return null;