handler: Custom prefix length

This commit is contained in:
LittleChest 2025-08-13 09:14:41 +08:00
parent f16c3164fe
commit 0c3cb5e6aa
5 changed files with 37 additions and 13 deletions

View File

@ -20,9 +20,11 @@ Read [Dohna NS Documentation](https://dohna.ovh/) to learn how to install Dohna
## Environment Variables
| Key | Default | Description |
| --- | ---------------------------- | ------------------------------------------------ |
| ----------- | ---------------------------- | -------------------------------------------------- |
| DNS | https://dns.google/dns-query | Specify a DNS over HTTPS server as the upstream. |
| API | https://dns.google/resolve | Specify a JSON API server as the upstream. |
| IPV4_PREFIX | 32 | Specify the EDNS client subnet IPv4 prefix length. |
| IPV6_PREFIX | 128 | Specify the EDNS client subnet IPv6 prefix length. |
## Self-hosted

View File

@ -2,5 +2,12 @@ import handler from "./common";
export default {
fetch: async (request, env) =>
handler(request, env.DNS, env.API, request.headers.get("cf-connecting-ip")),
handler(
request,
env.DNS,
env.API,
env.IPV4_PREFIX,
env.IPV6_PREFIX,
request.headers.get("cf-connecting-ip")
),
};

View File

@ -2,6 +2,8 @@ export default async function handler(
request,
dns = "https://dns.google/dns-query",
api = "https://dns.google/resolve",
ipv4Prefix = 32,
ipv6Prefix = 128,
rawIP
) {
const { method, headers, url } = request;
@ -75,14 +77,14 @@ export default async function handler(
}
if (queryData !== undefined) {
res = await queryDns(queryData, ip, dns);
res = await queryDns(queryData, ip, dns, ipv4Prefix, ipv6Prefix);
}
}
return res;
}
async function queryDns(queryData, ip, dns) {
async function queryDns(queryData, ip, dns, ipv4Prefix, ipv6Prefix) {
const hasOptRecord = checkForOptRecord(queryData);
let newQueryData = queryData;
if (!hasOptRecord && ip) {
@ -90,7 +92,7 @@ async function queryDns(queryData, ip, dns) {
const [headerAndQuestion] = extractHeaderAndQuestion(queryData);
// Construct a new OPT record with ECS option
const optRecord = createOptRecord(ip);
const optRecord = createOptRecord(ip, ipv4Prefix, ipv6Prefix);
// Combine the header, question, and new OPT record to create a new query
newQueryData = combineQueryData(headerAndQuestion, optRecord);
@ -172,21 +174,21 @@ function extractHeaderAndQuestion(data) {
return [headerAndQuestion, offset];
}
function createOptRecord(ip) {
function createOptRecord(ip, ipv4Prefix, ipv6Prefix) {
let ecsData;
let family;
if (isIPv4(ip)) {
const prefixLength = ipv4Prefix
// Convert client IP to bytes
const ipParts = ip.split(".").map((part) => parseInt(part, 10));
family = 1; // IPv4
const prefixLength = 32; // Adjust the prefix length as needed
ecsData = [0, 8, 0, 8, 0, family, prefixLength, 0, ...ipParts];
} else if (isIPv6(ip)) {
const prefixLength = ipv6Prefix
// Convert client IP to bytes
const ipParts = ipv6ToBytes(ip);
family = 2; // IPv6
const prefixLength = 128; // Adjust the prefix length as needed
ecsData = [0, 8, 0, 20, 0, family, prefixLength, 0, ...ipParts];
} else {
throw new Error("Invalid IP address");

View File

@ -1,5 +1,11 @@
import handler from "./common";
export default middleware = async (request) => {
return handler(request, process.env.DNS, process.env.API);
return handler(
request,
process.env.DNS,
process.env.API,
process.env.IPV4_PREFIX,
process.env.IPV6_PREFIX
);
};

View File

@ -1,4 +1,11 @@
import handler from "../../common.js";
export default async (request) =>
handler(request, Netlify.env.get("DNS"), Netlify.env.get("API"), Netlify.context.ip);
handler(
request,
Netlify.env.get("DNS"),
Netlify.env.get("API"),
Netlify.env.get("IPV4_PREFIX"),
Netlify.env.get("IPV6_PREFIX"),
Netlify.context.ip
);
export const config = { path: "*" };