这篇文章没准能帮你节省 1 天的时间折腾。当然,这个不是从 0 开始的教程,如果你完全不会,建议看其他的。
网络
首先,我的网络架构是这样的。
网段 | 说明 |
192.168.196.0/24 | ZeroTier 的虚拟网络 |
192.168.31.0/24 | 家里的路由器(OpenWrt) |
IP 地址 | 说明 |
192.168.31.1 | 路由器的 IP 地址 |
192.168.196.232 | HA 服务器的 IP 地址(Debian 12) |
我的 HA 是通过 Docker 来运行的。并且不是 Host 网络模式。
version: '3'
services:
homeassistant:
image: homeassistant/home-assistant:2024.1.2
container_name: homeassistant
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
ports:
- "127.0.0.1:8123:8123" # 如果你不需要 Nginx 这类,可以将 127.0.0.1 去掉
- "21063:21063" # WireShark 抓包到的端口,是 HomeKit 的
#- "51827:51827" # 这个我也不清楚,但是我没有启用,看别人也抓到了这个端口
restart: always
privileged: true
#network_mode: host # 我这里不用 host
这里的前提是将你的路由器加入到 ZeroTier 并且配置好静态路由后,服务器和路由器已经可以互 ping 通子网的设备。并且你家里的路由器可以正常访问 HA。
如果你都不能正常访问,那么你接下来干的事情的意义是什么呢?
获取 Docker 和 ZeroTier 的网卡名称
我是 Docker Compose 构建的服务,你可以参照我的方法获取网卡名称。
获取 Docker 网卡列表
docker network ls
root@VM-4-4-debian:~/homeassistant# docker network ls
NETWORK ID NAME DRIVER SCOPE
babd919187d1 bridge bridge local
d3883efb7bb5 homeassistant_default bridge local
3caf397b7076 host host local
de4898875ce3 none null local
看到那个 homeassistant_default 左边的 d3883efb7bb5 了吗?复制它!
对应服务的网卡就是 br-d3883efb7bb5 。
这里你可不能照抄,每个人的可能都不一样。
获取 ZeroTier 的网卡名称
我觉得这里应该每个人都会。
ip a
看到 ztzlgloho5 或者差不多,底下有个 ZeroTier 分配给你的 IP 的网卡就是了。也顺便获取一下路由器的 ZeroTier 网卡名称。
配置 Avahi
路由器和服务器都要安装 Avahi。
服务器:
apt install avahi-daemon
路由器:
apt install avahi-utils
这里的坑我都帮你踩完了,只要你能理解你基本都可以少走很多弯路。
Debian 和 OpenWrt 的 Avahi 的配置文件地址都在 /etc/avahi/avahi-daemon.conf。
我们都只需要做相同的事情。打开配置文件,编辑两个地方。
以下是省略的,只给了关键部分。你只需要从你的配置文件中查找这段部分即可。
Debian (服务器)的配置
[server]
allow-interfaces=br-d3883efb7bb5,ztzlgloho5 # 分别是 HA 的网卡和 ZeroTier 的网卡。
[reflector]
enable-reflector=yes
OpenWrt 的配置
[server]
allow-interfaces=ztzlgloho5,br-lan # 只需要修改 ZeroTier 的网卡
[reflector]
enable-reflector=yes
重启服务
这玩意虽然有 auto reload,但是实测了一下貌似不会监听新的网卡,必须要重启。
Debian
systemctl restart avahi-daemon
OpenWrt
/etc/init.d/avahi-daemon restart
手动配置 HA 的 HomeKit
为什么要手动配置呢?看这里。
我们需要手动指定通告 IP,不然它会回应自己的(容器的) IP。这样是连接不进来的。
首先,从你的 HA 集成里面删掉原来的 HomeKit 的服务条目。如果你之前没有添加,那就不用管。
接下来编辑一下 HA 的 config/configuration.yaml。以下我给出了关键部分。
http:
# For extra security set this to only accept connections on localhost if NGINX is on the same machine
# Uncommenting this will mean that you can only reach Home Assistant using the proxy, not directly via IP from other clients.
server_host: 0.0.0.0
use_x_forwarded_for: true
# You must set the trusted proxy IP address so that Home Assistant will properly accept connections
# Set this to your NGINX machine IP, or localhost if hosted on the same machine.
trusted_proxies:
- 127.0.0.1
- 172.25.0.1 # 反向代理所需要的,我也有这个需求,如果你不需要,直接看下面。
# 下面是你要添加的
homekit:
advertise_ip: '192.168.196.232' # 这里是你的服务器的 IP
然后重启 HA。
验证 Avahi
为什么到这步才验证呢?因为你得先配置好 HA 的 HomeKit!
接下来,到服务器上输入这个命令。
avahi-browse -at
root@VM-4-4-debian:~/homeassistant# avahi-browse -at
+ br-d3883efb7bb5 IPv4 Home Assistant Bridge 4ADABB _hap._tcp local
_nvstream_dbd._tcp local
+ br-d3883efb7bb5 IPv4 _________ _home-assistant._tcp local
检查输出中是否有以上加粗的部分。不用完全一致,有类似即可。
然后到路由器上执行相同的命令,检查是否有类似输出。如果都有,那恭喜你,你是个天才。
如果没有,请检查防火墙…………(其实我不喜欢这套说辞,但是你确实应该检查一下,特别是有没有重启 Avahi Daemon)。
可能的错误
如果在 OpenWrt 上,你遇到了什么 daemon not running 的问题,很可能就是没有启动服务。或者就是没有启动,你可以手动启动一下。
avahi-daemon
然后慢慢调试你在上面遇到的问题。
连接
接下来,打开你的 HA 页面,扫描 HomeKit 配对二维码,然后成功连接!
遇到问题
如果遇到了错误怎么办?
在路由器上抓包(可以用 tcpdump),抓源 IP 为你 iPhone 设备的包,看看 mDNS 和 TCP 这块,检查一下 iPhone 连接的目标地址是什么的地址,以及什么端口。
当然不是无脑抓,条目很多,如果连接失败了,那他肯定有红色的 TCP 相关的包,点击它查看目标地址。然后再做配置文件的修改。
完
祝你折腾的开心!
熬了 3 天夜才折腾出来个这玩意。
你好!感谢你的经验。
我是云上Ubuntu跑HA服务器和Zerotier,路由器Padavan跑Zerotier。
感觉和你唯一的区别是没用docker。
我研究了mDNS,然后按你的教程在HA和Padavan上都部署了Avahi。
奇怪的是HA环境上awahi-browser -at 无输出,
但Padavan上出现如下(- -!应该这部分是成功的):
Homekit扫码不成功,有机会和时间的话,帮帮分析一下 谢谢!
嗯…久等了。请尝试使用 WireShark 来抓包一下,看看 mDNS 那边目标 IP 是什么,看看你的手机可以不可以连接到。很可能你的路由器也需要安装一个 zerotier。
如果不方便安装但是能 ssh 的话,可以调整 HA 的 HoneKit 通告 IP,然后到路由器中对 IP 地址进行重定向。一些智能设备如检测到不在一个 lan 是无法连接的。(比如米家的台灯)
感谢,经过排查,两个原因,一个是防火墙的问题,另一个问题是HA配置里“网络适配器”要勾选zerotier的选项,很早就配置好了,稳定跑了几个月了。