DNS and BIND 配置指南

前言

    说来接触Linux也有一年了,BIND是我曾经学习RH系Linux接触的第一个服务,对我有着莫大的意义,当初差点因为这个服务难以配置而放弃Linux,今天学完马哥的bind相关系列视频之后,写一篇DNS and BIND的基础到进阶。

一、DNS的基础知识

  1. DNS是什么?

    DNS(Domain Name System)是Internet发展多年以来最重要的服务之一,它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用TCP和UDP端口53

  2. 域名解析

    简单来说,DNS就像是一个通讯录,AnyISalIn的电话是1829888****,有了通讯录,我们只需通过输入AnyISalIn这个名字就能够自动拨打其电话。DNS主要是用来定义IP地址和域名的关系。

  3. DNS资源记录类型

    SOA:起始授权记录,一个区域的解析库中有且只能有一条SOA记录,必须为解析库中的第一条记录,定义主DNS服务器地址和相关事件时间定义。

    A:实现FQDN ==> IP 

    MX:标明提供邮件服务的主机

    NS:标明当前域内的DNS服务器

    AAAA:FQDN ==> IPv6

    CNAME:Canonical Name,别名记录

    PTR:IP ==> FQDN

  4. DNS解析答案类型

    肯定答案:正确解析了请求的内容

    否定答案:请求的条目不存在等原因无法返回结果

    权威答案:通过迭代的方式从所查询域名的所在域的DNS服务器返回的结果

    非权威答案:请求的DNS服务器缓存的结果

  5. DNS资源记录定义方法

    A记录:IP IN  A Value ; 示例:192.168.1.1 IN A www.anyisalin.com.

    NS记录:domain IN NS Value; 示例:anyisalin.com. IN  NS ns1.anyisalin.com. #一条NS记录必须要有一条与之对应的A记录

    MX记录:domain IN NS priority Value; 示例:anyisalin.com. IN  MX 10 mail1.anyisalin.com. #一条MX记录必须要有与之对应的A记录, 优先级0-99,越低优先级越高

    PTR记录:IP.in-addr.arpa. IN PTR Value; 示例:1.1.168.192.in-addr.arpa. IN PTR www.anyisalin.com. #PTR记录的写法比较诡异,我们在后面进行叙述

    AAAA记录:和A记录相似,只是将IPv4地址换为IPv6

二、DNS的结构

blob.png

    上图为当今Internet中的DNS的结构,最多可分达127层,朋友们别看上图中的www.anyisalin.com.和ns.anyisalin.com.相距很近,其实他们可能各自在天南地北。DNS的各层只是逻辑上的关系,不存在物理上的界定 。

    在DNS各域中只包含其子域的信息,例如 "."域中的解析库只包含全球所有顶级域对对应的NS服务器的信息、 并且不知道父域的位置,例如:www.anyisalin.com. 不知道anyisalin.com.的具体位置(NS服务器的IP)

    

主从DNS:

    一个域的DNS一般情况下都有两个,主DNS提供解析库中信息,从DNS进行"区域传送"来同步其解析库,来达到负载均衡和高可用的效果。区域传送分为全量传送和增量传送,相信大家应该能够见名思意,这里不做过多叙述。

    

DNS解析过程:

    DNS查询分别有两种方式,"迭代"和"递归"。

        递归:DNS客户端使用的DNS服务器一般都是递归服务器,负责全权处理客户端的查询请求直至返回结果

        迭代:DNS服务器之间的查询方式,从根服务器开始向下级查询

        blob.png

三、BIND安装和基础配置

    前面我们介绍了DNS的一些基础知识,但是DNS是一种模型,需要使用软件去实现。BIND(Berkeley Internet Name Domain)就是一伴随着DNS出生到现在的软件,本文使用bind9.8。

  1. 安装bind

[root@localhost ~]# yum install -y bind bind-utils     
Loaded plugins: fastestmirror, security
Setting up Install Process
Loading mirror speeds from cached hostfile
 * base: mirrors.opencas.cn
 * extras: mirrors.pubyun.com
 * updates: mirrors.163.com
updates                                                                                                                                                               | 3.4 kB     00:00     
Package 32:bind-utils-9.8.2-0.37.rc1.el6_7.7.x86_64 already installed and latest version
Resolving Dependencies
--> Running transaction check
---> Package bind.x86_64 32:9.8.2-0.37.rc1.el6_7.7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
=============================================================================================================================================================================================
 Package                                Arch                                     Version                                                     Repository                                 Size
=============================================================================================================================================================================================
Installing:
 bind                                   x86_64                                   32:9.8.2-0.37.rc1.el6_7.7                                   updates                                   4.0 M
Transaction Summary
=============================================================================================================================================================================================
Install       1 Package(s)
Total download size: 4.0 M
Installed size: 7.3 M
Downloading Packages:
bind-9.8.2-0.37.rc1.el6_7.7.x86_64.rpm                                                                                                                                | 4.0 MB     00:03     
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing : 32:bind-9.8.2-0.37.rc1.el6_7.7.x86_64                                                                                                                                     1/1 
  Verifying  : 32:bind-9.8.2-0.37.rc1.el6_7.7.x86_64                                                                                                                                     1/1 
Installed:
  bind.x86_64 32:9.8.2-0.37.rc1.el6_7.7                                                                                                                                                      
Complete!

查看生成的关键文件

[root@localhost ~]# rpm -ql bind
/etc/NetworkManager/dispatcher.d/13-named
/etc/logrotate.d/named
/etc/named    
/etc/named.conf    #bind主配置文件
/etc/named.iscdlv.key
/etc/named.rfc1912.zones    #定义zone的文件
/etc/named.root.key
/etc/portreserve/named
/etc/rc.d/init.d/named    #bind脚本文件
/etc/rndc.conf    #rndc配置文件
/etc/rndc.key
/etc/sysconfig/named
/usr/lib64/bind
/usr/sbin/arpaname
/usr/sbin/ddns-confgen
/usr/sbin/dnssec-dsfromkey
/usr/sbin/dnssec-keyfromlabel
/usr/sbin/dnssec-keygen
/usr/sbin/dnssec-revoke
/usr/sbin/dnssec-settime
/usr/sbin/dnssec-signzone
/usr/sbin/genrandom
/usr/sbin/isc-hmac-fixup
/usr/sbin/lwresd
/usr/sbin/named
/usr/sbin/named-checkconf    #检测/etc/named.conf文件语法
/usr/sbin/named-checkzone    #检测zone和对应zone文件的语法
/usr/sbin/named-compilezone
/usr/sbin/named-journalprint
/usr/sbin/nsec3hash
/usr/sbin/rndc    #远程dns管理工具
/usr/sbin/rndc-confgen    #生成rndc密钥

#过长省略

/var/log/named.log
/var/named
/var/named/data
/var/named/dynamic
/var/named/named.ca    #根解析库
/var/named/named.empty
/var/named/named.localhost    #本地主机解析库
/var/named/named.loopback    
/var/named/slaves    #从文件夹
/var/run/named
[root@localhost ~]# rpm -ql bind-utils    #bind-utils包主要提供了一些检测工具
/usr/bin/dig    
/usr/bin/host    
/usr/bin/nslookup   
/usr/bin/nsupdate
/usr/share/man/man1/dig.1.gz
/usr/share/man/man1/host.1.gz
/usr/share/man/man1/nslookup.1.gz
/usr/share/man/man1/nsupdate.1.gz

手动创建bind主配置文件

[root@localhost etc]# vim named.conf    #不熟悉的可以直接通过修改原始的配置文件
options {
  directory "/var/named";
 
  };    
zone "." IN {
  type hint;
  file "named.ca";
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

定义一个zone

[root@localhost etc]# cat >> /etc/named.rfc1912.zones << EOF    #这里使用Here Document,不懂得可以搜素
> zone "anyisalin.com" IN {            #定义区域为anyisalin.com
>    type master;                    #设置类型为master
>    file "anyisalin.com.zone";        #解析库文件名称为anyisalin.com.zone
> };
> EOF

创建区域解析库文件

[root@localhost etc]# vim /var/named/anyisalin.com.zone 
$TTL 600    #定义全局默认超时时间
$ORIGIN anyisalin.com.    #定义后缀
@   IN  SOA    ns1.anyisalin.com.  admin.anyisalin.com. (
                20160321    #序列号
                1H    #刷新时间
                5M    #重试时间
                1W    #超时时间
                10M )    #否定答案缓存TTL值
        IN      NS      ns1
ns1     IN      A       192.168.192.150
        IN      MX 10   mail1
mail1   IN      A       192.168.192.1
www     IN      A       192.168.192.2
cname   IN      CNAME   www                #别名, 将cname.anyisalin.com. 解析到 www.anyisalin.com.的地址
*       IN      A       192.168.2.1    #泛域名解析,以上都不是的解析到192.168.2.1

检查、启动并测试

[root@localhost etc]# named-checkconf     #检查主配置文件语法
[root@localhost etc]# named-checkzone "anyisalin.com" /var/named/anyisalin.com.zone     #检查anyisalin.com zone所对应的解析库文件
zone anyisalin.com/IN: loaded serial 20160321
OK
[root@localhost etc]# service named start
Starting named:                                            [  OK  ]

解析域名

[root@localhost etc]# host -t A www.anyisalin.com 192.168.192.150    #解析www.anyisalin.com 对应的主机IP
Using domain server:
Name: 192.168.192.150
Address: 192.168.192.150#53
Aliases: 
www.anyisalin.com has address 192.168.192.2        #得出ip为192.168.192.2
[root@localhost etc]# host -t NS anyisalin.com 192.168.192.150    #查询anyisalin.com域内的NS记录
Using domain server:
Name: 192.168.192.150
Address: 192.168.192.150#53
Aliases: 
anyisalin.com name server ns1.anyisalin.com.    #ns1.anyisalin.com. 为其dns服务器

四、区域传送和子域授权

    上面我们已经讲过,一个域内的DNS服务器一般都需要两个,我们这里就进行主从配置和区域传送

在从服务器安装bind并创建bind主配置文件

[root@localhost etc]# vim named.conf    #不熟悉的可以直接通过修改原始的配置文件
options {
  directory "/var/named";
 
  };    
zone "." IN {
  type hint;
  file "named.ca";
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

定义zone

[root@localhost named]# cat >> /etc/named.rfc1912.zones <<EOF        #这里定义方式和主服务器的配置略有不同
> zone "anyisalin.com" IN {
>   type slave;
>   masters { 192.168.192.150; };    #定义主服务器的IP地址
>   file "slaves/anyisalin.com.zone";    #定义传送文件的存放位置,必须要和源文件相同
>  };
> EOF

在主服务器的解析库中添加一条NS记录指向从服务器的地址

[root@localhost etc]# vim /var/named/anyisalin.com.zone     #在主服务上执行!!!
$TTL 600
$ORIGIN anyisalin.com.
@   IN	SOA    ns1.anyisalin.com.  admin.anyisalin.com. (
		20160321
		1H
		5M
		1W
		10M )

	IN	NS	ns1
        IN      NS  ns2                #添加ns2记录
ns1	IN	A	192.168.192.150
ns2     IN     A   192.168.192.147        #添加ns2对应的A记录
	IN	MX 10 	mail1
mail1	IN	A	192.168.192.1
www	IN	A	192.168.192.2
cname	IN	CNAME	www
*	IN	A	192.168.2.1


[root@localhost etc]# rndc reload    #重载配置文件
server reload successful

启动bind服务

从下面的动态图可以看传送过程

若水GIF截图_2016年3月21日18点18分46秒.gif

增量传送, #增量传送需要修改序列号!

若水GIF截图_2016年3月21日18点26分49秒.gif

子域授权

在主dns服务器添加两条记录

vim /var/named/anyisalin.com.zone
$TTL 600
$ORIGIN anyisalin.com.
@   IN  SOA    ns1.anyisalin.com.  admin.anyisalin.com. (
                20160324
                1H
                5M
                1W
                10M )
        IN      NS      ns1
        IN      NS      ns2
ns1     IN      A       192.168.192.150
ns2     IN     A   192.168.192.147
        IN      MX 10   mail1
mail1   IN      A       192.168.192.1
www     IN      A       192.168.192.2
cname   IN      CNAME   www
*       IN      A       192.168.2.1
new     IN      A       192.168.1.1
ops     IN      NS      ns1.ops        #添加一条NS记录将ops.anyisalin.com. 域授权给ns1.ops.anyisalin.com.进行管理
ns1.ops IN      NS      192.168.192.151    #对应上条的NS记录的A记录

在ns1.ops.anyisalin.com.主机上进行配置

vim /etc/named.conf        #配置bind主配置文件
options {
  directory "/var/named";
  };    
zone "." IN {
  type hint;
  file "named.ca";
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

[root@localhost ~]# cat >> /etc/named.rfc1912.zones <<EOF    #定义zone
> zone "ops.anyisalin.com" IN {
>    type master;
>    file "ops.anyisalin.com.zone";
> };
> EOF
[root@localhost named]# cat ops.anyisalin.com.zone     #定义解析库
$TTL 600
$ORIGIN ops.anyisalin.com.
@	IN	SOA	ns1.ops.anyisalin.com.	admin.ops.anyisalin.com. (
		20160321
		1H
		5M
		7D
		1H
)


	IN	NS	ns1
ns1	IN	A	192.168.192.151
www	IN	A	192.168.1.1

测试

[root@localhost named]# service named start
Starting named:                                            [  OK  ]

通过本机解析本域主机名
[root@localhost named]# host -t A www.ops.anyisalin.com 192.168.192.151
Using domain server:
Name: 192.168.192.151
Address: 192.168.192.151#53
Aliases: 
www.ops.anyisalin.com has address 192.168.1.1

通过父域DNS解析本域下的主机名

[root@localhost named]# host -t A www.ops.anyisalin.com 192.168.192.150
Using domain server:
Name: 192.168.192.150
Address: 192.168.192.150#53
Aliases: 

www.ops.anyisalin.com has address 192.168.2.1

通过本机DNS解析父域中的主机名
[root@localhost named]# host -t A www.anyisalin.com 192.168.192.151
;; connection timed out; trying next origin
Using domain server:
Name: 192.168.192.151
Address: 192.168.192.151#53
Aliases: 

Host www.anyisalin.com not found: 3(NXDOMAIN)

但是我们可能会发现一个问题,如果我需要解析父域中的主机名,只能通过递归到根域去解析,这是非常不便的,所以我们要设置转发器。

[root@localhost named]# cat >> /etc/named.rfc1912.zones <<EOF    #定义转发器
> zone "anyisalin.com" IN {
>     type forward;
>     forward  only ;
>     forwarders { 192.168.192.150; };
> };
> EOF

重载、测试

[root@localhost named]# rndc reload    #重载配置文件
server reload successful
[root@localhost named]# host -t A www.anyisalin.com 192.168.192.151    #使用本机进行解析
Using domain server:
Name: 192.168.192.151
Address: 192.168.192.151#53
Aliases: 
www.anyisalin.com has address 192.168.192.2    #现在能够得出结果

五、BIND视图实现智能DNS

    大家都知道,中国的运营商之间的带宽是非常低,但是无论我们是哪个运营商的宽带,访问那些大型电商站点都是非常的快,那是因为在dns服务器中定义了来自哪些IP的请求解析成哪些地址,这就是视图的功能。

    

配置视图:

1、一旦启动了view, 所有的zone都只能在view中定义
2、仅有必要在匹配到允许递归请求的客户所在view定义根区域
3、客户端请求到达, 是自上而下检查每个view所服务器的客户端列表

[root@localhost etc]# vim /etc/named.conf    #修改主配置文件
acl mynet {

        192.168.192.150;
        127.0.0.0/8;
};

acl other {
        192.168.192.1;
};




options {
  directory "/var/named";

   dnssec-enable no;
   dnssec-validation no;

  };   
view "." {
match-clients { mynet; };
zone "." IN {
  type hint;
  file "named.ca";
};
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

vim /etc/named.rfc.1912.zones    #配置主配置文件
view mynet {    
 match-clients { mynet; };

zone "localhost.localdomain" IN {
	type master;
	file "named.localhost";
	allow-update { none; };
};

zone "localhost" IN {
	type master;
	file "named.localhost";
	allow-update { none; };
};

zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" IN {
	type master;
	file "named.loopback";
	allow-update { none; };
};

zone "1.0.0.127.in-addr.arpa" IN {
	type master;
	file "named.loopback";
	allow-update { none; };
};

zone "0.in-addr.arpa" IN {
	type master;
	file "named.empty";
	allow-update { none; };
};

zone "anyisalin.com" IN {
   type master;
   file "anyisalin.com.zone";
};
};

view other {
 match-clients { other; };
zone "anyisalin.com" IN {
  type master;
  file "anyisalin.com.other";
};
};

验证

blob.png

blob.png

六、bind编译安装和安全配置

编译安装相关博客==> 教你使用rpm、yum、编译等方式安装软件

我们通过isc.org下载bind9.9.5的安装包

yum groupinstall "Development Tools" "Server Platform Development" --nogpgcheck    #安装开发环境
tar xf bind-9.9.5.tar.gz #解压源码包

cd bind-9.9.5

./configure --prefix=/usr/local/bind9 --sysconfdir=/etc/named/ --disable-ipv6 --disable-chroot --enable-threads    #配置config文件

useradd -u 53 named -r ; groupadd -g 53 named -r     #创建named用户和组

make && make install     #编译和配置

export PATH=/usr/local/bin9/bin:/usr/local/bin9/sbin:$PATH    #将bind的执行路径加入PATH中
source /etc/bashrc    #重读bash配置文件

echo "/usr/local/bind9/lib" > /etc/ld.so.conf.d/bind.conf    #导入库文件路径

echo "MANPATH /usr/local/bind9/share/man" >> /etc/man.config    #导入manual文件路径


新建主配置文件

vim /etc/named/named.conf
options {
  directory "/var/named";
  
  };    
zone "." IN {
  type hint;
  file "named.ca";
};

zone "localhost" IN {
    type master;
    file "localhost.zone";
    };

zone "0.0.127.in-addr.arpa {
    type master;
    file "name.local";
    };


[root@localhost bind9]# /usr/local/bind9/sbin/named-checkconf     #检查配置文件,提示没有文件夹
/etc/named/named.conf:2: change directory to '/var/named' failed: file not fou
nd
/etc/named/named.conf:2: parsing failed
[root@localhost bind9]# mkdir /var/named    #创建/var/named
[root@localhost bind9]# /usr/local/bind9/sbin/named-checkconf    #检测通过


手动创建zone文件
[root@localhost bind9]# cd /var/named/

[root@localhost named]# dig -t NS . @192.168.1.1    #通过dig命令获取根服务器地址

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6 <<>> -t NS . @192.168.1.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43106
;; flags: qr rd ra; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;.				IN	NS

;; ANSWER SECTION:
.			12787	IN	NS	m.root-servers.net.
.			12787	IN	NS	d.root-servers.net.
.			12787	IN	NS	i.root-servers.net.
.			12787	IN	NS	k.root-servers.net.
.			12787	IN	NS	a.root-servers.net.
.			12787	IN	NS	e.root-servers.net.
.			12787	IN	NS	c.root-servers.net.
.			12787	IN	NS	b.root-servers.net.
.			12787	IN	NS	h.root-servers.net.
.			12787	IN	NS	g.root-servers.net.
.			12787	IN	NS	f.root-servers.net.
.			12787	IN	NS	l.root-servers.net.
.			12787	IN	NS	j.root-servers.net.

;; Query time: 78 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Mon Mar 21 19:29:53 2016
;; MSG SIZE  rcvd: 228

[root@localhost named]# dig -t NS . @192.168.1.1 > named.ca    #将根服务器解析库重定向到named.ca文件中


创建localhost.zone文件

[root@localhost named]# vim localhost.zone
$TTL 600
@       IN      SOA     localhost. admin.localhost. (
        20160321
        1H
        5M
        7D
        1H
)

                IN      NS      localhost.
localhost.      IN      A       127.0.0.1

创建named.local文件
$TTL 600
@       IN      SOA     localhost. admin.localhost. (
        20160321
        1H
        5M
        7D
        1H
)

                IN      NS      localhost.
1               IN      PTR     localhost.


修改属主和权限

[root@localhost named]# chown root:named /var/named/ -R 
[root@localhost named]# chmod 770 /var/named/ -R
[root@localhost named]# chown root:named /etc/named/ -R


运行bind程序
[root@localhost bind9]# /usr/local/bind9/sbin/named -u named

查看监听端口
[root@localhost ~]# ss -unlp | grep 53
UNCONN     0      0           192.168.192.152:53                       *:*      users:(("named",
6949,513))UNCONN     0      0                 127.0.0.1:53                       *:*      users:(("named",
6949,512)

bind安全配置:

    

访问控制命令:
allow-query {}; 允许查询的主机, 白名单
allow-transfer {}; 允许区域传送主机, 白名单
allow-recursion {}; 允许递归的主机
allow-update {}; 允许更新区域数据库中的内容

allow-query 测试:

blob.png

blob.png

blob.png

allow-transfer测试:

blob.png

blob.png

blob.png

总结

    还有很多没有写,本文写了大概5小时,前面还行,后面有些偷工减料,总的来说还行,理论的东西不多。

    参考资料:wiki百科,马哥Linux 2016视频,相关笔记,百度图库

    欢迎大家加我QQ交流:1449472454

原创文章,作者:Net18-AnyISalIn,如若转载,请注明出处:http://www.178linux.com/13071

(0)
Net18-AnyISalInNet18-AnyISalIn
上一篇 2016-03-20
下一篇 2016-03-22

相关推荐

  • 第六周作业

    一、Vim编辑器练习: 用Vim编辑器做下面的练习,我的Linux系统(CentOS 6.9)安装了精简版系统,没有Vim编辑器。 a、设置Yum源为网易开源镜像站。 b、选择对应“镜像名”,到对应的“CentOS使用说明”里面查看内容 c、看着CentOS说明操作就可以了 d、使用说明 首先备份/etc/yum.repos.d/CentOS-Base.re…

    Linux干货 2017-08-22
  • 双网卡绑定及单网卡多IP地址实现方法

    Bonding就是将多块网卡绑定同一IP地址对外提供服务,可以实现高可用或者负载均衡。当然,直接给两块网卡设置同一IP地址是不可能的。通过bonding,虚拟一块网卡对外提供连接,物理网卡的被修改为相同的MAC地址。mode=1(active-backup):一个网卡处于活动状态 ,一个处于备份状态,所有流量都在主链路上处理。当活动网卡down掉时,启用备份…

    Linux干货 2016-09-05
  • Linux基础(四)——用户管理&grep命令

    1、  复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限。 cp /etc/skel/ /home/tuser1 –r chmod -R 700 /home/tuser1/ 2、  编辑/etc/group文件,添加组hadoop。 echo "ha…

    Linux干货 2016-11-08
  • 集中练习6-bash脚本

    集中练习6-bash脚本

    Linux干货 2017-12-05
  • 用户和组及批量创建

    用户和组       操作系统都有用户和组,windows,linux等等,用户和组用来做什么呢?       用户,是我们进入系统时的凭证,不是每一个人想进就进的。你想吧,如果操作系统没有用户就能登录进系统,那这就带来了许许多多的安全隐患了。而组则是为了方便管理用户的一个组容器。 &nb…

    系统运维 2016-08-04
  • 分享 (History,Ls,感悟 )

    1.History 选项   -c: 清空命令历史   -d offset: 删除历史中指定的第offset个命令    n: 显示最近的n条历史   -a: 追加本次会话新执行的命令历史列表至历史文件   -n: 读历史文件中未读过的行到历史列表   -r: 读历史文件附加到历史列表 &…

    2017-07-15