Skip to content

Latest commit

 

History

205 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tollgate

Tollgate is a personal iOS ad blocker. It runs as an on-device packet tunnel (a Network Extension "VPN" whose traffic never leaves the phone), blocks ad and tracker domains at the DNS layer, and filters HTTPS requests through a local proxy that trusts a user-installed root certificate, so full URL rules (EasyList, uBlock Origin and AdGuard syntax) apply to Safari, web views and third-party apps.

It is not distributed through the App Store. It is built and signed by GitHub Actions with the owner's Apple Developer account and installed from a Linux workstation.

Status: M3. The tunnel runs the Rust core (DNS blocking with DNS over HTTPS, and HTTPS filtering through a local proxy once the certificate is trusted). The app downloads, caches and compiles the filter lists (daily, in the background), installs the certificate, and has an Activity tab with recent blocks and Settings for lists, your own rules, allowed sites, never-filtered hosts and learned certificate pins. The core is verified on Linux with devproxy; the on-device checks are in docs/experiments/m2.md and docs/experiments/m3.md. See the design and the feasibility research.

How it is built

  • core/: Rust workspace. Filtering, DNS and the HTTPS proxy live here and are developed and tested on Linux with cargo test. tollgate-ffi exposes them to Swift through uniffi.
  • core/tools/devproxy: runs the same DNS responder and proxy on the workstation for Firefox; devproxy --help and the checklist.
  • ios/: a thin SwiftUI app and a NEPacketTunnelProvider extension. The Xcode project is generated from ios/project.yml with XcodeGen; nobody edits a .xcodeproj.
  • .github/workflows/ios.yml: on an Apple silicon runner, cross-compiles the Rust core for aarch64-apple-ios, generates the Swift bindings, generates the project, archives, signs and uploads Tollgate.ipa as a workflow artifact. Without signing secrets (for example on pull requests from forks) it only checks that everything compiles.
  • Identifiers (bundle IDs, App Group, profile names) live in tooling/config.env only.

One-time signing setup

  1. In App Store Connect, Users and Access, Integrations, create a Team API key with Admin access and save the .p8 file somewhere private, for example ~/.config/tollgate/.

  2. In the Apple Developer portal, register the App Group named in tooling/config.env.

  3. With the iPhone connected over USB:

    cat > ~/.config/tollgate/asc.env <<EOF
    ASC_KEY_ID="XXXX"
    ASC_ISSUER_ID="your-issuer-id"
    ASC_KEY_PATH="~/.config/tollgate/AuthKey_XXXX.p8"
    EOF
    tooling/asc/provision.py setup

    The tool reads ~/.config/tollgate/asc.env for any of the three variables not set in the environment.

    This registers the phone, creates both App IDs with the Network Extensions and App Groups capabilities, creates an Apple Development certificate and the development profiles. The phone's UDID and name are read with libimobiledevice, or with the pinned pymobiledevice3 when it is not installed. If more than one device is connected, or neither tool can read them, add --udid <UDID> --name <name>.

  4. In the portal, assign the App Group to both App IDs, then run tooling/asc/provision.py profiles again.

  5. tooling/asc/push-secrets.sh stores the certificate and profiles as repository secrets.

Everything written by the provisioning tool goes to tooling/asc/out/, which is gitignored.

Install and debug

gh workflow run ios.yml --repo mmaher88/tollgate --ref <branch>   # build the branch tip first
tooling/scripts/fetch-ipa.sh <branch>   # the CI build of the branch tip (default main)
tooling/scripts/install.sh        # install on the USB-connected iPhone
tooling/scripts/logs.sh tunnel    # stream the extension's logs

fetch-ipa.sh refuses a build older than the branch tip unless given --allow-stale, and prints the run number (#N), run id and URL, and the commit (kept in build/ipa/BUILD_INFO). The app shows "N (short commit)" under Diagnostics, Build, which matches the run number and the short commit.

The first install of a development-signed app asks for Developer Mode on the phone (Settings, Privacy & Security, Developer Mode), followed by a reboot.

In the app: tap Turn on (allow the VPN configuration), let the filter lists download, then follow the Setup steps to install and trust the certificate before switching on HTTPS filtering. tooling/scripts/logs.sh streams the app, the tunnel and the Rust core together.

To try the core on Linux without a phone, run devproxy (see docs/experiments/m1-devproxy.md).

License

MIT

About

Personal iOS ad blocker: on-device packet tunnel with HTTPS filtering

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages