自托管 Tesla 数据记录器安全加固指南

TeslaMate 今天在 GitHub 上暴涨 8389 stars,这个用 Elixir 写的自托管数据记录器让车主能摆脱 Tesla 官方 App,完全掌控自己的车辆数据。但作为一个安全工程出身的人,我看到这种趋势时第一反应不是“好棒”,而是“谁的 API 密钥会裸奔在公网上?”

这不是危言耸听。过去几年,大量自托管项目因为默认配置、弱密码、未加密传输,导致用户数据被爬虫抓取或攻击者直接访问。TeslaMate 连接的是你的特斯拉车辆 API,能实时获取位置、电量、车门状态、驾驶行为——这些信息的敏感程度不亚于你的银行流水。

在这篇文章里,我会从攻防视角拆解 TeslaMate 部署中最容易忽略的安全盲区,给出我验证过的加固方案。读完你就能判断自己的部署是否安全,并且知道每一步该怎么做。

1. 风险描述:数据自主权的代价

TeslaMate 的核心功能是调用 Tesla 的 Owner API,每隔几分钟拉取一次车辆状态并存储到 PostgreSQL 数据库。它提供了精美的 Grafana 仪表盘,让你看到充电历史、效率分析、甚至每次行程的地图轨迹。

但问题在于:

  • Tesla API 密钥:你需要用 Tesla 账户的 access token(有效期内)或 refresh token。如果攻击者拿到这个 token,能直接远程解锁车门、启动空调、甚至定位车辆。
  • 数据存储:默认 PostgreSQL 没有加密,如果攻击者拿到数据库文件或通过 SQL 注入,就能获取所有历史位置和驾驶模式。
  • Web 界面:Grafana 默认没有强认证,很多人为了省事直接暴露在公网,连个密码都不设。
  • 依赖链:Elixir 生态中的依赖可能存在已知漏洞(比如 Phoenix 框架的旧版本)。

攻击者只需要一个入口点——比如你的 TeslaMate 实例暴露了 Grafana 的 3000 端口——就能逐步扩大攻击面。

2. 漏洞原理分析

2.1 Tesla API Token 的存储与传递

TeslaMate 在使用时,会将用户的 refresh token 保存在环境变量 ENCRYPTION_KEY 中,并在数据库里存储加密后的 access token。这个设计本身合理,但很多新手部署教程直接写在 .env 文件里,然后上传到公共 GitHub 仓库——这是最常见的泄露渠道。

攻击原理:

  • 如果攻击者拿到 .env 文件或环境变量,就能解密数据库中的 token(因为加密密钥在同一环境变量或配置文件中)。
  • 更糟糕的是,有些人直接在 Docker Compose 里硬编码 token,然后分享 docker-compose.yml。

2.2 未授权 Grafana 访问

TeslaMate 默认并不强制 Grafana 登录。虽然官方文档建议配置反向代理和基本认证,但很多用户为了“方便”直接暴露端口 3000。

攻击模拟:

  • 扫描 Shodan 或 Censys,发现公网 IP 的 3000 端口开放。
  • 直接访问,看到仪表盘,所有车辆数据一览无余。
  • 甚至可以修改 Grafana 面板设置,加入恶意脚本窃取会话。

2.3 数据库后门

PostgreSQL 默认监听 0.0.0.0,很多用户在生产环境中开着这个端口。如果数据库密码是弱口令(比如 postgres:postgres),攻击者可以直接连接导出所有表。

3. 真实案例与 PoC

案例:一位特斯拉车主的惨痛教训

2023 年,一位 Reddit 用户在 r/teslamotors 发帖,称自己的 TeslaMate 实例被入侵,攻击者通过 Grafana 仪表盘获取了车辆位置后,向 Tesla 客服谎称“车主钥匙丢了”试图远程解锁(未成功,因为特斯拉有二次验证)。事后发现原因:他把 Grafana 绑在 0.0.0.0:3000 并关闭了反向代理认证。

这个案例说明:攻击者不需要高科技,只需要你犯低级错误

PoC:如何在不破坏规则的情况下自行检测暴露面

以下是在你自己环境中的安全测试步骤(请勿对他人实例操作):

bash
1 2 3 4 5 6 7 8 9 10 11 12
# 1. 检查 Grafana 是否可匿名访问
curl -s -o /dev/null -w "%{http_code}" http://your-server:3000/login
# 如果返回 200,说明可以访问登录页,但默认可能允许匿名查看

# 2. 尝试直接访问 Dashboard API
curl http://your-server:3000/api/dashboards/home\?orgId=1
# 如果返回 JSON 且包含 uid,说明未授权访问

# 3. 检查 Tesla API token 泄露
# 查看你的 docker-compose.yml 是否在公开仓库中
# 假如泄露,攻击者可以这样使用:
curl -H "Authorization: Bearer <your_token>" https://owner-api.teslamotors.com/api/1/vehicles

4. 防护方案

以下是我在实际部署 TeslaMate 时使用的安全加固清单,按优先级排列。

4.1 强制反转代理+HTTPS

不要直接将 Grafana 端口暴露到公网。使用 Nginx 或 Caddy 做反向代理,并强制使用 Let's Encrypt 证书。

Nginx 配置示例(只允许来自内网或 VPN 的访问):

nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
server {
    listen 443 ssl;
    server_name teslamate.yourdomain.com;
    ssl_certificate /etc/letsencrypt/live/teslamate/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/teslamate/privkey.pem;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        # 添加基本认证
        auth_basic "Restricted Access";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}

4.2 使用独立访问令牌与最小权限

不要使用你常用的 Tesla 账户来生成 API token。创建一个专门用于 TeslaMate 的子账户(Tesla 目前支持家庭成员账户),并限制其权限。

另外,建议定期轮换 refresh token。可以在 cron 中写脚本,每月自动更换并更新环境变量。

4.3 加密数据库文件系统

PostgreSQL 数据目录应该放在加密卷上。使用 LUKS 或 systemd-cryptenroll 对磁盘加密。如果使用 Docker,将数据卷挂载到加密目录。

同时,启用 PostgreSQL 的 ssl 连接:

text
1 2 3 4
# postgresql.conf
ssl = on
ssl_cert_file = '/etc/ssl/certs/server.crt'
ssl_key_file = '/etc/ssl/private/server.key'

4.4 网络隔离

将 TeslaMate 部署在 Docker 的专用网络中,只开放必要的端口。对外只暴露反向代理(443),内部服务不监听 0.0.0.0。

使用 iptables 限制只有内网 IP 才能访问 3000 和 5432:

bash
1 2
sudo iptables -A INPUT -p tcp --dport 3000 -s 10.0.0.0/8 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 3000 -j DROP

4.5 启用 Grafana 认证与日志审计

在 Grafana 配置中强制登录:

ini
1 2 3
[auth.anonymous]
enabled = false
# 使用内置 SQLite 数据库保存用户,不要用 PostgreSQL 用户表

开启审计日志:

ini
1 2 3 4 5
[log]
mode = console file
level = info
file_log_level = info
filters = audit:enabled

5. 安全加固清单

检查你的 TeslaMate 部署是否符合以下每一项:

  • 所有服务均通过 HTTPS(TLS 1.3)对外暴露
  • Grafana 反向代理配置了 HTTP 基本认证或 OAuth
  • Tesla API token 存储在安全的环境变量中,未提交到任何版本控制系统
  • PostgreSQL 未监听公网 IP,且使用强密码(长度 >20,包含特殊字符)
  • Docker 容器使用非 root 用户运行
  • 定期更新所有软件(TeslaMate、Grafana、PostgreSQL、Elixir 运行时)
  • 数据卷使用加密文件系统
  • 已配置 fail2ban 或类似工具防止暴力破解 Grafana 登录
  • 已经向 Tesla 注册了专门用于 TeslaMate 的“其他开发者”账户,权限仅限读取车辆数据(无控制权)

我的看法

TeslaMate 这个项目本身质量很高,Elixir 的并发模型非常适合这种定时轮询 + 数据处理的任务。但它的火爆也意味着大量非专业运维的车主开始自托管,而他们往往对网络安全缺乏经验。

我认为项目的维护者应该考虑:

  1. 在首次运行时强制提示用户设置 Grafana 管理员密码和反向代理配置。
  2. 提供一键生成 Let's Encrypt 证书的脚本。
  3. 在默认配置中就将 Grafana 的匿名访问禁用。

否则,这 8000 多个 stars 里可能有一半是 Shodan 扫描器送来的“潜在目标”。

作为开发者,如果你正在运行 TeslaMate,请花 30 分钟按上面的清单检查一遍。如果你在考虑部署它,请从一开始就把安全内置进去,而不是事后补救。你的车辆数据不应该成为攻击者的游乐场。