常用网络协议整理笔记(五) —DNS协议

常用网络协议整理笔记(五) —DNS协议众所周知 在网络中计算机之间是通过 IP 地址进行互相访问的 当我们访问某个域名时 其背后是 DNS 服务器进行了域名解析 并得到对应的 IP 地址

大家好,欢迎来到IT知识分享网。

常用网络协议整理笔记(五) ---DNS协议

文章索引:

1. DNS协议概述

2. DNS协议格式

3. DNS协议工作原理和流程

4. DNS协议使用方法

5. DNS攻击和防范

6. 代码示例


一、DNS协议概述

1.定义和作用

DNS(域名系统,Domain Name System)是一种用于将人类可读的域名(如 http://www.example.com)转换为计算机可读的 IP 地址(如 192.0.2.1)的协议。

众所周知,在网络中计算机之间是通过IP地址进行互相访问的,当我们访问某个域名时,其背后是DNS服务器进行了域名解析,并得到对应的IP地址。所以域名相比于IP地址而言,更加简单易记,从而可以更方便的访问。

2.协议层次结构

1)DNS协议运行在UDP协议之上,位于网络协议栈的 应用层, 使用端口号53;

2)DNS在协议栈中的层次如下所示:

常用网络协议整理笔记(五) ---DNS协议

3.域名层次结构:

域名是具有一定的层次结构的,从上到下依次为:「根域名」「顶级域名」「二级域名」、(三级域名), 域名的层次结构在 DNS(域名系统)中具有至关重要的作用,它不仅使得域名的管理和解析变得高效,而且确保了互联网的可扩展性、灵活性和可靠性.

常用网络协议整理笔记(五) ---DNS协议

1)顶级域名:就是网址的最后一个部分。即上图中www.baidu.com 的顶级域名就是 .com。由国际机构ICANN来分配,当前顶级域名共有一千多个,它们大致可以分成两类:

a. 一类是「通用顶级域名」(gTLD),比如.com.net.edu.org.xxx等等,共有 700 多个。

b. 另一类是「国家顶级域名」(ccTLD),代表不同的国家和地区,比如.cn(中国)、.io(英属印度洋领地)、.cc( 科科斯群岛)、.tv(图瓦卢)等,共有 300 多个。

2) 二级域名:是在通用顶级域名或国家顶级域名之下具有不同的意义:

a. 通用顶级域名下的二级域名:一般是指域名注册人选择使用的网上名称,如 yahoo.com(商业组织通常使用自己的商标、商号或其他商业标志作为自己的网上名称,如 baidu.com

b. 国家顶级域名下的二级域名:一般是指类似于通用顶级域名的表示注册人类别和功能的标志。例如,在 .com.cn 域名结构中,.com 此时是置于国家顶级域名 .cn 下的二级域名,表示中国的商业性组织,以此类推。

3) 三级域名:是形如 www.baidu.com 的域名,可以当做是二级域名的子域名,特征为域名包含两个 .。对于域名所有者/使用者而言,三级域名都是二级域名的附属物而无需单独费用。

4) 根域名:由于 ICANN 管理着所有的顶级域名,所以它是最高一级的域名节点,被称为根域名(root domain)。在有些场合,http://www.xxx.com 被写成 www.xxx.com.,即最后还会多出一个点。这个点就是根域名,通常在实际使用中不显示。

由三级域名,二级域名,顶级域名可以像树型结构一样向上找。

常用网络协议整理笔记(五) ---DNS协议

4.查询方式:

DNS 查询是指通过 DNS(域名系统)将域名解析为相应的 IP 地址的过程。DNS 查询的方式主要有以下几种:

1) 递归查询:

在递归查询中,DNS 客户端向 DNS 服务器发出请求,并要求该服务器负责完成整个查询过程。递归查询就是从根域开始查,逐步往下,只需查询一次便能得到结果,但比较耗时.

常用网络协议整理笔记(五) ---DNS协议

具体步骤如下:

· 客户端向本地 DNS 服务器发送请求。

· 如果本地 DNS 服务器没有缓存该域名的解析结果,它会向根 DNS 服务器查询。

· 根 DNS 服务器返回对应的顶级域名服务器地址。

· 本地 DNS 服务器再向顶级域名服务器查询。

· 顶级域名服务器返回二级域名服务器地址。

· 本地 DNS 服务器向二级域名服务器查询,最终得到所需的 IP 地址。

· 最后,本地 DNS 服务器将解析结果返回给客户端。

2) 迭代查询:

在迭代查询中,DNS 客户端向 DNS 服务器发出请求,如果该服务器无法提供所需的结果,它会返回一个指向下一个 DNS 服务器的地址,而不是完成整个查询过程。

常用网络协议整理笔记(五) ---DNS协议

具体步骤如下:

· 客户端向本地 DNS 服务器发送请求。

· 如果本地 DNS 服务器没有缓存该域名的解析结果,它会向根 DNS 服务器查询。

· 根 DNS 服务器返回对应的顶级域名服务器的地址。

· 客户端再向顶级域名服务器发送请求。

· 如果顶级域名服务器没有结果,它会返回二级域名服务器的地址。

· 客户端继续向下查询,直到最终获得所需的 IP 地址。

3) 反向 DNS 查询:

反向 DNS 查询是将主机的IP地址转换为对应的域名,以便网络(服务)程序能够通过IP地址查询到主机的域名。这种查询通常用于网络管理和安全性检查。反向查询的过程如下:

a. 将 IP 地址转换为反向格式。例如,IP 地址 192.0.2.1 转换为 1.2.0.192.in-addr.arpa。

b. 向 DNS 服务器发出查询请求,要求返回该 IP 地址对应的域名。

c. DNS 服务器返回相关的域名(如果存在)。

5.DNS和mDNS区别:

DNS(域名系统)和 mDNS(多播域名系统)都是用于域名解析的协议,但它们的工作方式和应用场景有所不同。以下是它们的主要区别:

特性

DNS

mDNS

工作方式

客户端-服务器模式,通过 DNS 服务器进行查询和解析。

多播(Multicast)查询,不依赖专用服务器。

应用场景

适用于广域网(互联网)中的域名解析。

适用于局域网(LAN)中的设备自动发现和名称解析。

查询方式

通过单播(Unicast)进行查询。

通过多播(Multicast)进行查询。

网络拓扑

依赖远程 DNS 服务器,适用于全球范围。

仅限局域网,适用于小规模网络。

端口号

53端口,支持 TCP 和 UDP 协议。

5353端口,使用 UDP 协议。

是否需要 DNS 服务器

需要专用的 DNS 服务器。

不需要专用服务器,设备之间自动发现。

举例说明:

—DNS协议:当在浏览器中输入 http://www.baidu.com 时,浏览器会通过 DNS 查询解析该域名并返回 IP 地址,然后进行连接;

—mDNS协议:当你连接到局域网时,你的设备可以自动通过 mDNS 查找并连接网络中的打印机、智能电视或其他设备,例如 printer.local 或 tv.local,而无需配置 DNS 服务器。

6.名解析和动态域名解析

1) 静态域名解析:像hosts文件那样,手动配置域名和IP地址的映射关系,服务器IP发生变化时,要及时的 手动修改映射关系,否则会访问失败;

2)动态域名解析:通过本地服务每隔数分钟检查一次服务器IP,如果变化就更新到DNS服务器上,维护域名与动态IP的映射关系。

实际场景中,两种方式会同时使用。


二、DNS协议格式

DNS 消息的格式有两种:查询消息(Query Message)和响应消息(Response Message)。这些消息的格式基本相同,主要区别在于消息的内容和解析方式。

1. DNS 消息格式

DNS 消息有 12 字节的固定头部(Header),后面跟着可变长度的问题部分(Question Section)和资源记录部分(Answer Section,Authority Section 和 Additional Section)。DNS 消息结构:

常用网络协议整理笔记(五) ---DNS协议

1) Header 部分(12 字节):

· ID (2 bytes): 请求/响应的标识符,客户端和服务器用于匹配请求和响应。

对于请求报文和其对应的应答报文,这个字段是相同的,通过它可以区分DNS应答报文是哪个请求的响应。用于划分DNS流(一个请求对应一个响应)

· Flags (2 bytes): 标志字段,包括查询/响应标志、是否授权等信息。

常用网络协议整理笔记(五) ---DNS协议

— QR(1bit)查询/响应标志,0为查询,1为响应

—opcode(4bit)0表示标准查询,1表示反向查询,2表示服务器状态请求

—AA(1bit)表示授权回答

—TC(1bit)表示可截断的

—RD(1bit)表示期望递归

—RA(1bit)表示可用递归

—rcode(4bit)表示返回码,0表示没有差错,3表示名字差错,2表示服务器错误(Server Failure)

· Questions (2 bytes): 问题部分的数量,表示后续包含多少个查询问题。

· Answer RRs (2 bytes): 回答部分的资源记录数量。

· Authority RRs (2 bytes): 授权区域的资源记录数量。

· Additional RRs (2 bytes): 附加部分的资源记录数量。

2) DNS查询部分(Question):可变长度

常用网络协议整理笔记(五) ---DNS协议

· Name (variable): 查询的域名,以标签(Label)形式存储,长度前缀的字符串,每个标签的长度与标签本身相结合,格式如下(如:http://dns.jocent.me)

· Type (2 bytes): 查询记录的类型(如 A、MX、CNAME 等)。

常用网络协议整理笔记(五) ---DNS协议

· Class (2 bytes): 查询记录的类别,通常为 IN(Internet)。

Class名称

对应值

描述

IN

1

互联网中的标准 DNS 记录类

CH

3

CHAOS 网络记录类,现已很少使用

HS

4

Hesiod 目录服务协议记录类

ANY

255

请求所有记录类型的查询

以下为抓包的DNS查询数据信息:

常用网络协议整理笔记(五) ---DNS协议

3) 资源记录RR区(Answer / Authority / Additional 部分)可变长度

常用网络协议整理笔记(五) ---DNS协议

这些部分包含查询的结果或附加信息,包括:

· Name: 响应的域名(通常是查询的域名),当报文中域名重复出现的时候,该字段使用2个字节的偏移指针来表示;

· Type: 资源记录类型,同查询类型;

· Class: 资源记录类别, 同查询类;

· TTL (4 bytes): 生存时间,单位是秒,表示该记录在缓存中存活的时间。

· Data length (2 bytes): 数据长度。

· RData (variable): 记录的具体数据,例如 IP 地址、CNAME、MX 服务器等。

以下为抓包的DNS回复数据信息:

常用网络协议整理笔记(五) ---DNS协议

2. 示例 DNS 响应消息:

1.Header ID = 0x1a2b Flags = 0x8180 ( Questions = 1 Answer RRs = 1 Authority RRs = 0 Additional RRs = 0 2.Question Section: Name = "www.example.com" Type = A (IPv4 Class = IN 3.Answer Section: Name = "www.example.com" Type = A (IPv4 Class = IN TTL = 3600 Data length = 4 RData = 192.0.2.1 ( 

3. mDNS(Multicast DNS)协议格式

mDNS 是 DNS 的扩展,它在局部网络内使用多播地址(224.0.0.251)和 UDP(端口 5353)进行域名解析。mDNS 主要用于零配置网络(如局域网内的设备发现),并不依赖于传统的 DNS 服务器,mDNS 的消息结构与标准 DNS 消息相同,只是在传输方式和一些细节上有所不同。


三、DNS协议交互流程

当我们在IE中输入 http://www.rongcloud.cn 后,会执行以下完整的解析过程:

常用网络协议整理笔记(五) ---DNS协议

1. 先查「浏览器缓存」,缓存中维护一张域名与 IP 地址的对应表,有就直接访问IP;

2. 没有就查「本地缓存」,一般是指操作系统自带的 DNS 缓存;

3. 若仍然没有命中,则操作系统将域名发送至「本地域名服务器」,本地域名服务器查询自己的 DNS 缓存,查找成功则返回结果(注意:主机和本地域名服务器之间的查询方式是「递归查询」);

4. 若本地域名服务器的 DNS 缓存没有命中,则本地域名服务器向上级域名服务器进行查询,通过以下方式进行「迭代查询」(注意:本地域名服务器和其他域名服务器之间的查询方式是迭代查询,防止根域名服务器压力过大):

1)首先本地域名服务器向「根域名服务器」发起请求,根域名服务器是最高层次的,它并不会直接指明这个域名对应的 IP 地址,而是返回顶级域名服务器的地址,也就是说给本地域名服务器指明一条道路,让他去这里寻找答案;

2)本地域名服务器拿到这个「顶级域名服务器」的地址后,就向其发起请求,获取「权限域名服务器」的地址;

3)本地域名服务器根据权限域名服务器的地址向其发起请求,最终得到该域名对应的 IP 地址;

5. 本地域名服务器将得到的 IP 地址返回给操作系统,同时自己将 IP 地址缓存起来国;

6. 操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来;

7. 至此,浏览器就得到了域名对应的 IP 地址,然后「缓存」IP和域名的映射关系;


四、DNS协议使用方法

1. Linux系统下DNS 查询命令:

1) nslookup:这个命令可以查询域名的 IP 地址以及其他 DNS 记录(正反向查询均可)

命令

功能

nslookup http://example.com

查询 http://example.com 的 A 记录(IP 地址)

nslookup -query=MX http://example.com

查询 http://example.com 的 MX 记录(邮件交换)

nslookup -query=NS http://example.com

查询 http://example.com 的 NS 记录(名称服务器)

nslookup -query=TXT http://example.com

查询 http://example.com 的 TXT 记录(文本记录)

nslookup http://example.com 8.8.8.8

使用 Google 的 DNS 查询 http://example.com

nslookup 93.184.216.34

查询 IP 地址 93.184.216.34 的反向 DNS 记录

常用网络协议整理笔记(五) ---DNS协议

2) dig:dig 是一个功能强大的 DNS 查询工具,可以提供详细的查询结果,包括查询时间、服务器信息等;

命令

功能

dig http://example.com

查询 http://example.com 的 A 记录(IP 地址)

dig http://example.com MX

查询 http://example.com 的 MX 记录(邮件交换)

dig http://example.com NS

查询 http://example.com 的 NS 记录(名称服务器)

dig http://example.com TXT

查询 http://example.com 的 TXT 记录(文本记录)

dig @8.8.8.8 http://example.com

使用 Google 的 DNS 查询 http://example.com

dig -x 93.184.216.34

查询 IP 地址 93.184.216.34 的反向 DNS

dig +short http://example.com

简化输出,只显示 http://example.com 的 IP 地址

dig +trace http://example.com

追踪 DNS 查询的过程

dig +noall +answer http://example.com

只显示答案部分

常用网络协议整理笔记(五) ---DNS协议

3)host:host 是一个简单的命令行工具,用于查询 DNS(域名系统)记录。它通常用于获取域名的 IP 地址或查询其他类型的 DNS 记录。相较于dig和 nslookup, host的语法更为简单,适合快速查询;

命令

功能

host http://example.com

查询 http://example.com 的 A 记录(IP 地址)

host -t MX http://example.com

查询 http://example.com 的 MX 记录(邮件交换)

host -t NS http://example.com

查询 http://example.com 的 NS 记录(名称服务器)

host -t TXT http://example.com

查询 http://example.com 的 TXT 记录(文本记录)

host -t AAAA http://example.com

查询 http://example.com 的 AAAA 记录(IPv6 地址)

host http://example.com 8.8.8.8

使用 Google 的 DNS 查询 http://example.com

host -a http://example.com

查询 http://example.com 的所有类型的记录

常用网络协议整理笔记(五) ---DNS协议

4) ping:ping 可以通过解析域名来间接查询 DNS,因为它会将域名转换为 IP 地址并尝试与该 IP 地址建立连接;

常用网络协议整理笔记(五) ---DNS协议

2. Linux 系统中DNS 配置方法:

1) /etc/resolv.conf:设置使用的DNS服务器地址;

这个文件用于配置 DNS 解析器的设置。你可以在这里指定 DNS 服务器的 IP 地址。文件的格式通常如下:

nameserver 8.8.8.8 Google 的公共 DNS 服务器

nameserver 114.114.114.114 中国互联网络信息中心(CNNIC)提供的公共 DNS 服务器

2) /etc/hosts:本机的DNS服务器配置文件。

这个文件用于本地静态名称解析,可以手动添加主机名和对应的 IP 地址。例如:192.168.1.10 myserver.local,这允许在没有 DNS 服务器的情况下解析特定的主机名。

3) /etc/dhcp/dhclient.conf(如果使用 DHCP):

如果系统通过 DHCP 获取网络配置,这个文件可以用来配置 DHCP 客户端的行为,包括 DNS 设置;

4)
/etc/systemd/resolved.conf(在使用 systemd 的系统中):

在使用 systemd 的 Linux 发行版中,resolved.conf 文件用于配置 DNS 解析设置。可以通过编辑此文件来指定 DNS 服务器和其他选项。


五、DNS攻击和防范

DNS 劫持、DNS 欺骗和 DDoS 攻击都对个人用户、企业和整个互联网基础设施造成严重的危害,其影响程度因攻击目标、攻击规模和攻击持续时间而异。攻击的目的大多都是为了利益的广告费和推广费。以下简单介绍这几种DNS攻击的原理、攻击方式和防范方法。

1.DNS劫持:

常用网络协议整理笔记(五) ---DNS协议

1)攻击原理:DNS 劫持是指攻击者通过篡改 DNS 解析过程,劫持用户的 DNS 请求,将其引导到恶意服务器或网站。DNS 劫持通常发生在用户发起 DNS 查询时,攻击者修改了用户访问的 DNS 服务器的解析记录,从而改变了网站的实际 IP 地址。

2) 攻击方式

a. 路由器 DNS 劫持:通过攻击或篡改家庭或企业网络中的路由器设置,修改默认的 DNS 服务器地址,将所有连接到该路由器的设备的 DNS 请求指向攻击者控制的 DNS 服务器。

b. ISP 劫持:互联网服务提供商(ISP)可以劫持用户的 DNS 请求,并通过返回恶意的 DNS 记录进行攻击

3) 防范方法

a. 使用可信的 DNS 服务器(如 Google DNS 或中国电信提供的DNS)。

b. 启用 DNS SEC(DNS 安全扩展)来确保 DNS 数据的完整性和真实性。

c. 定期检查 DNS 配置,并保持路由器固件更新。

2.DNS欺骗:

常用网络协议整理笔记(五) ---DNS协议

1) 攻击原理:

DNS 欺骗是指攻击者向目标 DNS 服务器发送伪造的 DNS 响应,从而改变域名解析的结果。攻击者通过伪造的 DNS 响应返回恶意 IP 地址,诱使目标用户连接到恶意网站.

2) 攻击方式:

a. Man-in-the-middle 攻击:攻击者通过监听网络流量,伪造 DNS 响应来篡改目标计算机的 DNS 查询。

b. DNS 服务器攻击:攻击者直接向 DNS 服务器发送伪造的 DNS 响应,污染 DNS 缓存(即 DNS 缓存投毒)

3) 防范方法:

a. 使用 DNSSEC(DNS 安全扩展)来防止 DNS 响应被篡改。

b. 配置 DNS 服务器进行更严格的缓存验证。

c. 使用 HTTPS 和 SSL/TLS 加密传输,避免中间人攻击。

3.DDos攻击:

1) 攻击原理:

DDoS(Distributed Denial of Service)攻击是指攻击者通过大量分布在不同位置的受控设备(通常是“僵尸网络”中的计算机)向目标服务器发起大量请求,导致目标服务器无法正常响应合法用户的请求,从而使目标服务器瘫痪或无法使用。

2) 攻击方式:

a. 流量消耗型攻击(例如 SYN Flood、UDP Flood):通过发送大量无效的数据包,占用网络带宽或计算资源,导致目标系统资源耗尽。

b. 应用层攻击(例如 HTTP Flood):通过向目标网站发送大量 HTTP 请求,消耗服务器的计算资源。

c. 反射攻击:攻击者伪造源 IP 地址,向开放的第三方服务器(如 DNS 服务器、NTP 服务器等)发送请求,这些服务器会将响应发送到受害者的 IP 地址,从而造成拒绝服务攻击。

3) 防范方法:

a. 流量清洗:使用流量清洗服务(如 Cloudflare、Akamai 等),能够在流量到达目标服务器之前过滤掉恶意请求。

b. 速率限制:对单个 IP 地址或用户发出的请求设置速率限制,减少单一用户的请求量。

c. 抗 DDoS 硬件和软件:部署防火墙和反 DDoS 设备,这些设备能够识别并过滤恶意流量。

d. 分布式防御:通过部署多个服务器和负载均衡,分散攻击流量。


六、代码示例

以下是一个简单的 C 语言示例,展示了如何使用 DNS 协议进行域名解析。这个示例使用了原始套接字(raw sockets)来发送 DNS 查询,并解析返回的响应。请注意,这个例子仅用于学习目的,实际使用中可能需要更复杂的错误处理和网络配置。

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <unistd.h> #define DNS_PORT 53 #define DNS_HEADER_SIZE 12 // DNS header structure struct dns_header { unsigned short id; // Identifier unsigned char rd : 1; // Recursion Desired unsigned char tc : 1; // TrunCation unsigned char aa : 1; // Authoritative Answer unsigned char opcode : 4; // Opcode unsigned char qr : 1; // Query/Response unsigned char rcode : 4; // Response code unsigned char z : 1; // Reserved unsigned char ra : 1; // Recursion Available unsigned short q_count; // Number of questions unsigned short ans_count; // Number of answers unsigned short auth_count; // Number of authority records unsigned short add_count; // Number of additional records }; // DNS question structure struct dns_question { unsigned short qtype; // Query type unsigned short qclass; // Query class }; // Function to convert domain name to DNS format void format_domain_name(unsigned char *dn, const char *domain) { char *token; char *domain_copy = strdup(domain); int len = 0; token = strtok(domain_copy, "."); while (token != NULL) { len = strlen(token); *dn++ = len; // Length of the label strcpy((char *)dn, token); // Copy the label dn += len; token = strtok(NULL, "."); } *dn = 0; // End of the domain name free(domain_copy); } // Main function int main() { int sockfd; struct sockaddr_in server_addr; unsigned char buffer[512]; struct dns_header *dns = (struct dns_header *)buffer; struct dns_question *question = (struct dns_question *)(buffer + DNS_HEADER_SIZE); const char *domain = "Example Domain"; // Domain to query sockfd = socket(AF_INET, SOCK_DGRAM, 0); // Create UDP socket if (sockfd < 0) { perror("Socket creation failed"); return 1; } // Set up the server address structure server_addr.sin_family = AF_INET; server_addr.sin_port = htons(DNS_PORT); server_addr.sin_addr.s_addr = inet_addr("114.114.114.114"); // china’s DNS server // Fill in the DNS header dns->id = htons(12345); // Transaction ID dns->qr = 0; // Query dns->opcode = 0; // Standard query dns->aa = 0; // Not authoritative dns->tc = 0; // Not truncated dns->rd = 1; // Recursion desired dns->ra = 0; // Recursion not available dns->z = 0; // Reserved dns->rcode = 0; // No error dns->q_count = htons(1); // One question dns->ans_count = 0; // No answers yet dns->auth_count = 0; // No authority records dns->add_count = 0; // No additional records // Format the domain name format_domain_name(buffer + DNS_HEADER_SIZE + sizeof(struct dns_question), domain); // Set the query type and class question->qtype = htons(1); // A record question->qclass = htons(1); // IN class // Send the DNS query if (sendto(sockfd, buffer, DNS_HEADER_SIZE + sizeof(struct dns_question) + strlen(domain) + 2, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("Send failed"); close(sockfd); return 1; } // Receive the DNS response socklen_t len = sizeof(server_addr); if (recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&server_addr, &len) < 0) { perror("Receive failed"); close(sockfd); return 1; } // Print the response printf("Received DNS response:\n"); for (int i = 0; i < len; i++) { printf("%02x ", buffer[i]); } printf("\n"); close(sockfd); return 0; }

代码说明:

1. 结构体定义

1)dns_header:表示 DNS 响应的头部,包含标识符、标志、问题计数等信息。

2)dns_question:表示 DNS 查询的问题部分,包含查询类型和查询类。

2. 域名格式化函数

format_domain_name:将域名转换为 DNS 协议所需的格式。

3. 主要功能

1)创建 UDP 套接字。

2)填充 DNS 请求的头部和问题部分。

3)发送 DNS 查询请求到指定的 DNS 服务器(在此例中为中国电信 的 DNS 服务器 114.114.114.114)。

4) 接收 DNS 响应并打印响应的原始字节(可以进一步解析以提取 IP 地址等信息)。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/169417.html

(0)
上一篇 2025-02-07 12:20
下一篇 2025-02-07 12:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信