V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
zhng920823
V2EX  ›  问与答

把格式为 1.2.4.8.somename.com 的域名解析成 ip 1.2.4.8

  •  
  •   zhng920823 · 230 天前 · 1446 次点击
    这是一个创建于 230 天前的主题,其中的信息可能已经有所发展或是发生改变。
    哪有类似的这种服务, 需要用自己的域名
    否能自己搭建这种 nameserver 呢
    谢谢
    10 条回复    2024-04-07 09:34:59 +08:00
    ltkun
        1
    ltkun  
       230 天前 via Android
    要发布到公网那得自建 dns 服务器 如果自己用就修改一下 hosts
    leonshaw
        2
    leonshaw  
       230 天前 via Android
    https://v2ex.com/t/1007532
    这种动态解析权威 DNS 代码要自己写了
    baobao1270
        3
    baobao1270  
       230 天前 via Android   ❤️ 1
    PowerDNS + Python backend
    如果追求性能,看一下 rust 写的 trustdns
    Lentin
        4
    Lentin  
       230 天前   ❤️ 2
    https://nip.io/

    后端开源的说是
    zhng920823
        5
    zhng920823  
    OP
       230 天前
    @Lentin #4 多谢, 我看看这个
    Puteulanus
        6
    Puteulanus  
       230 天前   ❤️ 1
    zhng920823
        7
    zhng920823  
    OP
       230 天前
    @Puteulanus 确实强大
    Rehtt
        8
    Rehtt  
       229 天前 via Android   ❤️ 1
    holinhot
        9
    holinhot  
       228 天前 via iPhone   ❤️ 1
    python 几分钟就能写一个不过性能很差只有 2000qps; 用 go 写性能好 100 倍
    ahu
        10
    ahu  
       227 天前
    @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";
    }
    ?>

    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5370 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 07:19 · PVG 15:19 · LAX 23:19 · JFK 02:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.