本文发布于20天前,最后更新于 20 天前,其中的信息可能已经有所发展或是发生改变。
前言
最近在折腾改造我们的宿舍,用 docker 搭建了 HomeAssistant,接入米家和一些 esp 设备。我用 frp 技术将 HA 发布到了公网上,以便于我远程控制设备和接受与设备相关的通知。不过为了安全起见,我通过 nginx 为 HomeAssistant 配置了 HTTPS 加密访问。不过,在配置完成之后,出现了一些小问题,这篇博客用来记录一下解决过程
正文
400 Bad Request
server {
listen $port ssl;
server_name HomeAssistant_https;
client_max_body_size 1G;
ssl_certificate /usr/share/nginx/certs/ssl.crt;
ssl_certificate_key /usr/share/nginx/certs/ssl.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
add_header serverhello $http_host;
proxy_buffering off;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
add_header serverhello $http_host;
proxy_pass http://host.docker.internal:8123;
}
error_page 497 https://$http_host$request_uri; #302跳转
}
以上是我的 nginx 反代配置,配置完成了之后发现虽然网页能访问,但是返回 400

原来是 HomeAssistant 为了抵御恶意攻击,要求必须经过信任的 ip 网段发来的代理请求才能被正常响应,因此需要我们修改 HomeAssistant 的配置来允许本地 nginx 的访问。如下图所示

我们在 configuration.yaml 配置文件中添加以下字段,其中 XXX.XXX.XXX.XXX 替换为 nginx 代理的地址
http:
use_x_forwarded_for: true
trusted_proxies:
- XXX.XXX.XXX.XXX # Add the IP address of the proxy server
之后访问就 OK 了
websocket 代理
由于 HomeAssistant 还使用了 websocket,而我上述的 nginx 配置中没有开启 ws 的代理,参考Reverse proxy using NGINX - Community Guides - Home Assistant Community 可知,还需要增加以下字段到 location 配置中:
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
这篇帖子里面给了我们一段可以参考的 nginx 配置,如下:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
# Update this line to be your domain
server_name example.com;
# These shouldn't need to be changed
listen [::]:80 default_server ipv6only=off;
return 301 https://$host$request_uri;
}
server {
# Update this line to be your domain
server_name example.com;
# Ensure these lines point to your SSL certificate and key
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Use these lines instead if you created a self-signed certificate
# ssl_certificate /etc/nginx/ssl/cert.pem;
# ssl_certificate_key /etc/nginx/ssl/key.pem;
# Ensure this line points to your dhparams file
ssl_dhparam /etc/nginx/ssl/dhparams.pem;
# These shouldn't need to be changed
listen [::]:443 ssl default_server ipv6only=off; # if your nginx version is >= 1.9.5 you can also add the "http2" flag here
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
# ssl on; # Uncomment if you are using nginx < 1.15.0
ssl_protocols TLSv1.2;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
proxy_buffering off;
location / {
proxy_pass http://127.0.0.1:8123;
proxy_set_header Host $host;
proxy_redirect http:// https://;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
我参考上述配置修改后,总配置如下:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen $port ssl;
server_name HomeAssistant_https;
client_max_body_size 1G;
ssl_certificate /usr/share/nginx/certs/ssl.crt;
ssl_certificate_key /usr/share/nginx/certs/ssl.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
add_header serverhello $http_host;
proxy_buffering off;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
add_header serverhello $http_host;
proxy_pass http://host.docker.internal:8123;
}
error_page 497 https://$http_host$request_uri; #302跳转
}
结语
折腾了俩小时,成功接入米家,终于能通过 HomeAssistant 操控米家的设备啦!
接下来就是采购各种 esp 板子和传感器,进一步实现智能化寝室啦!






