在互联网业务中,时常遇到客户端无法正常解析域名的情况,而获取客户端dns服务器配置有助于及时分析问题进而保障客户体验。

对于技术人员来说,获取客户端服务器地址的方法大概有以下几种:

  1. 打开终端,使用命令ipconfig /all获取
  2. 对于将路由器地址(比如192.168.0.1)作为客户端DNS服务器地址的情况,可以登录路由器检查配置情况
  3. 也可以通过已有的网站,例如https://ip.skk.moe/,查看“DNS”出口查询栏目获得。

那么,我们是否有方法可以搞一搞一个方案,可以获取终端的DNS服务器地址呢?

就这个问题,咨询了GPT,其给了一段代码,可以直接返回当前来解析DNS的客户端的地址。代码如下:

#!/bin/env python3

import socket
import dnslib

def handle_dns_request(data, client_address):
    """
    Handle the DNS request and return a response with the client's IP address as A record.
    """
    try:
        # Parse the DNS request
        request = dnslib.DNSRecord.parse(data)

        # Get the client's IP address
        client_ip = client_address[0]

        # Create a DNS response
        response = dnslib.DNSRecord(
            dnslib.DNSHeader(id=request.header.id, qr=1, aa=1, ra=1),
            q=request.q
        )

        # Add the A record with the client's IP
        response.add_answer(dnslib.RR(
            rname=request.q.qname,
            rtype=dnslib.QTYPE.A,
            rclass=dnslib.CLASS.IN,
            ttl=1,
            rdata=dnslib.A(client_ip)
        ))
        with open("./getdnsserver.log","w") as f:
            f.write(client_ip)
        return response.pack()
    except Exception as e:
        print(f"Error handling request: {e}")
        return None

def start_dns_server(address='0.0.0.0', port=53):
    """
    Start a simple DNS server that returns the client's IP address in A records.
    """
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as server_socket:
        server_socket.bind((address, port))
        print(f"DNS Server started on {address}:{port}")

        try:
            while True:
                data, client_address = server_socket.recvfrom(512)
                print(f"Received request from {client_address}")

                response = handle_dns_request(data, client_address)
                if response:
                    server_socket.sendto(response, client_address)
        except KeyboardInterrupt:
            print("DNS Server stopped")

# Start the DNS server (Note: This requires root privileges for port 53)
start_dns_server()

# The above line is commented out to prevent the server from starting automatically in this environment.
# You can uncomment it and run in your local environment with appropriate permissions.

打包软件

pyinstaller -F main.py

打包容器

#Dockerfile

#FROM alpine:3.14
FROM ubuntu:22.04
WORKDIR /app
COPY ./dist/main /app/main
ENTRYPOINT ["./main"]
version: '3'
services:
  getdnsserver:
    image: zzlyzq/getdnsserver:1.0
    volumes:
      - ./getdnsserver.log:/app/getdnsserver.log
    build:
      context: ./
      dockerfile: Dockerfile
    container_name: getdnsserver
    restart: always
    ports:
      - "53:53/udp"
    networks:
      getdnsserver-network:
        ipv4_address: 172.18.26.31
#    entrypoint:
#      - sh
#      - -euc
#      - sleep 600


networks:
  getdnsserver-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.18.26.0/24

测试效果

使用本地直接测试,无论测试什么域名,总会返回返回访问该程序的SRC IP地址。
2023-12-15T07:26:30.png

将程序部署到公网服务器
对于我的域名sddts.cn
设置一个A记录,将dnscheck.sddts.cn CNAME hk.hlab.sddts.cn
设置一个NS记录,将check.sddts.cn NS dnscheck.sddts.cn
这样,当用户解析所有xx.check.sddts.cn 都会去dnscheck.sddts.cn服务器去进行DNS解析,而会得到终端DNS服务器地址。

2023-12-15T07:28:31.png

当然,这个地方虽然我们本地配置的可能是119.29.29.29,但是去获取xx.check.sddts.cn的SRC IP不一定是119.29.29.29,而是其周围相关的IP地址。

另外,经过一段时间测试,使用公共的DNS服务器119.29.29.29解析xx.check.sddts.cn后,陆续还会有一批地址去解析,而这些地址可能是北京、上海、广州的腾讯云(移动)相关的地址。

最后修改:2024 年 05 月 11 日
如果觉得我的文章对你有用,请随意赞赏