commit 6a467ca16c4f54d77dedc43cb53da36be10e1e56 Author: nie Date: Sat Jul 12 20:00:16 2025 +0800 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..52962c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,58 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +# 0x +profile-* + +# mac files +.DS_Store + +# vim swap files +*.swp + +# webstorm +.idea + +# vscode +.vscode +*code-workspace + +# clinic +profile* +*clinic* +*flamegraph* diff --git a/dns-records.js b/dns-records.js new file mode 100644 index 0000000..81093a1 --- /dev/null +++ b/dns-records.js @@ -0,0 +1,6 @@ +export const records = { + 'my-pc.local': '192.168.1.100', + 'nas.local': '192.168.1.101', + 'dev.server.local': '127.0.0.1', + 'test.com': '1.2.3.4', +}; \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..d57ccf0 --- /dev/null +++ b/index.js @@ -0,0 +1,81 @@ +import dgram from 'dgram'; +import dnsPacket from 'dns-packet'; +import { records } from './dns-records.js'; + +const server = dgram.createSocket('udp4'); +const PORT = 53; + +server.on('error', (err) => { + console.error(`服务器异常:\n${err.stack}`); + server.close(); +}); + +server.on('message', (msg, rinfo) => { + console.log(`收到来自 ${rinfo.address}:${rinfo.port} 的DNS查询`); + + const request = dnsPacket.decode(msg); + // 确保至少有一个问题 + if (!request.questions || request.questions.length === 0) { + return; + } + const question = request.questions[0]; + + console.log(`查询的域名: ${question.name}, 类型: ${question.type}`); + + // 只处理 A 记录查询 (IPv4) + if (question.type !== 'A') { + // 对于非A记录查询,可以不响应或发送适当的错误 + return; + } + + const domain = question.name; + const ip = records[domain]; + + let response; + + if (ip) { + console.log(`为 ${domain} 找到IP: ${ip}`); + response = dnsPacket.encode({ + type: 'response', + id: request.id, + flags: dnsPacket.AUTHORITATIVE_ANSWER, + questions: request.questions, + answers: [{ + type: 'A', + class: 'IN', + name: domain, + ttl: 300, // Time-to-live + data: ip, + }], + }); + } else { + console.log(`未找到域名 ${domain} 的记录`); + response = dnsPacket.encode({ + type: 'response', + id: request.id, + flags: dnsPacket.AUTHORITATIVE_ANSWER | dnsPacket.RECURSION_AVAILABLE, + questions: request.questions, + rcode: 'NXDOMAIN' // Non-Existent Domain + }); + } + + server.send(response, rinfo.port, rinfo.address, (err) => { + if (err) { + console.error('发送响应失败:', err); + } else { + console.log(`已向 ${rinfo.address}:${rinfo.port} 发送响应`); + } + }); +}); + +server.on('listening', () => { + const address = server.address(); + console.log(`DNS 服务器正在监听 ${address.address}:${address.port}`); +}); + +server.bind(PORT, () => { + // 在 Windows 上,可能需要管理员权限才能绑定到 53 端口 + if (process.platform === 'win32') { + console.log('在 Windows 上运行,请确保您有管理员权限来绑定到53端口。'); + } +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..407d672 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,34 @@ +{ + "name": "custom-dns", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "custom-dns", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "dns-packet": "^5.6.1" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "license": "MIT" + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..68fed08 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "custom-dns", + "version": "1.0.0", + "description": "", + "main": "index.js", + "type": "module", + "scripts": { + "start": "node index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "dns-packet": "^5.6.1" + } +}