0x00 什么是 awtrix

入坑其实是因为看到了 V2EX 上的一个帖子:我做了一个 WIFI 像素时钟,只要 Lametric 十分之一的价格。 - V2EX,发现这玩意是个“可定制的智能钟”(DIY intelligent clock),而且可定制程度非常非常高,于是想到可以自己动手做一个玩玩(逃

原帖博客少数派备份:https://sspai.com/post/54225

0x01 制备原材料

  1. WS2812B 全彩 8*32 可编程像素软屏

    这个淘宝直接买,简单省事

  2. ESP8266 WIFI 模块 CP2102 ESP-12E

    这个家里有,淘宝买也不贵

  3. 光栅

    是为了把圆光点变成方形的,看上去更帅气

    直接 3D 打印,走 SaaS 平台,打印好之后快递过来

  4. 长期可访问的网络节点

    考虑到我有台服务器,就直接用它好了。也可以用有公网 IP 的电脑来做。

  5. 杂项:杜邦线,micro USB线,热熔胶枪……

0x02 配置服务器端

0x02.1 基础配置

安装 awtrix 本体:

1
2
3
4
$ sudo su
$ timedatectl set-timezone 'Asia/Beijing'
$ mkdir /usr/local/awtrix && cd /usr/local/awtrix
$ wget https://blueforcer.de/downloads/awtrix.jar

之后是创建自启动:

1
2
3
4
5
$ sudo su
$ URLPREFIX=https://gistcdn.githack.com/XieJiSS/3df9a5ca5f7bcdc5d6cc261cb6d7497d/raw/9f3044c0f9a42c0f479e5244b7fcd0dad87686d2
$ curl "$(echo $URLPREFIX)/awtrix.service" > /etc/systemd/system/awtrix.service
$ curl "$(echo $URLPREFIX)/awtrix.sh" > /usr/local/bin/awtrix.sh
$ chmod +x /usr/local/bin/awtrix.sh

运行服务:

1
2
3
$ sudo su
$ systemctl enable awtrix
$ systemctl start awtrix.service

此时,awtrix 的 Web Interface 已经运行在 0.0.0.0:7000 上了。如果你的服务器没有做任何端口限制,则你应该可以在浏览器中访问 域名:7000 来查看 Web Interface。然而我的服务器使用 ufw 白名单限制了入站端口,外加上我希望把这玩意做成子域名的形式(类似 awtrix.jiejiss.com 这样的),所以需要修改下 nginx 的配置文件,使得能够通过 80/443 等白名单入站端口访问。

0x02.2 配置反向代理和 HTTP Basic Authentication

首先是反向代理:

1
2
3
4
5
6
7
8
9
10
11
upstream awtrix {
server 127.0.0.1:7000;
keepalive 64;
}
server {
server_name awtrix.jiejiss.com;
location / {
proxy_pass http://awtrix;
proxy_set_header Host $host;
}
}

随后用 letsencrypt 的 certbot-auto 命令注册一个 SSL Certificate。由于 Basic Auth 在认证时基本上不提供传输层安全性,因此需要用 TLS 包一下。

1
$ certbot-auto run --nginx -d awtrix.jiejiss.com

之后一路回车,直到最后一项时选择开启重定向。certbot-auto 将会自动修改你的 nginx 配置,将所有的 HTTP 请求重定向到 HTTPS。

此时你的 nginx 配置看上去像是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
upstream awtrix {
server 127.0.0.1:7000;
keepalive 64;
}
server {
server_name awtrix.jiejiss.com;
location / {
proxy_pass http://awtrix;
proxy_set_header Host $host;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/awtrix.jiejiss.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/awtrix.jiejiss.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = awtrix.jiejiss.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name awtrix.jiejiss.com;
listen 80;
return 404; # managed by Certbot
}

这个时候访问 awtrix.jiejiss.com 就已经可以看到 awtrix 的 Web Interface 界面了。

然而由于 awtrix 的 Web Interface 中有很多依托于 WebSocket 存在的内容,目前还没法正常工作,所以我们还得想办法让 nginx 反向代理支持 WebSocket。nginx v1.13.10+ 已经支持 WebSocket 了,所以我们只需要配置 nginx 正确处理 WebSocket 的 Upgrade 请求头即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
server_name awtrix.jiejiss.com;
location ~ /ws$ { # awtrix Web Interface 的所有 WebSocket 请求均以 /ws 结尾
proxy_pass http://awtrix;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
location / {
proxy_pass http://awtrix;
proxy_set_header Host $host;
}
# ...
}

到这里,Web Interface 已经可以正确使用了。

但是我们并不想让所有人都能访问到 awtrix.jiejiss.com 并修改我们配置好的内容,所以需要引入一个验证机制。考虑到怎么省事怎么来的原则,我放弃了在源码层面修改 awtrix 的代码并增加登录功能的想法,awtrix 的 docs 中也没有给出为管理界面增加密码的方法。于是干脆直接上 HTTP Basic Authentication 好了。这个时候前面的全站 HTTPS 就派上用场了:如果没有用 HTTPS,HTTP Basic Authentication 的用户名和密码可能会被中间人攻击所窃听到。

创建 .htpasswd 文件:

1
2
3
4
5
6
$ sudo su
$ apt-get install apache2-utils
$ htpasswd -c /etc/nginx/.htpasswd <username>
New password: <password>
Re-type new password: <password>
Adding password for user <username>

修改 nginx 配置文件:

1
2
3
4
5
6
7
8
9
10
server {  # 注意:不要在 nginx 的 listen 80 端口的 server 加入 auth_basic,务必保证先重定向到 HTTPS server 再认证!
server_name awtrix.jiejiss.com;
auth_basic "Restricted"; # 这两行要加在 server { 下面,不能加在 location / { 里面
auth_basic_user_file /etc/nginx/.htpasswd;
location ~ /ws$ {
# ...
}
listen 443 ssl; # managed by Certbot
# ...
}

(关于 HTTP Basic Authentication 的安全性问题,可以看:Is basic access authentication secure?

这样,我们再次访问 awtrix.jiejiss.com 就必须要先输入用户名和密码才能打开了,也不可能绕过 Authentication 直接连接 WebSocket。

这一步并不会影响 ESP8266 开发板对服务器的访问,因为在 src/AWTRIXController.cpp 中规定了 awtrix client 获取指令的地方是 server_ip:7001。只需要在防火墙里开启 7001 端口的 TCP 访问权限就好了。

具体的动手 DIY 部分以后开新篇写。如果只是想跑起来的话,剩下的部分参考最开始的 V2EX 帖子就足够了(原帖博客已失效,移步少数派投稿)。

UPDATE: 对于 ZJU 校内的 ZJUWLAN 环境,可以考虑魔改一下 awtrix IoT 客户端的 WiFi 认证登录部分,或许 gh:jiangotto/ESP32_ZJUWLAN 会有所帮助。

来源:https://blog.jiejiss.com/