Comment afficher les baux DHCP actifs

27

Pas expérimenté avec Ubuntu. Configurez un serveur DHCP il y a environ un an, mais ne vous souvenez pas de la commande pour voir les baux actifs.

Keith
la source

Réponses:

27

Essayez de vérifier le fichier de bail /var/lib/dhcp/dhcpd.leases

Squall5668
la source
23

Notre organisation utilise un script Python, comme indiqué ci-dessous, pour examiner le /var/lib/dhcp/dhcpd.leasesfichier:

#!/usr/bin/python
import datetime, bisect

def parse_timestamp(raw_str):
        tokens = raw_str.split()

        if len(tokens) == 1:
                if tokens[0].lower() == 'never':
                        return 'never';

                else:
                        raise Exception('Parse error in timestamp')

        elif len(tokens) == 3:
                return datetime.datetime.strptime(' '.join(tokens[1:]),
                        '%Y/%m/%d %H:%M:%S')

        else:
                raise Exception('Parse error in timestamp')


def timestamp_is_ge(t1, t2):
        if t1 == 'never':
                return True

        elif t2 == 'never':
                return False

        else:
                return t1 >= t2


def timestamp_is_lt(t1, t2):
        if t1 == 'never':
                return False

        elif t2 == 'never':
                return t1 != 'never'

        else:
                return t1 < t2


def timestamp_is_between(t, tstart, tend):
        return timestamp_is_ge(t, tstart) and timestamp_is_lt(t, tend)


def parse_hardware(raw_str):
        tokens = raw_str.split()

        if len(tokens) == 2:
                return tokens[1]

        else:
                raise Exception('Parse error in hardware')


def strip_endquotes(raw_str):
        return raw_str.strip('"')


def identity(raw_str):
        return raw_str


def parse_binding_state(raw_str):
        tokens = raw_str.split()

        if len(tokens) == 2:
                return tokens[1]

        else:
                raise Exception('Parse error in binding state')


def parse_next_binding_state(raw_str):
        tokens = raw_str.split()

        if len(tokens) == 3:
                return tokens[2]

        else:
                raise Exception('Parse error in next binding state')


def parse_rewind_binding_state(raw_str):
        tokens = raw_str.split()

        if len(tokens) == 3:
                return tokens[2]

        else:
                raise Exception('Parse error in next binding state')


def parse_leases_file(leases_file):
        valid_keys = {
                'starts':               parse_timestamp,
                'ends':                 parse_timestamp,
                'tstp':                 parse_timestamp,
                'tsfp':                 parse_timestamp,
                'atsfp':                parse_timestamp,
                'cltt':                 parse_timestamp,
                'hardware':             parse_hardware,
                'binding':              parse_binding_state,
                'next':                 parse_next_binding_state,
                'rewind':               parse_rewind_binding_state,
                'uid':                  strip_endquotes,
                'client-hostname':      strip_endquotes,
                'option':               identity,
                'set':                  identity,
                'on':                   identity,
                'abandoned':            None,
                'bootp':                None,
                'reserved':             None,
                }

        leases_db = {}

        lease_rec = {}
        in_lease = False
        in_failover = False

        for line in leases_file:
                if line.lstrip().startswith('#'):
                        continue

                tokens = line.split()

                if len(tokens) == 0:
                        continue

                key = tokens[0].lower()

                if key == 'lease':
                        if not in_lease:
                                ip_address = tokens[1]

                                lease_rec = {'ip_address' : ip_address}
                                in_lease = True

                        else:
                                raise Exception('Parse error in leases file')

                elif key == 'failover':
                        in_failover = True
                elif key == '}':
                        if in_lease:
                                for k in valid_keys:
                                        if callable(valid_keys[k]):
                                                lease_rec[k] = lease_rec.get(k, '')
                                        else:
                                                lease_rec[k] = False

                                ip_address = lease_rec['ip_address']

                                if ip_address in leases_db:
                                        leases_db[ip_address].insert(0, lease_rec)

                                else:
                                        leases_db[ip_address] = [lease_rec]

                                lease_rec = {}
                                in_lease = False

                        elif in_failover:
                                in_failover = False
                                continue
                        else:
                                raise Exception('Parse error in leases file')

                elif key in valid_keys:
                        if in_lease:
                                value = line[(line.index(key) + len(key)):]
                                value = value.strip().rstrip(';').rstrip()

                                if callable(valid_keys[key]):
                                        lease_rec[key] = valid_keys[key](value)
                                else:
                                        lease_rec[key] = True

                        else:
                                raise Exception('Parse error in leases file')

                else:
                        if in_lease:
                                raise Exception('Parse error in leases file')

        if in_lease:
                raise Exception('Parse error in leases file')

        return leases_db


def round_timedelta(tdelta):
        return datetime.timedelta(tdelta.days,
                tdelta.seconds + (0 if tdelta.microseconds < 500000 else 1))


def timestamp_now():
        n = datetime.datetime.utcnow()
        return datetime.datetime(n.year, n.month, n.day, n.hour, n.minute,
                n.second + (0 if n.microsecond < 500000 else 1))


def lease_is_active(lease_rec, as_of_ts):
        return timestamp_is_between(as_of_ts, lease_rec['starts'],
                lease_rec['ends'])


def ipv4_to_int(ipv4_addr):
        parts = ipv4_addr.split('.')
        return (int(parts[0]) << 24) + (int(parts[1]) << 16) + \
                (int(parts[2]) << 8) + int(parts[3])


def select_active_leases(leases_db, as_of_ts):
        retarray = []
        sortedarray = []

        for ip_address in leases_db:
                lease_rec = leases_db[ip_address][0]

                if lease_is_active(lease_rec, as_of_ts):
                        ip_as_int = ipv4_to_int(ip_address)
                        insertpos = bisect.bisect(sortedarray, ip_as_int)
                        sortedarray.insert(insertpos, ip_as_int)
                        retarray.insert(insertpos, lease_rec)

        return retarray


##############################################################################


myfile = open('/var/lib/dhcp/dhcpd.leases', 'r')
leases = parse_leases_file(myfile)
myfile.close()

now = timestamp_now()
report_dataset = select_active_leases(leases, now)

print('+------------------------------------------------------------------------------')
print('| DHCPD ACTIVE LEASES REPORT')
print('+-----------------+-------------------+----------------------+-----------------')
print('| IP Address      | MAC Address       | Expires (days,H:M:S) | Client Hostname ')
print('+-----------------+-------------------+----------------------+-----------------')

for lease in report_dataset:
        print('| ' + format(lease['ip_address'], '<15') + ' | ' + \
                format(lease['hardware'], '<17') + ' | ' + \
                format(str((lease['ends'] - now) if lease['ends'] != 'never' else 'never'), '>20') + ' | ' + \
                lease['client-hostname'])

print('+-----------------+-------------------+----------------------+-----------------')
print('| Total Active Leases: ' + str(len(report_dataset)))
print('| Report generated (UTC): ' + str(now))
print('+------------------------------------------------------------------------------')
Canadian Luke REINSTATE MONICA
la source
J'aime cela, car il filtre les baux expirés précédemment (contrairement à l'affichage de /var/lib/dhcp/dhcpd.leases). Merci d'avoir partagé.
Wireblue
3
Pas de problème, dites à vos amis
Canadian Luke REINSTATE MONICA
Merci Luke. J'ai partagé un lien vers cette page sur la page Facebook WelcomeToLinux.
LinuxGuru
7

Si vous utilisez NetworkManager (qui est par défaut dans de nombreuses distributions), le .lease fichiers se trouvent dans/var/lib/NetworkManager

$ sudo ls -al /var/lib/NetworkManager/*.lease
-rw-r--r-- 1 root root 399 Jun 12 10:23 /var/lib/NetworkManager/dhclient-6aef9d76-0f6a-46e3-8235-a4405a695b1a-eth0.lease
-rw-r--r-- 1 root root 856 Jun 12 10:30 /var/lib/NetworkManager/dhclient-86e97e19-0a11-4606-8edf-5a179ec6f82e-eth0.lease
-rw-r--r-- 1 root root 800 Jun 12 10:30 /var/lib/NetworkManager/dhclient-d0f4b29f-3059-4f55-a8d2-34db34310384-wlan0.lease
Taha Jahangir
la source
Je ne sais pas si cela est dû à Desktop vs Server ou à un changement de version, mais c'est l'emplacement correct pour Ubuntu Desktop 14.04, il n'était pas dans /var/lib/dhcp/dhcpd.leases comme d'autres réponses l'ont suggéré.
Elijah Lynn
4

Voici une excellente commande utilisant CLI - Vous pouvez aller dans le répertoire où dhcpd.logse trouve le fichier et faire:

tail -f dhcpd.log

Cela vous montrera les baux lorsqu'ils sont émis par le serveur en temps réel.

Vous pouvez également faire:

cat /var/lib/dhcpd/dhcpd.leases pour voir les baux qui se trouvent dans le dossier de location dhcpd.leases

P. Scott
la source
4

J'utilise ce script:

#!/usr/bin/perl

my $VERSION=0.03;

my $leases_file = "/var/lib/dhcp/dhcpd.leases";

use strict;
use Date::Parse;

my $now = time;
my %seen;       # leases file has dupes (because logging failover stuff?). This hash will get rid of them.


open(L, $leases_file) or die "Cant open $leases_file : $!\n";
undef $/;
my @records = split /^lease\s+([\d\.]+)\s*\{/m, <L>;
shift @records; # remove stuff before first "lease" block

## process 2 array elements at a time: ip and data
foreach my $i (0 .. $#records) {
    next if $i % 2;
    my $ip;
    ($ip, $_) = @records[$i, $i+1];

    s/^\n+//;     # && warn "leading spaces removed\n";
    s/[\s\}]+$//; # && warn "trailing junk removed\n";

    my ($s) = /^\s* starts \s+ \d+ \s+ (.*?);/xm;
    my ($e) = /^\s* ends   \s+ \d+ \s+ (.*?);/xm;

    my $start = str2time($s);
    my $end   = str2time($e);

    my %h; # to hold values we want

    foreach my $rx ('binding', 'hardware', 'client-hostname') {
        my ($val) = /^\s*$rx.*?(\S+);/sm;
        $h{$rx} = $val;
    }

    my $formatted_output;

    if ($end && $end < $now) {
        $formatted_output =
            sprintf "%-15s : %-26s "              . "%19s "         . "%9s "     . "%24s    "              . "%24s\n",
                    $ip,     $h{'client-hostname'}, ""              , $h{binding}, "expired"               , scalar(localtime $end);
    }
    else {
        $formatted_output =
            sprintf "%-15s : %-26s "              . "%19s "         . "%9s "     . "%24s -- "              . "%24s\n",
                    $ip,     $h{'client-hostname'}, "($h{hardware})", $h{binding}, scalar(localtime $start), scalar(localtime $end);
    }

    next if $seen{$formatted_output};
    $seen{$formatted_output}++;
    print $formatted_output;
}

Vous voudrez peut-être l'adapter à vos besoins.

Il existe également des modules Perl que vous voudrez peut-être essayer si vous avez une vague notion de Perl: Net :: ISC :: DHCPd :: Leases , POE :: Filter :: DHCPd :: Lease ou Text :: DHCPLeases .

Le dernier peut être installé avec

sudo apt-get install libtext-dhcpleases-perl

Les autres avec cpan -i.

Malheureusement, je n'ai essayé aucun d'entre eux, car j'avais déjà mon script quand je les ai remarqués.

mivk
la source
Je voulais essayer votre script Perl mais j'ai eu une erreur. Impossible d'utiliser global $ _ dans "mon" à ./bin/ShowDhcpLeases.pl ligne 22, près de ", $ _"
LinuxGuru
@LinuxGuru: Ce n'est qu'un avertissement, et le script fonctionne toujours (du moins pour moi). Mais de toute façon, je l'ai changé pour supprimer cet avertissement.
mivk
0

Si vous voulez quelque chose dans une interface graphique, jetez un œil à Glass . Il fonctionne comme une application Web et donne accès à votre fichier de configuration DHCPd, ainsi qu'aux baux. Il utilise des graphiques et des statistiques, qui sont utiles si vous avez plusieurs sous-réseaux ou pools.

J'aime aussi que cela m'alerte si l'activité semble désactivée - les appareils ne reçoivent pas les adresses en masse, ou trop de demandes de clients uniques. Je l'utilise depuis un mois maintenant et je l'adore.

Canadian Luke REINSTATE MONICA
la source