今天我们来学习一个最基本的linux DNS配置
一、 相关概念:
1 DNS原理
1.1 DNS简介
DNS(Domain Name System)域名系统,在TCP/IP网络中有非常重要的地位,能够提供域名与IP地址的解析服务。
1.2 域名空间
DNS是一个分布式数据库,命名系统采用层次的逻辑结构,如同一棵倒置的树,这个逻辑的树形结构称为域名空间,由于DNS划分了域名空间,所以各机构可以使用自己的域名空间创建DNS信息。
注:DNS域名空间中,树的最大深度不得超过127层,树中每个节点最长可以存储63个字符。
1)域和域名
DNS树的每个节点代表一个域,通过这些节点,对整个域名空间进行划分,成为一个层次结构。域名空间的每个域的名字,通过域名进行表示。域名通常由一个完全正式域名(FQDN)标识。FQDN能准确表示出其相对于DNS域树根的位置,也就是节点到DNS树根的完整表述方式,从节点到树根采用反向书写,并将每个节点用“.”分隔,对于DNS域google来说,其完全正式域名(FQDN)为google.com。
一个DNS域可以包括主机和其他域(子域),每个机构都拥有名称空间的某一部分的授权,负责该部分名称空间的管理和划分,并用它来命名DNS域和计算机。例如,google为com域的子域,其表示方法为google.com,而www为google域中的Web,可以使用www.google.com表示。
注意:通常,FQDN有严格的命名限制,长度不能超过256字节,只允许使用字符a-z,0-9,A-Z和减号(-)。点号(.)只允许在域名标志之间(例如“google.com”)或者FQDN的结尾使用。域名不区分大小。
2).Internet域名空间
Internet域名空间结构为一棵倒置的树,并进行层次划分。由树根到树枝,也就是从DNS根到下面的节点,按照不同的层次,进行了统一的命名。域名空间最顶层,DNS根称为根域(root)。根域的下一层为顶级域,又称为一级域。其下层为二级域,再下层为二级域的子域,按照需要进行规划,可以为多级。所以对域名空间整体进行划分,由最顶层到下层,可以分成:根域、顶级域、二级域、子域。并且域中能够包含主机和子域。主机www的FQDN从最下层到最顶层根域进行反写,表示为www.europe.example.com。
Internet域名空间的最顶层是根域(root),其记录着Internet的重要DNS信息,由Internet域名注册授权机构管理,该机构把域名空间各部分的管理责任分配给连接到Internet的各个组织。
DNS根域下面是顶级域,也由Internet域名注册授权机构管理。共有3种类型的顶级域。
组织域:采用3个字符的代号,表示DNS域中所包含的组织的主要功能或活动。比如com为商业机构组织,edu为教育机构组织,gov为政府机构组织,mil为军事机构组织,net为网络机构组织,org为非营利机构组织,int为国际机构组织。
地址域:采用两个字符的国家或地区代号。如cn为中国,kr为韩国,us为美国。
反向域:这是个特殊域,名字为in-addr.arpa,用于将IP地址映射到名字(反向查询)。
对于顶级域的下级域,Internet域名注册授权机构授权给Internet的各种组织。当一个组织获得了对域名空间某一部分的授权后,该组织就负责命名所分配的域及其子域,包括域中的计算机和其他设备,并管理分配的域中主机名与IP地址的映射信息。
1.3 区(Zone)
区是DNS名称空间的一个连续部分,其包含了一组存储在DNS服务器上的资源记录。每个区都位于一个特殊的域节点,但区并不是域。DNS域是名称空间的一个分支,而区一般是存储在文件中的DNS名称空间的某一部分,可以包括多个域。一个域可以再分成几部分,每个部分或区可以由一台DNS服务器控制。使用区的概念,DNS服务器回答关于自己区中主机的查询,它是哪个区的授权服务器。
1.4 DNS查询原理及流程
1)DNS相关概念
(1)DNS服务器
运行DNS服务器程序的计算机,储存DNS数据库信息。DNS服务器会尝试解析客户机的查询请求。在解答查询时,如果DNS服务器能提供所请求的信息,就直接回应解析结果,如果该DNS服务器没有相应的域名信息,则为客户机提供另一个能帮助解析查询的服务器地址,如果以上两种方法均失败,则回应客户机没有所请求的信息或请求的信息不存在。
(2)DNS缓存
DNS服务器在解析客户机请求时,如果本地没有该DNS信息,则可以会询问其他DNS服务器,当其他域名服务器返回查询结果时,该DNS服务器会将结果记录在本地的缓存中,成为DNS缓存。当下一次客户机提交相同请求时,DNS服务器能够直接使用缓存中的DNS信息进行解析。
(3)资源记录
DNS服务器的信息数据,按照分类进行存储,能够解析客户端的DNS请求。
(4)区文件
包含区资源记录的文件,选择DNS服务器为授权服务器,管理该区域。在大部分DNS实现中,用文本文件实现区。
2)递归查询和迭代查询
(1)递归查询
递归查询是一种DNS服务器的查询模式,在该模式下DNS服务器接收到客户机请求,必须使用一个准确的查询结果回复客户机。如果DNS服务器本地没有存储查询DNS信息,那么该服务器会询问其他服务器,并将返回的查询结果提交给客户机。
(2)迭代查询
DNS服务器另外一种查询方式为迭代查询,DNS服务器会向客户机提供其他能够解析查询请求的DNS服务器地址,当客户机发送查询请求时,DNS服务器并不直接回复查询结果,而是告诉客户机另一台DNS服务器地址,客户机再向这台DNS服务器提交请求,依次循环直到返回查询的结果为止。
3)DNS查询流程
(1)DNS域名解析工作原理
<1> 客户机提交域名解析请求,并将该请求发送给本地的域名服务器。
<2> 当本地的域名服务器收到请求后,就先查询本地的缓存。如果有查询的DNS信息记录,则直接返回查询的结果。如果没有该记录,本地域名服务器就把请求发给根域名服务器。
<3> 根域名服务器再返回给本地域名服务器一个所查询域的顶级域名服务器的地址。
<4> 本地服务器再向返回的域名服务器发送请求。
<5> 接收到该查询请求的域名服务器查询其缓存和记录,如果有相关信息则返回客户机查询结果,否则通知客户机下级的域名服务器的地址。
<6> 本地域名服务器将查询请求发送给返回的DNS服务器。
<7> 域名服务器返回本地服务器查询结果(如果该域名服务器不包含查询的DNS信息,查询过程将重复<6>、<7>步骤,直到返回解析信息或解析失败的回应)。
<8> 本地域名服务器将返回的结果保存到缓存,并且将结果返回给客户机。
(2)域名解析实例
假设客户机使用电信ADSL接入Internet,电信为其分配的DNS服务器地址为219.141.140.10,域名解析过程如下哈~
<1> 客户机向本地的域名服务器219.141.140.10发送解析www.google.com请求。
<2> 当本地的域名服务器收到请求后,就先查询本地的缓存。如果有查询的DNS信息记录,则直接返回查询的结果。如果没有该记录,本地域名服务器就把解析www.google.com请求发给根域名服务器。
<3> 根域名服务器收到请求后,根据完全正式域名FQDN,判断该域名属于com域,查询所有的com域DNS服务器的信息,并返回给本地域名服务器。
<4> 本地域名服务器219.141.140.10收到回应后,先保存返回的结果,再选择一台com域的域名服务器,向其提交解析域名www.google.com的请求。
<5> com域名服务器接收到该查询请求后,判断该域名属于google.com域,通过查询本地的记录,列出管理google域的域名服务器信息,然后将查询结果返回给本地的域名服务器219.141.140.10。
<6> 本地域名服务器219.141.140.10收到回应后,先缓存返回的结果,再向google.com域的服务器发出请求解析域名www.google.com的数据包。
<7> 域名服务器google.com收到请求后,查询DNS记录中的www主机的信息,并将结果返回给本地服务器219.141.140.10。
<8> 本地域名服务器将返回的查询结果保存到缓存,并且将结果返回给客户机。
1.7 正向解析与反向解析
1)正向解析
正向解析是指域名到IP地址的解析过程。
2)反向解析
反向解析是从IP地址到域名的解析过程。反向解析的作用为服务器的身份验证。
1.8 资源记录
为了将名字解析为IP地址,服务器查询它们的区(又叫DNS数据库文件或简单数据库文件)。区中包含组成相关DNS域资源信息的资源记录(RR)。例如,某些资源记录把友好名字映射成IP地址,另一些则把IP地址映射到友好名字。某些资源记录不仅包括DNS域中服务器的信息,还可以用于定义域,即指定每台服务器授权了哪些域,这些资源记录就是SOA和NS资源记录。
1)SOA资源记录
每个区在区的开始处都包含了一个起始授权记录(Start of Authority Record),简称SOA记录。SOA定义了域的全局参数,进行整个域的管理设置。一个区域文件只允许存在唯一的SOA记录。
2)NS资源记录
名称服务器(NS)资源记录表示该区的授权服务器,它们表示SOA资源记录中指定的该区的主和辅助服务器,也表示了任何授权区的服务器。每个区在区根处至少包含一个NS记录。
3)A资源记录
地址(A)资源记录把FQDN映射到IP地址,因而解析器能查询FQDN对应的IP地址。
4)PTR资源记录
相对于A资源记录,指针(PTR)记录把IP地址映射到FQDN。
5)CNAME资源记录
规范名字(CNAME)资源记录创建特定FQDN的别名。用户可以使用CNAME记录来隐藏用户网络的实现细节,使连接的客户机无法知道。
6)MX资源记录
邮件交换(MX)资源记录为DNS域名指定邮件交换服务器。邮件交换服务器是为DNS域名处理或转发邮件的主机。处理邮件指把邮件投递到目的地或转交另一不同类型的邮件传送者。转发邮件指把邮件发送到最终目的服务器,用简单邮件传输协议SMTP把邮件发送给离最终目的地最近的邮件交换服务器,或使邮件经过一定时间的排队。
DNS理论和概念了解得差不多了,下面我们开始DNS安装和配置
二、相关配置
首先当然是软件的准备,配置DNS我们需要四个软件分别是
bind,bind-utils,bind-chroot以及caching-nameserver。
bind:该包为DNS服务的主程序包,服务器端必须安装该软件包
bind-utils:该包为客户端工具,默认安装,用于搜索域名指令
安装好前三个软件后,系统会在/var/named/chroot底下生成一些文件(dev,etc,var),进入etc目录下会发现里面只有localtime和rndc.key两个文件,如图:
安装如上安装包时,named服务是不会运行的,我们还需将caching-nameserver安装后才可以启动named,安装好后会发现etc底下多了几个文件,如图:
named.caching-nameserver.conf 和 named.rfc1912.zones 这两个文件和/etc下的同名文件是链接文件。都安装好后我们就可以开始配置了。系统中默认的配置是named.conf文件,我们在此建立一个此文件
复制好后,我们就可以直接在named.conf中进行配置的更改了
1. 编辑named.conf
图1
named.conf是BIND的核心配置文件,它包含了BIND的基本配置,但其并不包括区域数据。named.conf文件定义了DNS服务器的工作目录所在位置,所有的区域数据文件都存放在该目录中,该文件还定义了DNS服务器能够管理哪些区域,如果DNS服务器可以管理某个区域,它将完成该区域内的域名解析工作。named.conf配置文件分为整体和局部两个部分
options为整体配置,在这里的更改将对整个DNS服务器产生影响,而view则是局部的,只对其include下的配置文件起作用,此配置文件包含了各种zone(区文件),当然我们也可以直接把“区”中的内容写在此处,替换掉view。
一般格式为:
options{
字段、字段值;
};
Logging{
字段、字段值;
};
zone {
type 区域类型;
file 区域文件名;
};
我们这里可以用view来替换掉zone的配置,就如图1所示一样。
(1)options配置如下:
◆ listen-on port 53 { 127.0.0.1; }:这个是DNS侦听本机的端口及IP。这里设置表示只侦听127.0.0.1这个地址。如不定义此选项表示侦听所有网络
◆ directory “/var/named”指主配置文件路径,这个路径也是相对路径,它的绝对路径/var/named/chroot/var/named
◆ query-source port 53:客户端在进行DNS查询时必须使用53做为源端口
◆ allow-query { localhost; }:允许提交查询的客户端,如不定义此选项表示允许所有查询
◆ allow-recursion {192.168.0.0/24;192.168.0.1/24}:允许提交递归查询的客户端,如不定义此选项表示允许所有
◆ allow-transfer {192.168.0.254;}:允许区域传输的DNS服务器(辅助DNS),不写表示允许所有,这个也可以写在zone文件中,对特定的域名进行辅助dns查询,写在此处就是表示对此dns下的所有域名都辅助查询
◆ forwarders {192.168.0.9;}:转发器
◆ forward only|first:only表示如果在指定的转发器找不到,不会去向根查询,first表示快速转发(默认)
(2)局部配置
此部分可有多个,只要求localhost_resolver这个名字不重复
◆ match-clients { localhost; };客户端的源IP
◆ match-destinations { localhost; };解析出的目标IP
◆ recursion yes;如果客户端提交的FQDN本服务器没有,那么服务器会帮助客户端去查询(递归查询)
◆ include “/etc/named.rfc1912.zones”; 指定主配置文件
我试验机的具体配置如下:
options { 整体配置对DNS服务器生效
listen-on port 53 { 127.0.0.1;localnets;}; //监听的端口,也可以写成{any;} ,如不定义此选项表示侦听所有网络
// listen-on-v6 port 53 { ::1; }; //对ip6的支持
directory "/var/named"; //区域文件的存储目录,该目录存放区域数据文件。配置文件中所有相对路径的路径名都基于此目录。如果没有指定,默认的是BIND启动的目录。它的绝对路径/var/named/chroot/var/named
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
// Those options should be used carefully because they disable port
// randomization
// query-source port 53; //客户端在进行DNS查询时必须使用53做为源端口
// query-source-v6 port 53;
allow-query { localhost;localnets; };//指定允许查询的主机,我这里指定的是本机和本网段的, 如不定义此选项表示允许所有查询,因为此是在全局配置中定义了,所以局部中的任何区域文件都可以被此处定于的客户机去查询
allow-query-cache { localhost;localnets;}; //貌似是类似递归查询的服务,这里我还需要在查查资料
};
logging {
channel default_debug {
file "data/named.run";
severity dynamic;
};
};
view localhost_resolver { //是一个局部的配置,定义了一个视图
match-clients { localhost;localnets; }; // 查询者的源地址,any表示localhost_resolver视图对任何主机开放,如果写成{ acl1; },那么就只有acl1表里的ip可以递归查询了,这里我们写成了对本机和本网段开放。这里是在局部中定义的,所以只是对此视图有效,当然我们前面全局中
match-destinations { localhost;localnets; }; //查询者的目标地址,这里也可以写成{ localhost; acl1; }
recursion yes; // 设置进行递归查询,即如果客户端提交的FQDN本服务器没有,那么服务器会帮助客户端去查询
include "/etc/named.rfc1912.zones"; //指出了zone文件的位置
};
注意:
可以在全局配置文件的最顶部通过以下文件给定义一个计算机的集合,在指定地址范围进也可使用该集合名称
2.配置zone文件
/var/named/chroot/etc 下,编辑局部视图定义的named.rfc1912.zones文件:
zone "example.com" IN { //解析的域名
type master; //表示服务器类型,type表示是主DNS服务器
file "example.zone"; // 存储A记录文件的名称,意即指定区域配置文件,该文件中将定义资源记录
allow-update { none; }; //是否允许动态更新,这里我们暂时不允许,等下个章节在讲这里
4.配置资源记录文件
首先我们创建一个example.com的区域文件,这个文件应该位于/var/named(全局配置文件中定义的目录)目录下,这个路径是相对的,其绝对路径为:/var/named/chroot/var/named。
如图所示去创建出一份example.com文件,复制的时候记得用cp –a,因为如果区域配置文件的拥有组不是named的话,那么BIND服务是无法运行的。
编辑配置文件:
图2
通过上图,我们可以看到有几个重点的地方需要注意:
TTL、SOA、NS记录、A资源记录,下来我对这几个方面一一加以解释
(1)TTL 86400:缓存记录保持时间
@ 代表zone的意思,这个档案由 /etc/named.rfc1912.zones 定义出 zone 为example.com,因此在本档案的 @ 就代表 example.com.
(2)SOA资源记录
SOA资源记录为起始授权机构记录,是最重要、最常用的一种资源记录。区域以服务器授权机构的概念为基础。当DNS服务器配置成加载区域时,其使用SOA和NS两种资源记录来确定区域的授权属性。
SOA和NS资源记录在区域配置中具有特殊作用,它们是任何区域都需要的记录并且一般是文件中列出的第一个资源记录。
起始授权机构SOA资源记录总是处于任何标准区域中的第一位。它表示最初创建它的DNS服务器或现在是该区域的主服务器的DNS服务器。它还用于存储会影响区域更新或过期的其他属性,比如版本信息和计时。这些属性会影响在该区域的域名服务器之间进行同步数据的频繁程度
SOA资源记录语法格式:
区域名(当前) 记录类型 SOA 主域名服务器(FQDN) 管理员邮件地址 (序列号 刷新间隔 重试间隔过期间隔 TTL)
SOA :开始授权标志
主域名服务器:区域的主DNS服务器的FQDN,也就linux102.exampl.com
管理员:管理区域的负责人的电子邮件。在该电子邮件名称中使用英文句号“.”代替at符号“@”。这是因为这里的@符号表示的是区域
序列号(serial):该区域文件的修订版本号。每次区域中的资源记录改变时,这个数字便会增加,每次区域改变时增加这个值非常重要,它使部分区域改动或完全修改的区域都可以在后续传输中复制到其他辅助DNS服务器上。
刷新间隔(refresh):以秒计算的时间,辅助DNS服务器请求与源服务器同步的等待时间。当刷新间隔到期时,辅助DNS服务器请求源服务器的SOA记录副本,然后辅助DNS服务器将源服务器的SOA记录的序列号与其本地SOA记录的序列号相比较,如果二者不同,则辅助DNS服务器从主DNS服务器请求区域传输。这个域的默认时间是900秒(15分钟)。
重试间隔(retry):以秒计算时间,辅助DNS服务器在请求区域传输失败后,等待多长时间再次请求区域传输时间。通常,这个时间短于刷新间隔。默认值为600秒(10分钟)。
过期间隔(Expire):以秒计算时间,当这个时间到期时,如果辅助DNS服务器还无法与源服务器进行区域传输,则辅助DNS服务器会把它的本地数据当作不可靠数据。默认值为86400秒(24小时)。
最小(默认)TTL(minimum):区域的默认生存时间(TTL)和缓存否定应答名称查询的最大间隔。默认值为3600秒(1小时)
(3)NS记录
用于指定一个区域的权威DNS服务器,通过在NS资源记录中列出服务器的名字,其他主机就认为它是该区域的权威服务器。这意味着在NS资源记录中指定的任何服务器都被其他服务器当作权威的来源并且能应答区域内所含名称的查询。
语法格式:
区域名 IN NS [完整主机名称]
注意喔, NS 后面接的一定是主机名称!代表的意思是说:‘这个 zone 的查询请向后面这部主机要求’的意思。 所以,如果你这个 zone 有两部以上的 DNS 伺服器负责时,那就最好写上所有的DNS服务器名称!而 NS 后面接的主机名称必需要有 IP 的对应啊!因此就需要 A 这个标志了!如图2所示。(这里区域名就是表示服务器的域名,如果是本机,那么就可以用@来替代,这里@就表示我本机的域名)
注意:
完整主机名后一定要加上“.”不然,默认会再次加上@所定义的后缀(example.com)。比如如果我写成desktop.example.com 没有加“.”则解析出来后,dns服务器的地址为:desktop.example.com.example.com
所以要加上“.“比较合适。当然下面讲述的A记录中就不要加点了,因为其只是写了主机名,并没有写上完整的主机名(带域名)
(4)A资源记录
A资源记录是使用最为频繁的一种,通常用于将指定的主机名称解析为它们对应的IP地址。A:表示正向解析;是正解的符号,意思是说该部主机的 IP 对应之意
A资源记录语法格式:
完整主机名(FQDN) IN A IP地址
www IN A 192.168.1.40 表示将主机www解析成IP地址;
(5)其他一些名称解释
PTR:表示反向解析;
Refresh:刷新时间;辅dns隔多长时间来此刷新记录
Retry:重试时间,辅dns此时间后再与主dns来刷新
expire:放充时间;如隔此时间后仍未联系上,则放弃连接;
minimum:缓存记录保持时间
5.重启named
都配置好后,service named restart 重启服务,在客户机中将/etc/resolv.conf文件中的dns地址指向dns服务器,然后在客户机中进行测试:dig www.example.com,
从图中我们可以看出解析已经成功。
HEADER(标题):显示查询的内容有哪些,包括一个 query, 一个 answer 及两个验证部分。
QUESTION(问题):显示所要查询的内容,因为我们是查询 www.example.com 所以这里自然就是显示这个讯息。
ANSWER(回应):依据刚刚的 QUESTION 去查询所得到的结果,因为在我们的设定当中仅有设定了 A 的标签,所以这里自然就显示这个信息
AUTHORITY(验证):由这里我们可以查阅example.com这个领域是由 linux102.example.com来设定的~里面那个 86400 是什么呢?很简单,他就是我们所设定的 ttl 那个数值啦!
6.反向解析
前文我们提到的都是正向解析的基本命令,那么反向解析呢?其实基本的步骤都是差不多的,只是有几个步骤需要更改下:
首先,我们进入到/var/named/chroot/etc底下,并且编辑
named.rfc1912.zones文件:
在里面加上如图这段文字,然后保存。
下来,我们进入/var/named/chroot/var/named目录,我们ls查看下,发现里面有如图这些文件:
跟前面正向解析一样,复制好dl.local文件后,我们对其进行编辑如图:
我们看到里面有个PTR,这个PTR资源记录与A记录相反,用于查询IP地址与主机名的对应关系。
PTR资源记录语法格式:
IP地址 IN PTR 主机名(FQDN)
反向解析的名词解释基本和前文所述的一样,有个别几个地方需要注意一下:
(1)@ 在正向解析中我们表示的是named.rfc1912.zones文件中关于正向解析的定义:example.com;那么在反向解析中自然也是其文件中关于反向解析的定义:
(2)主机的名称尽量写完整,也就是要记得加上小数点“.”,因为反解的zone是1.168.192.in-addr.arpa,所以如果图中的xxx而没有小数点时,那么则对应的主机就会变成xxx. 1.168.192.in-addr.arpa,这么怪异的名称(这个和正向解析中说的是一样的效果)。如图:
反向解析基本就这些,和正向解析基本是一样的
---------------------------------------------------------
对前面的区域文件和资源记录文件做个总结:
区域文件实际上就是DNS的数据库,而资源记录就是数据库中的数据。这些数据其中包括多种记录类型,比如SOA、NS、A记录等等,这些记录统称为资源记录。如果没有资源记录那么DNS服务器将无法为客户端提供域名解析服务
常用名词解释:
递归查询:进行一次查询就能得到最终结果
迭代查询:需要进行多次查询,才能得到最终结果
互联网上的应用方式一般是:本地递归,互联网部分迭代。
所有DNS都不知道其他DNS在哪里,但都知道根在哪里,本地主机向本地DNS递归,本地DNS出去迭代查询后向本地返回最终结果。
DNS常见的记录类型:
A记录: 由主机名解析IP地址
PTR记录:由IP地址解析主机名
NS记录: 用来指定本地的域名服务器(有主,有辅)
MX记录: 用来指定本地的邮件服务器,MX(邮件交换器)资源记录提供邮件传递信息。该记录会指定区域内的邮件服务器名称。
MX资源记录语法格式:
区域名 IN MX 优先级(数字) 邮件服务器名称(FQDN)
CNAME: 用来指定一个主机的别名例如管理员告知公司的首页为www.abc.com,而实际在访问时访问的是www1.abc.com主机。
该资源记录经常用于在同一区域的A资源记录中的主机需要重命名时或者为多台主机(例如一组WWW服务器)提供相同的别名。
CNAME资源记录语法格式:
别名 IN CNAME 主机名
SOA: 起始授权记录,用来说明本域的主域名服务器!
辅助域名服务器每隔一段时间要去主(或者其他辅助)域名服务器上面查询更新,以保证数据的一致性, 这个过程叫做区域传送,这个过程使用TCP协议,53号端口。为了保证数据的一致性,如果主服务器有更新,也会及时告知从服务器过来同步。
补充知识:
常用的测试命令:host、nslookup、dig等命令
如host:
nslookup:
dig前面已经用过了,这就不例举了,其实一般直接用host来测试比较方便
OK 写到这里,基本上DNS 的一个简单配置就完成了,都是初学者,如有纰漏或者错误,欢迎大家指正。
有机天使