할당 된 DHCP 주소를 나열하는 명령


21

dhcpd 서버에 어떤 주소가 할당되었는지 묻는 데 사용할 수있는 명령이 있습니까?

답변:


21

아니오,이 정보 서버 측은 DHCP 서버에서만 얻을 수 있습니다. 이 정보는 /var/lib/dhcpd/dhcpd.leasesISC의 DHCP 서버를 사용하는 경우 DHCP 서버의 .lease 파일 : 에 포함되어 있습니다.

$ more /var/lib/dhcpd/dhcpd.leases
# All times in this file are in UTC (GMT), not your local timezone.   This is
# not a bug, so please don't ask about it.   There is no portable way to
# store leases in the local timezone, so please don't request this as a
# feature.   If this is inconvenient or confusing to you, we sincerely
# apologize.   Seriously, though - don't ask.
# The format of this file is documented in the dhcpd.leases(5) manual page.
# This lease file was written by isc-dhcp-V3.0.5-RedHat

lease 192.168.1.100 {
  starts 4 2011/09/22 20:27:28;
  ends 1 2011/09/26 20:27:28;
  tstp 1 2011/09/26 20:27:28;
  binding state free;
  hardware ethernet 00:1b:77:93:a1:69;
  uid "\001\000\033w\223\241i";
}
...
...

3
우분투에서 경로는 없다 /var/lib/dhcp/dhcpd.leases(즉, 더 d처음의 끝에서 dhcp...)
알렉시스 WILKE

20

isc-dhcpd패키지 버전 4.3.1에는 다음 명령이 임대를 나열합니다.

dhcp-lease-list --lease PATH_TO_LEASE_FILE

이전 DHCP 릴리스도 지원하는 간단한 perl 스크립트 스크립트입니다. 데비안 소스 코드공식 DHCP 배포판 ( contrib/)에서도 사본을 볼 수 있습니다 .

출력은 예쁘다 :

$ perl contrib/dhcp-lease-list.pl --lease /var/db/dhcpd/dhcpd.leases
To get manufacturer names please download http://standards.ieee.org/regauth/oui/oui.txt to /usr/local/etc/oui.txt
MAC                IP              hostname       valid until         manufacturer
===============================================================================================
90:27:e4:f9:9d:d7  192.168.0.182   iMac-de-mac    2015-12-12 01:37:06 -NA-
d8:a2:5e:94:40:81  192.168.0.178   foo-2          2015-12-12 01:04:56 -NA-
e8:9a:8f:6e:0f:60  192.168.0.127   angela         2015-12-11 23:55:32 -NA-
ec:55:f9:c5:f2:55  192.168.0.179   angela         2015-12-11 23:54:56 -NA-
f0:4f:7c:3f:9e:dc  192.168.0.183   kindle-1234567 2015-12-11 23:54:31 -NA-
f4:ec:38:e2:f9:67  192.168.0.185   -NA-           2015-12-11 23:55:40 -NA-
f8:d1:11:b7:5a:62  192.168.0.184   -NA-           2015-12-11 23:57:34 -NA-

oui.txt제안대로 파일 을 다운로드하면 더 좋지만 다음 패치를 적용하지 않으면 출력이 깨질 수 있습니다.

--- dhcp-lease-list.pl.orig     2015-12-12 12:30:00.000000000 -0500
+++ dhcp-lease-list.pl  2015-12-12 12:54:31.000000000 -0500
@@ -41,7 +41,7 @@
     if (defined $oui) {
        $manu = join('-', ($_[0] =~ /^(..):(..):(..):/));
        $manu = `grep -i '$manu' $oui | cut -f3`;
-       chomp($manu);
+       $manu =~ s/^\s+|\s+$//g;
     }

     return $manu;
@@ -142,7 +142,7 @@
     }
     foreach (@leases) {
        if ($opt_format eq 'human') {
-          printf("%-19s%-16s%-15s%-20s%-20s\n",
+          printf("%-19s%-16s%-14.14s %-20s%-20s\n",
                  $_->{'mac'},       # MAC
                  $_->{'ip'},        # IP address
                  $_->{'hostname'},  # hostname

이 패치는 ISC- 버그 # 41288로 업스트림에 제출되었으며 검토를 기다리고 있습니다.


8

egrep 명령을 사용하여 출력을 얻을 수 있습니다.

egrep "lease|hostname|hardware|\}" /var/lib/dhcpd/dhcpd.leases

산출:

lease 192.168.11.10 {
  hardware ethernet 20:6a:8a:55:19:0a;
  client-hostname "Maryam-PC";
}
lease 192.168.11.7 {
  hardware ethernet 00:16:ea:51:d3:12;
  client-hostname "parsoon";
}
lease 192.168.11.3 {
  hardware ethernet 00:17:c4:3f:84:e3;
  client-hostname "zahra-ubuntu";
}
lease 192.168.11.5 {
  hardware ethernet 58:b0:35:f1:31:2f;
}

4

위의 답변의 대부분은 부분적입니다. 솔직히 간단한 해결책은 없습니다. 1) dhcpd.leases 데이터베이스 파일을 구문 분석하고 활성 임대에 대한 정보를 얻을 수 있지만 다음과 같은 행으로 지정된 FIXED 주소에 대한 정보는 얻을 수 없습니다.

host switch1      { hardware ethernet a1:b2:c3:d7:2f:bc ; fixed-address switch1.mydomain.com; }

그리고 이것은 또한 dhcp ack이 머신에 마지막으로 전송 된 시간에 대한 정보를 실제로 제공하지 않습니다.

2) 반면에 dhcpd.log 파일을 구문 분석하여 ack 라인을 검색 할 수 있습니다 (이것은 다음과 같습니다).

2017-03-12T08:44:52.421114+01:00, Linuxx, info, dhcpd: DHCPREQUEST for 10.0.0.63 from 68:ab:35:59:9c:a1 via 10.0.0.1 
2017-03-12T08:44:52.421174+01:00, Linuxx, info, dhcpd: DHCPACK on 10.0.0.63 to 68:ab:35:59:9c:a1 via 10.0.0.1

그러나 당신이 정말로해야 할 일은 둘 다하는 것입니다. 먼저 로그 파일을 구문 분석 한 다음 dhcpd.leases 파일에서 얻은 정보로 데이터베이스를리스 시작 엔드 등과 같은 누락 된 정보로 파일을 업데이트하십시오.

이제 FIXED와 dynamic 모두의 모든 활성 임대로 HTML 테이블을 만드는 솔루션을 만들 때까지 평일 2 일 내내 게임을했습니다. 다음은 cgi-bin 폴더 또는 어디에나 배치 할 수있는 코드입니다.

#!/usr/bin/perl
#####################################################################################
# list dhcpd active leases 
#   - both "fixed" addresses which are normally not placed into leases database
#   - and dynamically given leases which are present in leases DB
# working for isc-dhcpd-server service but should also work for other compatible
# dhcpd servers. 
# produces HTML or CSV list of leases
#
# written by Marcin Gosiewski, BV Grupa s.c. Poland <marcin@gosiewski.pl>
# based on portions of code by Jason Antman <jason@jasonantman.com> 
#
# to make it work change the $logfilename and $leasedbname below and modify
# the regexp in second part of code (see below) to match your log lines format
# also you can optionally turn off reverse dns lookup (see below) which speeds up the process 
# of table creation and is useless unless you have reverse dns populated for 
# your fixed or dynamic leases
#
# CHANGELOG:
#     2017-03-13: initial version
use Socket;
use strict;
use warnings;
no warnings 'uninitialized';

# adjust this to match your files location: both log file and leases
# database. We use 2 last log files from logrotate, but you can add as many as you want
my @logfilenames = ( "/var/log/LOCALAPP.dhcpd.log.1", "/var/log/LOCALAPP.dhcpd.log" );
my $leasedbname = "/var/lib/dhcp/dhcpd.leases";
my %data = ();
# optional, can be modified to produce local time
use Time::Local;
use POSIX 'strftime';
my $now = time();
# local variables, lease information stored here
my $ip=""; 
my $status=""; 
my $interface=""; 
my $sdate="";         # beginning of lease
my $stime=""; 
my $edate="";         # end of lease
my $etime=""; 
my $adate="";         # last update (ACK) sent to requesting server
my $atime="";
my $mac=""; 
my $hostname="";
my $dnsname="";       # reverse dns lookup for host

#######################################################################
# first gather data from logfile for all ACK actions
#######################################################################

# collect all lines from log files into memory...
my @lines = (); my @loglines=(); 
foreach my $logfilename (@logfilenames)
{
  open LOGFILE, '<', $logfilename;
  chomp(@loglines = <LOGFILE>);
  #printf "LINES1: " . scalar @loglines . " in " .$logfilename . "\n";
  push(@lines, @loglines);
  close(LOGFILE);
}
@loglines=();
#printf "TOTAL LINES: " . scalar @lines . "\n";
foreach my $line (@lines)
{
  if ( $line !~ m/dhcpd: DHCPACK/) { next;}
  #printf "LINE: $line\n";

  ###############################
  # Modify the following line to make regexp capture 6 groups from log line:
  # 1 - date
  # 2 - time
  # 3 - ip 
  # 4 - mac
  # 5 - hostname if available
  # 6 - interface
  #$line =~ m/(^.{10})T(.{8}).+,\ dhcpd: DHCPACK on (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) to ((?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2}.*) via (.+)/;
  $line =~m/(^.{10})T(.{8}).+,\ dhcpd: DHCPACK on (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) to ((?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2}) (.*)via (.+)/;
  # process the input
  $adate="$1";
  $atime="$2";
  $ip="$3";
  $mac="$4";
  $hostname="$5";
  $interface="$6";
  #add some 'known' facts:
  $status="ACK";
  $sdate="";    #"FOREVER";
  $stime="";
  $edate="";
  $etime="";

  #create/update record for this mac_addr
  #you can add extra check here if the IP address is not duplicated within
  #ack history and choose only the newer one. 

  $data{"$mac"}->{'ip'} = "$ip";
  $data{"$mac"}->{'status'} = "$status";
  $data{"$mac"}->{'interface'} = "$interface";
  $data{"$mac"}->{'adate'} = "$adate";
  $data{"$mac"}->{'atime'} = "$atime";
  $data{"$mac"}->{'sdate'} = "$sdate";
  $data{"$mac"}->{'stime'} = "$stime";
  $data{"$mac"}->{'edate'} = "$edate";
  $data{"$mac"}->{'etime'} = "$etime";
  $data{"$mac"}->{'mac'} = "$mac";
  $data{"$mac"}->{'hostname'} = "$hostname";
}
#close(LOGFILE);

#######################################################################
# gather data from lease database for dynamic addresses
# update the records (for existing) or add new records
#######################################################################

my $isdata = 0;
my $type = "";

#this information is not present in leases database so we just set
#it to default values
$interface="dhcpd";
$status="ACTIVE";
$adate="-";
$atime="";

open LEASEDB, $leasedbname or die $!;
foreach my $line (<LEASEDB>) 
{
  chomp($line);
  $isdata = 1 if $line =~ /^lease /;
  $isdata = 0 if $line =~ /^}/;

  if ($isdata) 
  {
    if ($line =~ /^lease/) 
    {
      $ip = (split(" ", $line))[1];
    } 
    elsif ($line =~ /^  starts/) 
    {
      ($sdate, $stime) = (split(" ", $line))[2,3];
      $sdate =~ s/\//-/g;
      $stime =~ s/;//;
    } 
    elsif ($line =~ /^  ends/) 
    {
      ($type, $edate, $etime) = (split(" ", $line))[1,2,3];
      if($type eq "never;")
      {
        $edate="forever";
        $etime=" ";
      }
      else
      {
        $edate =~ s/\//-/g;
        $etime =~ s/;//;
      }
    } 
    elsif ($line =~ /^  hardware ethernet/) 
    {
            $mac = (split(" ", $line))[2];
            $mac =~ s/;//;
    } 
    elsif ($line =~ /^  client-hostname/) 
    {
            $hostname = (split(/\"/, $line))[1];
    }
    elsif($mac ne "") 
    {
        #we have parsed the whole record, no more matching entries
        #data is collected to variables. now push the record.

        #now let's decide if we are updating the record or creating
        #new record

        # check against lease date, do not add expired leases
        # convert lease end time to local time/date and compare with $now
        my $y=0; my $m=0; my $d=0; my $H=0; my $M=0; my $S=0;
        my $edatetime = $now;
        ($y, $m, $d) = split("-", $edate);
        ($H, $M, $S) = split(":", $etime);
        $edatetime = timelocal($S,$M,$H,$d,$m-1,$y);
        if($edatetime >= $now)
        {
          # now check if record exists
          if(!defined($data{"$mac"}->{'mac'}))
          {
            #record does not exist, fill up default data
            $data{"$mac"}->{'mac'} = "$mac";
            $data{"$mac"}->{'interface'} = "$interface";
            $data{"$mac"}->{'ip'} = "$ip";
            $data{"$mac"}->{'hostname'} = "$hostname";
          }
          # record exists, let's check if we should update
          $data{"$mac"}->{'status'} = "$status";
          $data{"$mac"}->{'sdate'} = "$sdate";
          $data{"$mac"}->{'stime'} = "$stime";
          $data{"$mac"}->{'edate'} = "$edate";
          $data{"$mac"}->{'etime'} = "$etime";
          $data{"$mac"}->{'hostname'} = "$hostname";
          #we do NOT update ACK time because we do not have it
          #do NOT uncomment below
          #$data{"$mac"}->{'adate'} = "$adate";
          #$data{"$mac"}->{'atime'} = "$atime";

        }
    }
  }
}
close(LEASEDB);

#######################################################################
# sort data
#######################################################################

#we sort by IP but you can sort by anything.
my @sorted = sort { ($data{$a}{'ip'}) cmp ($data{$b}{'ip'}) } %data;

#######################################################################
# Print out everything to the HTML table
#######################################################################

my $hostnamelong="";

printf "Content-type: text/html\n\n";
printf "<html><head><title>Aktywne dzierzawy DHCP</title></head>\n";
printf "<style> table, th, td { border: 1px solid lightgray; border-collapse: collapse; padding: 3px; } ";
printf "tr:nth-child(even) { background-color: #dddddd; } ";
printf "</style>\n";
printf "<body>\n";
printf "<table border='1' cellpadding='6'>\n";
printf "<tr><th>IP</th><th>Status</th><th>Interface</th><th>Lease time</th><th>ACK time</th><th>Mac</th><th>Host</th></tr>\n";
foreach my $key (@sorted) {
    if($data{$key}{'mac'} eq "") { next ; }

    # BEGIN reverse dns lookup
    # can optionally turn off reverse dns lookup (comment out below lines) which speeds up the process 
    # of table creation and is useless unless you have reverse dns populated for 
    # your fixed or dynamic leases uncomment single line below instead:
    #
    # version without reverse dns lookup:
    # $hostnamelong = $data{$key}{'hostname'};
    #
    # version with reverse dns lookup: 
    # BEGIN
    $dnsname = gethostbyaddr(inet_aton($data{$key}{'ip'}), AF_INET);
    if($data{$key}{'hostname'} ne "")
    {
      $hostnamelong = $data{$key}{'hostname'} . " | " . $dnsname;
    }
    else
    {
      $hostnamelong = $dnsname;
    }
    $dnsname = "";
    # END

    printf "<tr>";
    printf "<td>" . $data{$key}{'ip'} ."</td>";
    printf "<td>" . $data{$key}{'status'} ."</td>";
    printf "<td>" . $data{$key}{'interface'} ."</td>";
    printf "<td>" . $data{$key}{'sdate'} . " " . $data{$key}{'stime'} ." - ";
    printf $data{$key}{'edate'} . " " . $data{$key}{'etime'} ."</td>";
    printf "<td>" . $data{$key}{'adate'} . " " . $data{$key}{'atime'} . "</td>";
    printf "<td>" . $data{$key}{'mac'} ."</td>";
    printf "<td>" . $hostnamelong ."</td>";
    printf "</tr>\n";
}

printf "</table>\n";
printf "</body></html>\n";

# END of programm

1) 위 스크립트는 환경에서 실행하기 전에 약간의 수정이 필요하며 로그 파일 형식에 따라 파일 위치와 하나의 정규식을 수정해야합니다. 스크립트의 주석을 참조하십시오. 2) 위의 스크립트는 마지막 날에 두 개의 다른 시스템이 동일한 주소를 얻은 경우 ACK 테이블에서 IP가 반복되지 않는지 확인하지 않습니다. 이것은 의도적으로 설계된 것입니다 (마지막 날 네트워크에 존재했던 각 mac 주소를 보는 데 개인적으로 필요했습니다)-쉽게 수정할 수 있으며 코드에 준비된 섹션이 있으며 조건 하나만 추가하면됩니다.

너가 좋아하길 바래.


1

임대 파일의 형식이 변경되었거나를 사용할 때 적어도 다릅니다 dhcpcd5. wlan0WiFi 네트워크 에 대한 임대를 보려면 MyNetwork이 파일 (또는 이와 유사한 파일)을 봐야합니다 /var/lib/dhcpcd5/dhcpcd-wlan0-MyNetwork.lease.

이 파일은 이진 파일입니다. (왜? 모르겠다. 어쩌면 귀중한 CPU 사이클을 파싱 할 때 저장해야합니까? Blech.)이를 보려면 dhcpcd --dumpleaseSTDIN에서 바이너리를 구문 분석하고 사람이 읽을 수있는 버전을 출력하는을 사용하십시오.

cat /var/lib/dhcpcd5/dhcpcd-wlan0-MyNetwork.lease | dhcpcd --dumplease

반면에 현재리스가 할당 된 것이 무엇인지 확인하려면 wlan0간단히 다음을 수행하십시오.

dhcpcd --dumplease wlan0

1

나는 이것을 얻기 위해 실제로 bash에 무언가를 썼다. 모든 IP 주소를 동일한 이름 파일에 기록하므로 다른 파일이 다시 나타나면 이전 파일을 덮어 쓰므로 중복이 없습니다. 또한 oui.txt를 사용하여 해당 MAC 주소의 제조업체를 찾습니다.

사용할 수 있는지 확인하십시오.

#!/bin/bash

pid=$$

while read i
do
        echo $i | egrep -qi '^lease|hardware|starts|ends|hostname' || continue
        if [[ $i =~ [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]; then
                ip=$(echo $i | awk '{print $2}')
                printf "IP Address: " > /root/$ip.$pid
                echo $ip >> /root/$ip.$pid
        elif [[ $i =~ starts ]]; then
                printf "\tLease start: " >> /root/$ip.$pid
                echo $i | awk '{print $3,$4}' | tr -d ';' >> /root/$ip.$pid
        elif [[ $i =~ ends ]]; then
                printf "\tLease ends: " >> /root/$ip.$pid
                echo $i | awk '{print $3,$4}' | tr -d ';' >> /root/$ip.$pid
        elif [[ $i =~ ethernet ]]; then
                mac=$(echo -n $i | awk '{print $3}' | tr -d ';')
                oui=$(echo -n $mac | tr ':' '-' | cut -c1-8)

                printf "\tMAC Address: " >> /root/$ip.$pid
                echo $mac >> /root/$ip.$pid
                printf "\tManufacturer: " >> /root/$ip.$pid
                grep -i $oui /usr/share/hwdata/oui.txt | awk '{print $3,$4,$5,$6}' >> /root/$ip.$pid
                printf "\n" >> /root/$ip.$pid
        elif [[ $i =~ hostname ]]; then
                printf "\tHostname: " >> /root/$ip.$pid
                echo $i | awk '{print $2}' | tr -d ';' >> /root/$ip.$pid
        fi

done < /var/lib/dhcpd/dhcpd.leases

cat /root/*.$pid
echo "Total leased: $(ls -l /root/*.$pid | wc -l)"
rm -rf /root/*.$pid
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.