isc-dhcp-server的分配的地址列表在哪,linux/树莓派做无线路由器怎么查看已连接设备

时间:2024-04-15 07:35:13

标题问题答案

/var/lib/dhcp/dhcpd.leases,这个文件记录了所有isc-dhcp-server分配的IP地址信息

 

dhcpd.leases文件详解:

# 推荐用 $ man dhcpd.leases 指令 查看详细含义

lease 192.168.8.24 {
  starts 3 2016/05/18 10:48:59; # 分配地址的时间
  ends 3 2016/05/18 10:58:59; # 租约到期时间
  tstp 3 2016/05/18 10:58:59; # 租约到期时间
  cltt 3 2016/05/18 10:49:04; # 客户端最后访问时间
  binding state free; # 租约绑定状态 状态分别是 free 和 active
  hardware ethernet 30:3a:64:50:2d:32; # 客户端mac地址
  uid "\0010:dP-2"; # 客户端识别id
  set vendor-class-identifier = "MSFT 5.0";
}
lease 192.168.8.25 {
  starts 2 2016/06/14 04:23:16;
  ends 2 2016/06/14 04:33:16;
  cltt 2 2016/06/14 04:23:16;
  binding state free;
  next binding state free;
  rewind binding state free;
  hardware ethernet c0:ee:fb:25:82:92;
  client-hostname "android-50efd8d429a1278b"; # 客户端主机名
}
lease 192.168.8.25 {
  starts 2 2016/06/14 04:28:08;
  ends 2 2016/06/14 04:38:08;
  cltt 2 2016/06/14 04:28:08;
  binding state active;
  next binding state free;
  rewind binding state free;
  hardware ethernet c0:ee:fb:25:82:92;
  client-hostname "android-50efd8d429a1278b";
}

 

 

你若对如何找这类文件感兴趣,可以接着往下看v

软件:isc-dhcp-server(以下简称IDS), python flask, hostapd 
平台:debian8 for arm(raspberry pi 树莓派)
硬件:EP-N8508GS USB无线网卡(以下简称为无线网卡),树莓派2B(以下简称PI)

目的:

         学习LINUX,制作一个基于网页端管理的无线路由器(本文主要讲怎么找DHCP的客户端列表)。

         选修课大作业,非常感谢万老师开这门课,让我学到了很多linux的知识。

         主要思路:

      PI以任意方式通过有线网卡连接外网;

      PI通过无线网卡作为Wireless Access Point,用到软件hostapd;

      PI安装isc-dhcp-server作为DHCP服务器分配IPV4地址;

      PI配置IP table使通过AP连接可以访问外网;

      配置网页大部分已经完成,只是做功能补充,添加查看DHCP客户端列表功能。

 

分析:

  DHCP由isc-dhcp-server控制,linux不自带DHCP服务器,所以猜测,DHCP的客户端都是由IDS记录的。

  第一种情况,所有的记录文件直接以文本文件的形式保存,文件命名是isc-dhcp-*,这种方法我们读取查找起来最简单;

  第二种情况,文本文件记录,存放在*/isc-dhcp/*,读取起来和上一种情况类似;

  第三种情况,用了sqlite存储信息,被保存成*.db文件,这是读取起来最麻烦的;

  第四种情况,DHCP客户端信息放在内存中,其他程序无法读取,如果是这样的,那就基本无解了,但是想到世面上的路由器都有查看DHCP客户端的功能,IDS这个软件应该会把这信息记录到本地文件吧。

 

无论是什么情况,首先得把存储信息的文件找出来,执行以下查找文件的指令:

$ sudo find / -name \'isc-dhcp*\' -type f

查找结果:  

pi@raspberrypi:~ $ sudo find / -name \'isc-dhcp*\' -type f
/var/lib/dpkg/info/isc-dhcp-client.conffiles
/var/lib/dpkg/info/isc-dhcp-client.postrm
/var/lib/dpkg/info/isc-dhcp-server.postrm
/var/lib/dpkg/info/isc-dhcp-server.conffiles
/var/lib/dpkg/info/isc-dhcp-server.prerm
/var/lib/dpkg/info/isc-dhcp-server.list
/var/lib/dpkg/info/isc-dhcp-server.config
/var/lib/dpkg/info/isc-dhcp-client.md5sums
/var/lib/dpkg/info/isc-dhcp-server.templates
/var/lib/dpkg/info/isc-dhcp-server.postinst
/var/lib/dpkg/info/isc-dhcp-common.list
/var/lib/dpkg/info/isc-dhcp-client.list
/var/lib/dpkg/info/isc-dhcp-server.md5sums
/var/lib/dpkg/info/isc-dhcp-client.postinst
/var/lib/dpkg/info/isc-dhcp-client.preinst
/var/lib/dpkg/info/isc-dhcp-common.md5sums
/run/systemd/generator.late/isc-dhcp-server.service

看到’isc-dhcp-client.list’这个文件,欣喜若狂,莫非就这么被我找到了,查看了一下结果…

pi@raspberrypi:/var/lib/dpkg/info $ cat isc-dhcp-client.list 
/.
/var
/var/lib
/var/lib/dhcp
/sbin
/sbin/dhclient-script
/sbin/dhclient
/etc
/etc/dhcp
/etc/dhcp/dhclient.conf
/etc/dhcp/dhclient-exit-hooks.d
/etc/dhcp/dhclient-exit-hooks.d/debug
/etc/dhcp/dhclient-exit-hooks.d/rfc3442-classless-routes
/etc/dhcp/dhclient-enter-hooks.d
/etc/dhcp/dhclient-enter-hooks.d/debug
/usr
/usr/share
/usr/share/doc
/usr/share/doc/isc-dhcp-client
/usr/share/doc/isc-dhcp-client/copyright
/usr/share/doc/isc-dhcp-client/changelog.Debian.gz
/usr/share/doc/isc-dhcp-client/NEWS.Debian.gz
/usr/share/man
/usr/share/man/man5
/usr/share/man/man5/dhclient.conf.5.gz
/usr/share/man/man5/dhclient.leases.5.gz
/usr/share/man/man8
/usr/share/man/man8/dhclient-script.8.gz
/usr/share/man/man8/dhclient.8.gz

继续,当查看到isc-dhcp-client.postrm这个文件时,渐渐开始明朗了起来,红色的语句,应该就是初始化dhcp服务时,需要删除的文件,那么就是本次dhcp服务的记录文件,接下来就是查看这些文件。

pi@raspberrypi:/var/lib/dpkg/info $ cat isc-dhcp-client.postrm 
#!/bin/sh -e
#
#

if [ "$1" = "purge" ]; then
    # Remove lease database
    rm -f /var/lib/dhcp/dhclient*.leases
    rm -f /var/lib/dhcp/dhclient*.lease

    # Try to remove directory
    if [ -d /var/lib/dhcp ]; then
        rmdir --ignore-fail-on-non-empty /var/lib/dhcp/
    fi

    rmdir --ignore-fail-on-non-empty /etc/dhcp

fi

转到 /var/lib/dhcp/ 可以看到有这样一个文件,翻译过来是dh客户端.租约,猜想应该就是这个文件了:

pi@raspberrypi:/var/lib/dhcp $ ls -la dhclient*.leases 
-rw-r--r-- 1 root root 0 Mar 18 08:08 dhclient.leases
pi@raspberrypi:/var/lib/dhcp $ cat dhclient.leases 
pi@raspberrypi:/var/lib/dhcp $ 

查看了一下 空欢喜,什么都没有,

那就看看这个路径还有些什么文件:

pi@raspberrypi:/var/lib/dhcp $ ls -la
total 20
drwxr-xr-x  2 root root 4096 Jun 14 16:16 .
drwxr-xr-x 47 root root 4096 May 18 10:32 ..
-rw-r--r--  1 root root    0 Mar 18 08:08 dhclient.leases
-rw-r--r--  1 root root 5535 Jun 14 16:50 dhcpd.leases
-rw-r--r--  1 root root 3015 Jun 14 16:16 dhcpd.leases~

文件数量不多,逐个查看,dhcpd.leases这个文件,没错就是他 运气不错,记录了DHCP客户端的连接日志:

pi@raspberrypi:/var/lib/dhcp $ cat dhcpd.leases
# The format of this file is documented in the dhcpd.leases(5) manual page.
# This lease file was written by isc-dhcp-4.3.1

lease 192.168.8.22 {
  starts 1 2016/06/14 16:55:13;
  ends 2 2016/06/14 17:05:13;
  cltt 2 2016/06/14 16:55:13;
  binding state active;
  next binding state free;
  rewind binding state free;
  hardware ethernet 0c:1d:af:e3:ab:e0;
  client-hostname "android-33afb4dbee873a4b";
}

# The format of this file is documented in the dhcpd.leases(5) manual page.

第一句注释说,这个格式在dhcpd.leases(5)的用户手册,用户手册中记录了每个项的详细含义

$ man dhcpd.leases

这是我们需要用到的内容

lease 192.168.8.22 {
  starts 1 2016/06/14 16:55:13; # 租约开始时间
  ends 2 2016/06/14 17:05:13; # 租约结束时间
  cltt 2 2016/06/14 16:55:13;  # 客户端最后访问时间
  binding state active; # 绑定状态
  next binding state free;
  rewind binding state free;
  hardware ethernet 0c:1d:af:e3:ab:e0; # 客户端mac地址
  client-hostname "android-33afb4dbee873a4b"; # 客户端主机名
}

接下来就是在python中写获取这些内容的方法,源代码如下:

def getDhcpClientMap():
    dhcp_client_filepath = "/var/lib/dhcp/dhcpd.leases"
    #dhcp_client_filepath = "dhcpd.leases"
    # 打开文件
    dhcp_client_file = open(dhcp_client_filepath)
    # 创建list用于存放
    dhcpClientList = {}
    rline = dhcp_client_file.readline()
    while(rline):
    #     检查地址位置
        pos192 = rline.find(\'192.168\')
        if(pos192 >= 0):
    #         如果找到 创建对象
            posdkh = rline.find(\'{\')
            rIpAddr = rline[pos192:posdkh - 1]
            rstartTime = \'\'
            rendTime = \'\'
            rBindState = \'\'
            rMacAddr = \'\'
            rHostName = \'\'
    # 查找其他内容
            while(True):
                rline = dhcp_client_file.readline()
                if(rline.find(\'}\') >= 0):
                    break;
                if(rline.find(\'starts\') >= 0):
                    rstartTime = rline[rline.find(\'starts\') + 9:].replace(\';\n\', \'\')
                    continue;
                if(rline.find(\'ends\') >= 0):
                    rendTime = rline[rline.find(\'ends\') + 7:].replace(\';\n\', \'\')
                    continue;
                if(rline.find(\'  binding state\') >= 0):
                    rBindState = rline[rline.find(\'  binding state\') + 15:].replace(\';\n\', \'\').replace(\' \', \'\') 
                    continue;
                if(rline.find(\'hardware ethernet\') >= 0):
                    rMacAddr = rline[rline.find(\'hardware ethernet\') + 17:].replace(\';\n\', \'\').replace(\' \', \'\') 
                    continue;
                if(rline.find(\'client-hostname\') >= 0):
                    rHostName = rline[rline.find(\'client-hostname\') + 15:].replace(\';\n\', \'\').replace(\' \', \'\').replace(\'"\', \'\') 
                    continue;
            dxbDhcpClient = {}
            dxbDhcpClient[\'ipAddr\'] = rIpAddr
            dxbDhcpClient[\'satrtTime\'] = rstartTime
            dxbDhcpClient[\'endTime\'] = rendTime
            dxbDhcpClient[\'bindState\'] = rBindState
            dxbDhcpClient[\'macAddr\'] = rMacAddr
            dxbDhcpClient[\'hostName\'] = rHostName
    #         添加到存放的list
            dhcpClientList[rMacAddr] = dxbDhcpClient
    # 接着下一个循环
        rline = dhcp_client_file.readline()
    return dhcpClientList
View Code

把状态为active 的设备放入到一个list中,供前端显示:

# 清除非连接状态的客户端
def clearDhcpClientFreeAndToList(dhcpClientMap):
    for tk in dhcpClientMap.keys():
        if(dhcpClientMap[tk]["bindState"] == \'free\'):
            dhcpClientMap.pop(tk)
    changeList = []
    for tk in dhcpClientMap.keys():
        changeList.append(dhcpClientMap[tk])
    return changeList
View Code

控制器方法源代码如下:

@app.route("/wirelessClientList")
def dhcpClientPage():
    # 获取DHCP客户端列表方法
    deviceList = clearDhcpClientFreeAndToList(getDhcpClientMap())
    print deviceList
    return render_template(\'dhcpclient.html\', dlist=deviceList)
View Code

页面中遍历(for endfor)获取到的客户端代码如下:

{% for dev in dlist %}
      <tr>
          <td>{{dev.hostName}}</td>
          <td>{{dev.ipAddr}}</td>
          <td>{{dev.macAddr}}</td>
          <td>{{dev.satrtTime}}</td>
          <td>{{dev.endTime}}</td>
      </tr>
{% endfor %}
View Code