广告位

云服务器安装qq本地DNS缓存实战(dnsmasq SQLite 简易统计)

频道: 日期: 浏览:0

安全云查看服务器

一、前言

在内网部署本地 DNS 缓存能加速域名解析、减小外网 DNS 请求量并便于统计常访问域名。本文给出最简单、可落地的方案:在一台 Raspberry Pi / 小型服务器上用 dnsmasq 做 DNS 缓存并开启查询日志,然后用一个 小巧的 Python 脚本 将日志解析写入 SQLite 做统计(比如按域名计数、查看 TOPN)。适合家庭、小型办公室、实验环境。全程命令可复制粘贴。

二、适用场景

局域网加速域名解析(一个局域网 DNS 缓存)统计内网最常访问的域名(排查流量或广告域)在无法或不想使用外部 Pi-Hole/云服务时做轻量替代

三、环境与依赖

一台运行 Debian/Ubuntu / Raspberry Pi OS 的机器(例如:192.168.1.10)安装软件:dnsmasq, sqlite3, python3(系统常自带)

sudo apt update

sudo apt install -y dnsmasq sqlite3 python3

四、dnsmasq 快速配置(缓存 + 日志)

编辑或新建/etc/dnsmasq.d/local-cache.conf,内容如下(注:示例使用 53 端口的默认配置):

/etc/dnsmasq.d/local-cache.conf

缓存大小(条目数)

cache-size=1000

启用查询日志并写入独立日志文件

log-queries

log-facility=/var/log/dnsmasq.log

可选:对某些域做自定义解析(示例)

address=/internal.example.local/192.168.1.5

保存后重启 dnsmasq:

sudo systemctl restart dnsmasq

sudo systemctl status dnsmasq

确保日志文件存在并可写:

sudo touch /var/log/dnsmasq.log

sudo chown dnsmasq:adm /var/log/dnsmasq.log

sudo chmod 640 /var/log/dnsmasq.log

(可选)如果系统使用 systemd-journald + rsyslog,log-facility 会把日志写到指定文件,便于后续解析。

五、在客户端指向本地 DNS(示例)

把局域网内客户端的 DNS 设置为 Pi 的 IP(例如 192.168.1.10)。可以在路由器 DHCP 中设置,或在单台机器上手动设置:

Linux 示例(临时)

sudo nmcli dev show | grep DNS 查看

sudo nmcli connection modify ipv4.dns "192.168.1.10"

sudo nmcli connection up

测试解析:

dig @192.168.1.10 www.google.com +short

六、简单的日志解析与写入 SQLite(脚本)

把下面脚本保存为/opt/dns_cache/dns_log_to_sqlite.py 并赋可执行权限。脚本功能:增量读取 /var/log/dnsmasq.log,统计每个查询的域名出现次数并写入 SQLite 表 domain_stats(保留最新计数和上次出现时间)。

!/usr/bin/env python3

/opt/dns_cache/dns_log_to_sqlite.py

import os, sqlite3, re, time

LOG_FILE = "/var/log/dnsmasq.log"

DB_FILE = "/opt/dns_cache/dns_queries.db"

OFFSET_FILE = "/opt/dns_cache/.offset"

匹配 dnsmasq 查询行中的域名(常见格式)

示例日志行:

Jan 01 12:00:00 dnsmasq[1234]: query[A] www.example.com from 192.168.1.20

RE = re.compile(rquery[[AIPV4a-zA-Z]*]s+([^s]+)s+from)

def init():

os.makedirs(os.path.dirname(DB_FILE), exist_ok=True)

conn = sqlite3.connect(DB_FILE)

c = conn.cursor()

c.execute(

CREATE TABLE IF NOT EXISTS domain_stats (

domain TEXT PRIMARY KEY,

count INTEGER,

last_ts INTEGER

云服务器提供上行

))

conn.commit()

conn.close()

ensure offset file exists

if not os.path.exists(OFFSET_FILE):

with open(OFFSET_FILE, w) as f:

f.write("0")

def read_offset():

try:

with open(OFFSET_FILE,r) as f:

return int(f.read().strip())

except:

return 0

架设云打印服务器

def write_offset(v):

with open(OFFSET_FILE,w) as f:

f.write(str(v))

def process():

if not os.path.exists(LOG_FILE):

print("log not found:", LOG_FILE); return

off = read_offset()

size = os.path.getsize(LOG_FILE)

if size < off:

off = 0 log rotated

conn = sqlite3.connect(DB_FILE)

c = conn.cursor()

with open(LOG_FILE,r,errors=ignore) as fh:

fh.seek(off)

for line in fh:

m = RE.search(line)

if not m:

continue

domain = m.group(1).lower().rstrip(.)

ts = int(time.time())

upsert

c.execute(SELECT count FROM domain_stats WHERE domain=?, (domain,))

row = c.fetchone()

if row:

c.execute(UPDATE domain_stats SET count = count + 1, last_ts = ? WHERE domain = ?, (ts, domain))

else:

c.execute(INSERT INTO domain_stats(domain, count, last_ts) VALUES (?,?,?), (domain, 1, ts))

new_off = fh.tell()

conn.commit()

conn.close()

write_offset(new_off)

if __name__ == "__main__":

init()

process()

赋权限并创建目录:

sudo mkdir -p /opt/dns_cache

sudo chown $(whoami):$(whoami) /opt/dns_cache

sudo chmod 750 /opt/dns_cache

sudo chmod +x /opt/dns_cache/dns_log_to_sqlite.py

七、定时执行(cron)

把解析脚本放到 cron 定时运行(例如每分钟),以便近实时统计:

crontab -e

添加一行(每分钟运行)

* * * * * /usr/bin/python3 /opt/dns_cache/dns_log_to_sqlite.py >/dev/null 2>&1

八、查看统计结果(示例)

用 sqlite3 查询 TOP 20 访问域名:

sqlite3 /opt/dns_cache/dns_queries.db "SELECT domain, count, datetime(last_ts,unixepoch,localtime) FROM domain_stats ORDER BY count DESC LIMIT 20;"

快速查看某个域名的计数:

sqlite3 /opt/dns_cache/dns_queries.db "SELECT count FROM domain_stats WHERE domain=www.example.com;"

九、日志轮转与安全建议

日志轮转: /var/log/dnsmasq.log 会变大,建议为其添加 logrotate 配置 /etc/logrotate.d/dnsmasq:

/var/log/dnsmasq.log {

daily

rotate 7

compress

missingok

notifempty

create 640 dnsmasq adm

postrotate

systemctl restart dnsmasq >/dev/null 2>&1 || true

endscript

}

权限:确保只有可信用户能读 /var/log/dnsmasq.log 与 /opt/dns_cache 下的 DB 文件。隐私:统计仅记录域名,不记录完整请求者 IP(脚本可扩展记录 IP);若要记录 IP,请注意隐私合规。

十、扩展(可选、非必须)

将 SQLite 数据定期导出到 InfluxDB / Grafana 做可视化。在脚本中记录客户端 IP(从日志中提取)以做来源分析。添加白名单/黑名单规则(dnsmasq 支持 address=/bad.site/0.0.0.0 阻断广告域)。把统计脚本做成小 Web 服务(Flask)以便在线查看 TOPN。

十一、总结

本文提供了一个非常轻量、易上手的本地 DNS 缓存与统计方案:用 dnsmasq 做缓存与日志,用一个简短的 Python 脚本把查询写入 SQLite,便于快速落地、长期统计与排查。整套方案依赖少、脚本短、适合想在局域网内提升解析速度并观察访问热点的读者。

超云服务器客服

关键词: