Deploy Flutter Web application with Tor network: A Step-by-Step Guide

This article discusses deploying a fully usable Flutter Web application accessible using the Tor network.

You might wonder, "Why and what for?". To create the best looking dark-web store avail...

No. My goal has been to explore and experiment with this approach. While Tor is primarily known for its security features, the Flutter(made by Google, sic!) rather should not be the first choice for applications focusing on anonymity. Scroll to the bottom for the pros and cons of this approach.


Tools

- 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

This is the spec, I am using while running. You should be able to run different versions without much trouble.


Preparing Flutter Web project

Create an empty project

flutter create <PROJECT_NAME> -e

(Optional) Delete all unnecessary folders

In my case, I don't want to run iOS, macOS, Android or Linux, so I delete all platform-specific folders. You can easily add them again, if you need to.

The output file tree is:

├── 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

Test app

flutter run -d chrome

The project should be running locally at this stage, which means it is ready to continue.


Deployment configuration

Since the project runs correctly, there are three objectives left:

  • preparing the environment,
  • building the web app,
  • running and allowing it to be accessible via the Tor network.

I use Docker, but you are not forced to use it, you can use a separate machine or other tools available. Steps remain same.

Create 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        

The project is set up. Now build and run it.


Deployment

Build app

docker build -t flutter-web-tor . 

Run app

docker run --name flutter-web-tor flutter-web-tor 

When successful, you can check and see your container running.

Flutter Web app is running

Access to app

No matter the host, once the app is operational, it becomes accessible on any device connected to the Tor network. This setup is distinctive because, unlike traditional hosting, there is no need to own a traditional domain; the app is immediately accessible from various devices.

Try accessing it from your phone while connected to a different network for verification.

Obtain app's domain

docker exec -it flutter-web-tor cat /var/lib/tor/hidden_service/hostname

Your .onion domain should look like this:

btlithizf76bj4rryp5fj3t7nmnni3jptrhiya5bfqns5ab5jtkwehqd.onion

Next, open the Tor browser, connect to the Tor network, and enter your .onion link.

App is running and alive!

Staying with the same domain

Tor manages domains uniquely by using .onion addresses, which are automatically generated based on the cryptography. These addresses serve as the domain names on the Tor network, ensuring anonymity and security.

To maintain the same .onion domain over time, it's crucial to securely back up and restore the private key associated with your Tor service. If the key is lost, the .onion address cannot be recovered, meaning a new domain would be generated with a new key.

This configuration is not set up to preserve the domain, meaning each time you will re-run, it will regenerate!


Considerations

The Tor network enables anonymous communication by routing internet traffic through a global network of volunteer relays. It's primarily used to protect users' privacy and internet censorship by hiding IP addresses and network activity from potential surveillance or traffic analysis.

The Tor can be used by journalists, activists, whistleblowers and individuals to communicate securely and access the internet without fear of monitoring or repercussions. By encrypting and bouncing traffic through multiple Tor relays, it becomes difficult to trace internet activity back to the original user, thereby providing a high degree of anonymity.


Flutter is not recommended for the Tor network deployment for many reasons.


Tor websites typically use as little JS as possible, because JS can compromise security and privacy. This is why Flutter might not seem like the best approach from the very beginning.

The list of vulnerabilities or issues can be quite extensive and it's just few of them:

  • poor performance
  • extensive networking
  • dependencies on external libraries
  • JS is heavily used
  • hosting issues
  • local storage vulnerabilities
  • loading 3rd party resources
  • ...

However, you CAN adapt it for whatever purposes you find useful.

Read more

Appwrite vs Supabase - Which backend solution is best for you? Cloud vs Self-Hosted performance comparison

Appwrite vs Supabase - Which backend solution is best for you? Cloud vs Self-Hosted performance comparison

In this article, you will read about: * Appwrite performance: How fast Appwrite handles eCommerce simulation * Supabase performance: How fast Supabase performs under the same eCommerce simulation * Cloud vs Self-Hosted: How self-hosted instances can outperform cloud options, offering better control and performance for various use cases * Flexibility: Which platform, Supabase or

By Maks Kulicki