我需要知道我的 DNS 服务器客户端数量。可能意味着每天的唯一 IP 或其他什么,因为我认为没有其他方法可以识别客户端。因此,我需要知道我的 bind9 服务了多少个客户端。我怎样才能以最简单的方式实现这一点?
答案1
1 - 查询日志记录
启用查询日志记录rndc querylog
并解析您的日志文件,如下所示:
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
排除重复项| uniq
并| wc -l
对其进行计数,但不介意找到真正准确且简单的实际解决方案。
2 - dnstop
捕获流量:
tcpdump -w dump.pcap -c 10000 port 53
解析一下:
dnstop dump.pcap > report.txt
输出格式如下(仅限前 50 名客户):
% 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
还有dnstap
,但我对此了解不多,只知道这是 BIND 9.11 计划的功能:https://la51.icann.org/en/schedule/mon-tech/presentation-isc-bind-13oct14-en.pdf。
编辑:该命令没有列出所有 IP,我通过添加来解决这个问题sort -u
。
注意:'uniq' 不会检测重复的行,除非它们相邻。
答案2
从根本上讲,获取这些信息的最简单方法是从tcpdump
。我最近自己也在做类似的事情,但寻找不同的模式。您可能会发现我所做的一些事情对您有用。
http://distracted-it.blogspot.co.nz/search/label/dns http://distracted-it.blogspot.co.nz/2014/07/capturing-and-analysing-dns-samples.html
具体来说,如“捕获和分析 DNS 样本(tcpdump 与 SQLite3 相遇)”中所述,如果您以后想进一步询问问题,将其放入 sqlite3 数据库中很有用,但对于实时监控则无用。相关代码可在以下位置找到https://github.com/cameronkerrnz/scriptorium/blob/master/dns-query-sample
代码快照:
#!/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._-]+) .*/\1 \3 \4/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) }'
对于实时监控,您可能希望使用 tcpdump,然后使用 sed 和 AWK、Python、Perl 等解决方案对其进行处理。我最近使用 sed 和 AWK 来帮助我查找每秒发送请求数最多的人,然后我将其与另一个人汇总以查找最频繁的峰值。您至少应该能够重新利用第一部分(我刚刚注意到我需要上传)。
最后,您要确保在报告中不要通过过于频繁地调用 dig 来滥用您自己的 DNS 服务器。改用“getent hosts”。
例子:
$ 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
如果您正在寻找一个可以在其上安装仪表板的持续解决方案,那么您可以使用 tcpdump 和 Python 通过 JSON 发出每个客户端的每秒汇总报告(以减少数据量)并将其推送到 ELK 堆栈。在 Kibana 4 中,您可以拥有它,然后绘制属性的唯一计数(例如 clientip.raw)
希望这能给你带来许多有用的想法。
干杯,卡梅伦