Contar o número de clientes DNS (bind9)?

1

Eu preciso saber o número dos meus clientes de servidor DNS. Provavelmente isso significa IPs únicos por dia, ou algo assim, porque eu acho que não há outra maneira de identificar os clientes de outra maneira. Então, eu preciso saber quantos clientes meu bind9 serve. Como posso conseguir isso da maneira mais simples?

    
por Ivan Petrov 17.04.2015 / 08:56

2 respostas

3

1 - registro de consultas

Habilite o log de consulta rndc querylog e analise seus arquivos de log, assim:

grep -Eo "client ([0-9]{1,3}[\.]){3}[0-9]{1,3}" /path/to/logfile | sort -u | uniq
client 10.0.252.1
client 10.0.231.15
client 127.0.0.1

excluindo duplicatas | uniq e | wc -l para contá-las, mas não se preocupe em encontrar uma solução real que seja realmente precisa e simples.

2 - dnstop

Capturar tráfego:

tcpdump -w dump.pcap -c 10000 port 53

Analise:

dnstop dump.pcap > report.txt

Aqui está o formato de saída ( somente os 50 principais clientes):

% cat report.txt
Sources          Count      %   cum%
------------ --------- ------ ------
10.0.252.1          36   87.8   87.8
10.0.250.100         3    7.3   95.1
10.0.231.15          2    4.9  100.0
[...]

3 - dnstap

Há também dnstap , mas eu não sei muito sobre isso, exceto que é um recurso planejado para o BIND 9.11: link .

Edit: O comando não estava listando todos os IPs, corrigi-lo adicionando sort -u .

Note: 'uniq' does not detect repeated lines unless they are adjacent.

    
por 17.04.2015 / 09:39
1

Fundamentalmente, a maneira mais fácil de obter essas informações é de tcpdump . Eu tenho feito algo semelhante recentemente, mas procurando padrões diferentes. Você pode encontrar algo do que eu fiz para ser útil para você.

link link

Em particular, como descrito em "Capturando e Analisando Amostras de DNS (tcpdump atende SQLite3)", e colocando-o em um banco de dados sqlite3 é útil se você quiser mais tarde fazer outras perguntas, mas não é útil para monitoramento ao vivo. O código para isso pode ser encontrado em link

Instantâneo do código:

#!/bin/bash

sample_size="50000"
interface="eth0"

echo "Capturing sample of $sample_size packets from interface $interface"

tcpdump -w /tmp/query-sample.pcap -i "$interface" -nn -p -c "$sample_size" -s0 dst port domain

rm -f /tmp/query-sample.sqlite3
sqlite3 /tmp/query-sample.sqlite3 'create table queries (count int,client,querytype,queryval);'

tcpdump -r /tmp/query-sample.pcap -nn \
    | sed -rne 's/^[^ ]+ IP ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+ > ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+: .* ([^?]+)\? ([A-Za-z0-9._-]+) .*/  /p' \
    | awk '
        { queryval = $3 }
        queryval ~ /\.noisy-example\.com\.$/ { queryval = "SOMETHING.noisy-example.com." }
        queryval ~ /\.10\.in-addr\.arpa\.$/ { queryval = "SOMETHING.10.in-addr.arpa." }
        queryval ~ /\.67\.45\.123\.in-addr\.arpa\.$/ { queryval = "SOMETHING.67.45.123.in-addr.arpa." }
        queryval ~ /[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\.in-addr\.arpa\.$/ { queryval = "SOMETHING.in-addr.arpa." }
        { print $1,$2,queryval }' \
    | sort | uniq -c \
    | sed -re 's/[ \t]+/|/g' -e 's/^\|//' \
    | sqlite3 /tmp/query-sample.sqlite3 '.import /dev/stdin queries'

echo "
    In this report, Cost is a count of such queries received,
    normalised by the number of clients that queried it. Thus,
    something with a Cost greater than 10 (<= are omitted),
    would likely benefit from DNS caching.

    Some queries, namely inverse lookups and things under
    noisy-domain.com (generally some abuse of DNS) are
    aggregated.

"

sqlite3 /tmp/query-sample.sqlite3 <<EOF
.mode column
.header on

.width 4 7 70
select sum(count)/count(count) as Cost, querytype as RRtype, queryval as Name from queries group by RRtype,Name having Cost > 10 order by Cost desc limit 100;

.width 9 6 15
select sum(count) as NumQueries, querytype as RRtype, client as Client from queries group by Client having NumQueries > 10 order by NumQueries desc limit 100;
EOF

tcpdump -tt -r /tmp/query-sample.pcap -nn \
    | grep '\.53: ' \
    | cut -d. -f1 | uniq -c \
    | awk '
        NR == 1 {starttime = $2; next}
        {total += $1; count += 1; last = $1; lasttime = $2}
        END { total -= last; print "Queries / second = " total / (lasttime - starttime) }'

Para monitoramento ao vivo, você pode usar o tcpdump e processá-lo com uma solução como sed e AWK, Python, Perl, etc. Eu usei sed e AWK recentemente para me ajudar a procurar quem está enviando mais número de solicitações por segundo, que eu, em seguida, resumir com outro para procurar os spikers mais frequentes. Você deve ser capaz de reutilizar a primeira parte, pelo menos (o que eu notei que preciso enviar).

Por fim, convém garantir que, em seus relatórios, você não abuse do seu próprio servidor DNS, chamando dig com frequência. Use 'hosts getent' em vez .

Exemplo:

$ echo -e '1.1.1.1 2\n8.8.8.8 12\n8.8.4.4 25' \
  | awk '
    BEGIN {threshold = 5}
    $2 > threshold {
      "getent hosts " $1 | getline getent_hosts_str;
      split(getent_hosts_str, getent_hosts_arr, " ");
      print $1, getent_hosts_arr[2], $3
    }'
8.8.8.8 google-public-dns-a.google.com
8.8.4.4 google-public-dns-b.google.com

Se você está procurando uma solução contínua em que possa ter um painel de controle, você pode usar o tcpdump e o Python para emitir relatórios resumidos por segundo por cliente (para reduzir os dados) via JSON e empurrar isso para uma pilha ELK. No Kibana 4 você pode fazer com que ele trace a Contagem Única de um atributo (como clientip.raw)

Espero que você tenha muitas ideias úteis.

Felicidades, Cameron

    
por 17.04.2015 / 11:44