1
ltkun 241 天前 via Android
要发布到公网那得自建 dns 服务器 如果自己用就修改一下 hosts
|
2
leonshaw 241 天前 via Android
https://v2ex.com/t/1007532
这种动态解析权威 DNS 代码要自己写了 |
3
baobao1270 241 天前 via Android 1
PowerDNS + Python backend
如果追求性能,看一下 rust 写的 trustdns |
4
Lentin 241 天前 2
|
5
zhng920823 OP @Lentin #4 多谢, 我看看这个
|
7
zhng920823 OP @Puteulanus 确实强大
|
8
Rehtt 240 天前 via Android 1
|
9
holinhot 239 天前 via iPhone 1
python 几分钟就能写一个不过性能很差只有 2000qps; 用 go 写性能好 100 倍
|
10
ahu 238 天前
@Puteulanus #6 不错的示范 😄
于是我照猫画虎,经过约 5 轮的对话,免费的 GPT 3.5 为我写了个能 work 的 PHP 版本: ``` <?php // 指定域名 $targetDomain = 'somename.com'; // 响应 IP 地址 $responseIP = '1.2.4.8'; // 启动 DNS 服务器 $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); socket_bind($socket, '127.0.0.1', 5345); echo "DNS 服务器已启动...\n"; while (true) { socket_recvfrom($socket, $data, 512, 0, $from, $port); // 解析 DNS 请求 $dnsRequest = dns_parse_message($data); // 打印收到的 DNS 请求 echo "收到 DNS 请求:\n"; print_r($dnsRequest); // 检查请求是否为 A 记录且为目标域名的子域名 if ($dnsRequest && isset($dnsRequest['question'][0]['qtype']) && $dnsRequest['question'][0]['qtype'] == 0 && endsWith($dnsRequest['question'][0]['qname'], ".$targetDomain")) { // 构建响应数据 $dnsResponse = dns_build_response($dnsRequest, $responseIP); // 打印响应数据 echo "准备发送的 DNS 响应:\n"; print_r($dnsResponse); // 发送响应 $bytesSent = socket_sendto($socket, $dnsResponse, strlen($dnsResponse), 0, $from, $port); if ($bytesSent === false) { echo "发送 DNS 响应失败\n"; } else { echo "已发送 $bytesSent 字节的 DNS 响应\n"; } echo "已响应 DNS 请求:{$dnsRequest['question'][0]['qname']} -> $responseIP\n"; } } // 解析 DNS 请求 function dns_parse_message($data) { $dnsHeader = unpack('nid/nflags/nqdcount/nancount/nnscount/narcount', substr($data, 0, 12)); $question = []; $offset = 12; for ($i = 0; $i < $dnsHeader['qdcount']; $i++) { $questionName = ''; $nameFound = false; while (true) { $labelLength = ord($data[$offset]); if ($labelLength == 0) { $offset++; break; } if (($labelLength & 0xC0) == 0xC0) { $offset += 2; // 跳过指针 break; } $questionName .= substr($data, $offset + 1, $labelLength) . '.'; $offset += $labelLength + 1; } $offset += 4; $question[] = [ 'qname' => rtrim($questionName, '.'), 'qtype' => isset(unpack('ntype', substr($data, $offset, 2))['type']) ? unpack('ntype', substr($data, $offset, 2))['type'] : '', ]; $offset += 4; } return [ 'header' => $dnsHeader, 'question' => $question, ]; } // 构建 DNS 响应 function dns_build_response($request, $ip) { $header = pack('nnnnnn', $request['header']['id'], 0x8180, 1, 1, 0, 0); $question = ''; foreach ($request['question'] as $q) { $question .= dns_compress_name($q['qname']) . pack('nn', 1, 1); } $answer = dns_compress_name($request['question'][0]['qname']) . pack('n*', 1, 1, 0, 1, 0, 4); // 响应类型为 A 记录,TTL 为 0 ,数据长度为 4 $answer .= inet_pton($ip); // 将 IP 地址转换为二进制格式 return $header . $question . $answer; } // 辅助函数,检查字符串结尾 function endsWith($haystack, $needle) { return substr($haystack, -strlen($needle)) === $needle; } // 辅助函数,压缩 DNS 消息中的域名 function dns_compress_name($name) { $parts = explode('.', $name); $compressedName = ''; foreach ($parts as $part) { $compressedName .= chr(strlen($part)) . $part; } return $compressedName . "\x00"; } ?> ``` |