Files
as_ban_policy_service/index.mjs
T
2026-06-24 16:28:45 -07:00

90 lines
2.1 KiB
JavaScript

import net from "node:net";
import IpToAsn from "ip-to-asn";
import {
getASFromCache,
updateAS,
isASBanned,
incrementRejected,
incrementAccepted,
} from "./db.mjs";
const asClient = new IpToAsn();
// Create a server
const server = net.createServer((socket) => {
// console.log(`Policy server connection established`);
socket.on("data", async (data) => {
const lines = data.toString().trim();
let response = "dunno"; // Default response
try {
const command = lines.split(/[\r\n]/).reduce((acc, i) => {
const [key, value] = i.split("=");
return { ...acc, [key]: value };
}, {});
const { client_address, client_name, sender, recipient } = command;
console.log(
`Incoming email from "${client_name}[${client_address}]. ${sender} -> ${recipient}`,
);
// check if IP belongs to previously cached AS records
let as = getASFromCache(client_address);
if (!as) {
// console.log(`Fetching AS for ${client_address}`);
const result = await query(client_address);
if (result) {
const { range, ASN, description } = result;
as = ASN;
updateAS(as, range, description);
}
}
const reason = isASBanned(as);
if (reason) {
// console.log(`AS ${as} is banned`);
response = `reject ${reason.reason}`;
incrementRejected(as);
} else {
incrementAccepted(as);
}
// Check if AS is in the ban list
} catch (err) {
console.error("Error processing command:", err);
}
console.log(`Verdict: ${response}`);
socket.write(`${response}\r\n`);
});
socket.on("end", () => {
console.log("Policy server connection ended");
});
socket.on("error", (err) => {
console.error("Policy server socket error:", err);
});
});
// Start the server
server.listen(12346, "127.0.0.1", () => {
console.log(`Policy server running`);
});
function query(...ip) {
return new Promise((resolve, reject) => {
asClient.query(ip, (err, result) => {
if (err) {
return reject(err);
}
resolve(result[ip[0]]);
});
});
}