About: the mail node by hostname, found with resolvePtr #17
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
import { test, beforeEach } from "node:test";
|
import { test, beforeEach } from "node:test";
|
||||||
import assert from "node:assert/strict";
|
import assert from "node:assert/strict";
|
||||||
import { clearNodeCache, mailNode } from "./nodes.js";
|
import { clearNodeCache, mailNode, ptrName } from "./nodes.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* About names the mail node by the PTR of the address the server's name
|
* About names the mail node by the PTR of the address the server's name
|
||||||
@@ -38,3 +38,12 @@ test("the answer is cached for a minute, then looked up again", async () => {
|
|||||||
await mailNode("https://mail.example.com", count, rev, 61_000);
|
await mailNode("https://mail.example.com", count, rev, 61_000);
|
||||||
assert.equal(calls, 2);
|
assert.equal(calls, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("the PTR name is built for IPv4 and IPv6 alike", () => {
|
||||||
|
assert.equal(ptrName("192.0.2.52"), "52.2.0.192.in-addr.arpa");
|
||||||
|
assert.equal(
|
||||||
|
ptrName("2001:db8::25"),
|
||||||
|
"5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa",
|
||||||
|
);
|
||||||
|
assert.equal(ptrName("::1"), "1" + ".0".repeat(31) + ".ip6.arpa");
|
||||||
|
});
|
||||||
+18
-1
@@ -12,7 +12,8 @@
|
|||||||
* node has one: mail/mx2/mx3). The server offers its node name only to
|
* node has one: mail/mx2/mx3). The server offers its node name only to
|
||||||
* administrators, so asking it would leave everyone else with nothing.
|
* administrators, so asking it would leave everyone else with nothing.
|
||||||
*/
|
*/
|
||||||
import { lookup as dnsLookup, reverse as dnsReverse } from "node:dns/promises";
|
import { lookup as dnsLookup, resolvePtr } from "node:dns/promises";
|
||||||
|
import { isIPv4 } from "node:net";
|
||||||
import { hostname } from "node:os";
|
import { hostname } from "node:os";
|
||||||
import { config } from "./config.js";
|
import { config } from "./config.js";
|
||||||
|
|
||||||
@@ -33,6 +34,22 @@ export interface Nodes {
|
|||||||
type Lookup = (host: string) => Promise<{ address: string }>;
|
type Lookup = (host: string) => Promise<{ address: string }>;
|
||||||
type Reverse = (address: string) => Promise<string[]>;
|
type Reverse = (address: string) => Promise<string[]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reverse-lookup name for an address: 1.2.0.192.in-addr.arpa, or the
|
||||||
|
* nibble form under ip6.arpa. Asked for directly, because `dns.reverse` came
|
||||||
|
* back empty in the image while the resolver answered the PTR (2026-09-26).
|
||||||
|
*/
|
||||||
|
export function ptrName(address: string): string {
|
||||||
|
if (isIPv4(address)) return `${address.split(".").reverse().join(".")}.in-addr.arpa`;
|
||||||
|
const [head = "", tail = ""] = address.split("::");
|
||||||
|
const groups = (part: string) => (part ? part.split(":") : []);
|
||||||
|
const h = groups(head), t = groups(tail);
|
||||||
|
const full = [...h, ...Array(8 - h.length - t.length).fill("0"), ...t];
|
||||||
|
return `${full.map((g) => g.padStart(4, "0")).join("").split("").reverse().join(".")}.ip6.arpa`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dnsReverse: Reverse = (address) => resolvePtr(ptrName(address));
|
||||||
|
|
||||||
const CACHE_MS = 60_000;
|
const CACHE_MS = 60_000;
|
||||||
const cache = new Map<string, { node: MailNode; at: number }>();
|
const cache = new Map<string, { node: MailNode; at: number }>();
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ interface Nodes {
|
|||||||
|
|
||||||
function mailNodeLabel(m: Nodes["mailServer"]): string {
|
function mailNodeLabel(m: Nodes["mailServer"]): string {
|
||||||
if (!m.address) return t("{host} does not resolve", { host: m.host });
|
if (!m.address) return t("{host} does not resolve", { host: m.host });
|
||||||
return m.name ? `${m.name} (${m.address})` : m.address;
|
// The node's hostname; the bare address only when it has no PTR record.
|
||||||
|
return m.name ?? m.address;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AboutSettings() {
|
export function AboutSettings() {
|
||||||
|
|||||||
Reference in new issue
Block a user