这篇文章讨论如何部署一个完全可用、并且可以通过 Tor 网络访问的 Flutter Web 应用。
你可能会想,“为什么,拿来干嘛?”。为了做一个最好看的 dark-web 商店 avail…
不是。我的目标是探索和实验这种方法。虽然 Tor 主要以安全特性闻名,但 Flutter (Google 做的,sic!) 对于专注匿名性的应用来说,反而不应该是第一选择。优缺点请滚到最下面看。
工具
- Flutter (Channel stable, 3.19.6, on macOS 14.4.1 darwin-arm64)
- Dart version 3.3.4 | DevTools version 2.31.1
- VS Code (version 1.88.1) | Flutter extension version 3.87.20240402
- Google Chrome 124.0.6367.62
- Tor Browser 13.0.14
- Docker Desktop 4.29.0 | Engine 26.0.0
这是我运行时使用的规格。你应该也可以使用不同版本,不会有太大问题。
准备 Flutter Web 项目
创建一个空项目
flutter create <PROJECT_NAME> -e
(可选)删除所有不需要的文件夹
在我的情况里,我不想跑 iOS、macOS、Android 或 Linux,所以我删除所有平台相关文件夹。如果你需要,也可以很容易再加回来。
输出文件树是:
├── README.md
├── analysis_options.yaml
├── flutter_web_tor.iml
├── lib
│ └── main.dart
├── pubspec.lock
├── pubspec.yaml
└── web
├── favicon.png
├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
├── index.html
└── manifest.json
4 directories, 13 files
测试应用
flutter run -d chrome
这个阶段项目应该已经在本地运行了,也就是说它已经准备好继续。
部署配置
既然项目运行正确,还剩三个目标:
- 准备环境,
- 构建 web app,
- 运行它,并允许它通过 Tor 网络访问。
我使用 Docker,但你并不一定要用它,也可以使用单独的机器或其他可用工具。步骤保持一样。
创建 Dockerfile
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
curl \
git \
unzip \
nginx \
tor
# Clone Flutter SDK at specified version into the /src/flutter
RUN git clone --branch 3.19.6 https://github.com/flutter/flutter.git /src/flutter
ENV PATH="/src/flutter/bin:$PATH"
COPY . /app
WORKDIR /app
# Build the web app
RUN flutter precache
RUN flutter doctor -v
RUN flutter clean
RUN flutter pub get
RUN flutter build web
# Copy the output to the default Nginx server root
RUN cp -r build/web/* /var/www/html/
# Configure Tor service
# Specify the port for Tor control interface
RUN echo "ControlPort 9051" >> /etc/tor/torrc
RUN echo "CookieAuthentication 1" >> /etc/tor/torrc
# Allow read access to the cookie authentication file
RUN echo "CookieAuthFileGroupReadable 1" >> /etc/tor/torrc
# Disable Tor from being an exit node on the Tor network
RUN echo "ExitPolicy reject *:*" >> /etc/tor/torrc
# Set the directory for the hidden service configuration
RUN echo 'HiddenServiceDir /var/lib/tor/hidden_service/' >> /etc/tor/torrc
# Configure a hidden service to listen on port 80 and forward
# traffic to the local web server on 127.0.0.1:80.
RUN echo 'HiddenServicePort 80 127.0.0.1:80' >> /etc/tor/torrc
EXPOSE 80
CMD service nginx start && tor
├── Dockerfile
├── README.md
├── analysis_options.yaml
├── flutter_web_tor.iml
├── lib
│ └── main.dart
├── pubspec.lock
├── pubspec.yaml
└── web
├── favicon.png
├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
├── index.html
└── manifest.json
4 directories, 14 files
项目已经设置好了。现在构建并运行它。
部署
构建应用
docker build -t flutter-web-tor .
运行应用
docker run --name flutter-web-tor flutter-web-tor
成功后,你可以检查并看到容器正在运行。
访问应用
不管主机是什么,一旦应用正常运行,它就可以被任何连接到 Tor 网络的设备访问。这个设置很特别,因为 不同于传统托管,你不需要拥有传统域名;应用会立刻可以从各种设备访问。
试着用手机连接到另一个网络来访问它,做一下验证。
获取应用的域名
docker exec -it flutter-web-tor cat /var/lib/tor/hidden_service/hostname
你的 .onion 域名应该长这样:
btlithizf76bj4rryp5fj3t7nmnni3jptrhiya5bfqns5ab5jtkwehqd.onion
接下来,打开 Tor browser,连接到 Tor 网络,然后输入你的 .onion 链接。
应用正在运行,而且活着!
保持同一个域名
Tor 通过 .onion 地址用一种独特方式管理域名,这些地址会基于加密自动生成。这些地址就是 Tor 网络上的域名,用来保证匿名性和安全性。
如果想长期保持同一个 .onion 域名,关键是安全备份并恢复与你的 Tor 服务关联的私钥。如果密钥丢失,.onion 地址无法恢复,也就是说会用新密钥生成一个新域名。
这个配置没有设置成保留域名,也就是说每次重新运行都会重新生成!
注意事项
Tor 网络通过全球志愿者中继网络路由互联网流量,实现匿名通信。它主要用来保护用户隐私、对抗互联网审查,通过隐藏 IP 地址和网络活动来防止潜在监控或流量分析。
Tor 可以被记者、活动人士、吹哨人和个人使用,用来安全通信,并在不担心被监控或报复的情况下访问互联网。通过加密并让流量经过多个 Tor 中继,很难把网络活动追溯回原始用户,因此提供较高程度匿名性。
由于很多原因,不推荐把 Flutter 用于 Tor 网络部署。
Tor 网站通常会尽可能少用 JS,因为 JS 可能破坏安全和隐私。这也是为什么 Flutter 从一开始看起来就不太像最佳方案。
漏洞或问题列表可能相当长,下面只是其中几个:
- 性能差
- 大量网络通信
- 依赖外部库
- 大量使用 JS
- 托管问题
- local storage 漏洞
- 加载第三方资源
- …
不过,你可以把它改造成任何你觉得有用的用途。