OpenWrt 安装 mDNS,并设置 mDNS 映射
- 路由器:OpenWrt 21.02.1
- 电脑:Windows 10 21H1
Windows 10 现在已经默认支持了 mdns,可以直接 ping 设备名称.local
查看电脑的ip。
1.下载 mDNS 安装包
opkg update
opkg install umdns
2.配置防火墙通信规则
2.1 方式1: uic 方式配置
uci -q delete firewall.mdns
uci set firewall.mdns="rule"
uci set firewall.mdns.src_port="5353"
uci set firewall.mdns.name="Allow-mDNS"
uci set firewall.mdns.target="ACCEPT"
uci set firewall.mdns.dest_ip="224.0.0.251"
uci set firewall.mdns.dest_port="5353"
uci set firewall.mdns.proto="udp"
uci set firewall.mdns.src="*"
uci commit firewall
/etc/init.d/firewall restart
2.1 方式2: Luci 页面方式配置
Luci -> 网络 -> 防火墙 -> 通信规则 -> 新增
2.2 电脑端 mDNS 测试
此时在电脑接在路由器lan口,在电脑上 ping OpenWrt.local
就可以得到 OpenWrt 路由器的地址。
其中,OpenWrt 是路由器的主机名,在 Luci -> 系统 -> 系统 -> 常规属性 -> 主机名 查看:
2.3 路由器端 mDNS 问题
但是,当你在 OpenWrt 路由器上 ping 电脑端,却不能得到电脑的 ip 地址。
使用 ubus call umdns hosts
可以扫描到 ip 地址
为了能够 ping 到 电脑端的IP。这里有2中方法,第1种是把 mdns 域名添加到路由器 host 文件中。第2种方法是添加主机名映射。
3.添加 mdns 映射
3.1 安装 jq
解析 json 格式
opkg install jq
3.2 方法一 : 添加 mdns 域名到路由器 host 文件中
- 编写 shell 脚本
UpdateMDNS.sh
用以生成 hosts 文件
#!/bin/sh
ubus call umdns update
sleep 2
mDNS_JSON=$(ubus call umdns hosts)
# 获得主机域名
mDNs_hosts=$(echo ${mDNS_JSON} | jq ". | keys" | sed 's/[][]//g' | sed 's/"//g' | sed 's/,//g')
# 获得主机IP
hosts_text=""
for host in ${mDNs_hosts}
do
host_ipv4=$(echo ${mDNS_JSON} | jq ".\"${host}\".ipv4" | sed 's/"//g')
if [ ${host_ipv4} != "null" ] && [ ${host_ipv4} != "0.0.0.0" ]; then
hosts_text="${hosts_text}${host_ipv4} ${host}\n"
fi
done
echo -e ${hosts_text} > /root/mDNS_hosts
/etc/init.d/dnsmasq restart
-
运行脚本
UpdateMDNS.sh
得到/root/mDNS_hosts
-
添加额外的 hosts 文件:Luci -> 网络 -> DHCP/DNS -> Host和解析文件
3.2 方法二:添加主机名映射
- 编写 shell 脚本
UpdateMDNS.sh
用以添加主机名映射
#!/bin/sh
ubus call umdns update
sleep 2
mDNS_JSON=$(ubus call umdns hosts)
# 获得主机域名
mDNs_hosts=$(echo ${mDNS_JSON} | jq ". | keys" | sed 's/[][]//g' | sed 's/"//g' | sed 's/,//g')
# 删除所有的主机名映射
# 这里将 domain[0] 改为 domain[1] 就可以保留最上面一条主机名映射,以此类推。
uci delete dhcp.@domain[0] > /dev/null 2>&1
while [ $? == 0 ]; do
uci delete dhcp.@domain[0] > /dev/null 2>&1
done
# 获得主机IP
for host in ${mDNs_hosts}
do
host_ipv4=$(echo ${mDNS_JSON} | jq ".\"${host}\".ipv4" | sed 's/"//g')
if [ ${host_ipv4} != "null" ] && [ ${host_ipv4} != "0.0.0.0" ]; then
# 添加一条主机名映射
uci add dhcp domain > /dev/null
# 在最后一条主机名映射填写 IP 地址和 mDNS 域名
uci set dhcp.@domain[-1].name=${host}
uci set dhcp.@domain[-1].ip=${host_ipv4}
fi
done
# 提交 dncp 配置, 并重启 dhcp 服务器
uci commit dhcp
/etc/init.d/dnsmasq restart
这里再提供一个与上面 shell 脚本功能相同的 lua 脚本 UpdateMDNS.lua
:
#!/usr/bin/lua
-- 加载 ubus 模块
require "ubus"
-- 连接 ubus
local conn = ubus.connect()
if not conn then
error("Failed to connect to ubusd")
end
-- 检查是否存在由 mnds 创建的 domain,通过 source 来判断来源
local domain = conn:call("uci", "get", { config="dhcp", type="domain", match={source="mdns"}}).values
-- 如果存在由 mnds 创建的 domain
if next(domain) ~= nil then
-- print("domain is not empty.")
-- 删除所有由 mdns 创建的 domain
conn:call("uci", "delete", { config="dhcp", type="domain", match={source="mdns"}})
end
-- 更新 mdns
conn:call("umdns", "update", {})
-- 获得 mdns 主机
local hosts = conn:call("umdns", "hosts", {})
for host, addr in pairs(hosts) do
if (addr["ipv4"] ~= nil and addr["ipv4"] ~= "0.0.0.0") then
-- print("host=" .. host .. " value=" .. addr["ipv4"])
-- 添加 mnds 主机的ip地址到 domain,额外添加 source 选项来标记该条 domain 由 mdns 添加
conn:call("uci", "add", { config="dhcp", type="domain",
values = {
name = host,
ip = addr["ipv4"],
source = "mdns"
}
})
end
end
-- 提交 dhcp 更改
conn:call("uci", "commit", { config="dhcp" })
-- 重启 dns 服务
conn:call("service", "state", { name="dnsmasq", spawn=false }) -- 关闭
conn:call("service", "state", { name="dnsmasq", spawn=true }) -- 启动
-- 关闭 ubus 连接
conn:close()
查看主机名映射:Luci -> 网络 -> 主机名映射
注意:这里的IP地址不仅有 192.168.1.0/24 网段,还有 10.16.0.0/17 网段是因为 mDNS 开启了 wan 监听,设置方法在第4小节。
3.3 测试
此时可以 ping 到电脑 ip:
3.4 添加定时任务
- 设置定时任务,每30分钟更新一次,命令
crontab -e
,输入
*/30 * * * * /root/UpdateMDNS.sh >> /dev/null 2>&1
- 重启定时任务:
/etc/init.d/cron restart
4. 添加 wan 口监听 (可选)
- 在
/etc/config/umdns
文件中添加list network wan
,修改后内容为:
config umdns
option jail 1
list network lan
list network wan # Provides visibility into both networks, but does not act as a repeater
-
重启 umdns :
/etc/init.d/umdns restart
-
重新添加 mdns 映射:
/root/UpdateMDNS.sh