{"id":50577411,"url":"https://github.com/21-dot-dev/swift-tor","last_synced_at":"2026-06-04T23:03:08.444Z","repository":{"id":355363956,"uuid":"1138624716","full_name":"21-DOT-DEV/swift-tor","owner":"21-DOT-DEV","description":"Swift wrapper around the Tor daemon with a concurrency-first client API. Provides SOCKS5 proxy, onion-routing, and Tor control protocol. iOS, macOS, and Linux.","archived":false,"fork":false,"pushed_at":"2026-05-14T18:11:43.000Z","size":11386,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-29T00:27:19.723Z","etag":null,"topics":["anonymity","async","c-language","censorship-resistance","daemon","hidden-services","networking","onion-routing","privacy","proxy","socks5","spm","swift","swift-concurrency","swift-library","swift-package-manager","swift6","tor","tor-control","tor-network"],"latest_commit_sha":null,"homepage":"https://docs.21.dev/documentation/tor/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/21-DOT-DEV.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":".github/AGENTS.md","dco":null,"cla":null}},"created_at":"2026-01-20T23:02:08.000Z","updated_at":"2026-05-28T05:50:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/21-DOT-DEV/swift-tor","commit_stats":null,"previous_names":["21-dot-dev/swift-tor"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/21-DOT-DEV/swift-tor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/21-DOT-DEV%2Fswift-tor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/21-DOT-DEV%2Fswift-tor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/21-DOT-DEV%2Fswift-tor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/21-DOT-DEV%2Fswift-tor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/21-DOT-DEV","download_url":"https://codeload.github.com/21-DOT-DEV/swift-tor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/21-DOT-DEV%2Fswift-tor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33923218,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anonymity","async","c-language","censorship-resistance","daemon","hidden-services","networking","onion-routing","privacy","proxy","socks5","spm","swift","swift-concurrency","swift-library","swift-package-manager","swift6","tor","tor-control","tor-network"],"created_at":"2026-06-04T23:03:07.745Z","updated_at":"2026-06-04T23:03:08.435Z","avatar_url":"https://github.com/21-DOT-DEV.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Apple Platforms](https://github.com/21-DOT-DEV/swift-tor/actions/workflows/apple-builds.yml/badge.svg)](https://github.com/21-DOT-DEV/swift-tor/actions/workflows/apple-builds.yml) [![Docker Builds](https://github.com/21-DOT-DEV/swift-tor/actions/workflows/docker-builds.yml/badge.svg)](https://github.com/21-DOT-DEV/swift-tor/actions/workflows/docker-builds.yml) [![MIT License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![Swift Versions](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2F21-DOT-DEV%2Fswift-tor%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/21-DOT-DEV/swift-tor) [![Platforms](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2F21-DOT-DEV%2Fswift-tor%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/21-DOT-DEV/swift-tor)\n\n# swift-tor\n \n Swift package that embeds Tor (`libtor`) and provides a Swift-concurrency-first API (`TorClient`), plus Tor control protocol utilities (including ephemeral onion service management).\n\n## Contents\n\n- [Features](#features)\n- [Platforms](#platforms)\n- [Installation](#installation)\n- [Quick Start (Basic)](#quick-start-basic)\n- [Creating a Hidden Service](#creating-a-hidden-service)\n- [Demo](#demo)\n- [Testing](#testing)\n- [Roadmap](#roadmap)\n- [Security](#security)\n- [Contributing](#contributing)\n- [License](#license)\n \n ## Features\n \n - **Embedded Tor**: run Tor in-process (via the `libtor` product)\n - **High-level API**: `TorClient` actor to start/stop Tor and observe events\n - **Control protocol**: `TorControlClient` for `GETINFO`, `SIGNAL`, `ADD_ONION`, `DEL_ONION`, etc.\n - **Onion services**: create/delete ephemeral v3 onion services\n - **Caching**: optional `cacheDirectory` to reuse consensus/descriptor cache across runs\n - **Apple-only networking helper**: `URLSessionConfiguration` + `TorClient.makeURLSession()` (guarded by `canImport(CFNetwork)`)\n \n ## Platforms\n \n - **macOS**: 15+\n - **iOS**: 18+\n - **Linux**: Ubuntu 22.04+ (via Docker)\n \n\u003e [!IMPORTANT]  \n\u003e **tvOS/watchOS/visionOS are not supported.** Tor's codebase relies on UNIX process primitives (`fork`, `execve`, `daemon`, `setuid`) that Apple prohibits on these platforms. These restrictions are enforced at the App Store review level and would cause runtime crashes.\n \n ## Installation\n \n This package uses Swift Package Manager.\n \n ### Xcode\n \n 1. Go to `File \u003e Add Packages...`\n 2. Enter the package URL: `https://github.com/21-DOT-DEV/swift-tor`\n 3. Select the desired version\n \n ### Package.swift\n \n Add the dependency:\n \n ```swift\n .package(url: \"https://github.com/21-DOT-DEV/swift-tor\", from: \"0.1.0\"),\n ```\n\n\u003e [!WARNING]  \n\u003e This package is pre-1.0 ([SemVer major version zero](https://semver.org/#spec-item-4)). The public API is not stable and may change with any release. Pin a version using `exact:` to avoid unexpected breaking changes.\n\n Then add `Tor` as a dependency:\n \n ```swift\n .target(\n     name: \"MyApp\",\n     dependencies: [\n         .product(name: \"Tor\", package: \"swift-tor\")\n     ]\n )\n ```\n \n ## Quick Start (Basic)\n \n Start Tor, wait for bootstrap, and get a SOCKS endpoint:\n \n ```swift\n import Tor\n \n let config = TorConfiguration.makeDefault()\n let client = TorClient(configuration: config)\n \n try await client.start()\n try await client.waitUntilBootstrapped()\n \n let socks = await client.socksEndpoint\n ```\n \n ### Faster bootstraps with `cacheDirectory`\n\n\u003e [!TIP]  \n\u003e Reusing a `cacheDirectory` across runs can significantly reduce bootstrap time.\n \n ```swift\n import Tor\n import Foundation\n \n let tempDataDir = FileManager.default.temporaryDirectory\n     .appendingPathComponent(\"tor-data-\\(UUID().uuidString)\")\n     .path\n \n let cacheDir = FileManager.default.temporaryDirectory\n     .appendingPathComponent(\"tor-cache\")\n     .path\n \n try? FileManager.default.createDirectory(atPath: cacheDir, withIntermediateDirectories: true)\n \n let config = TorConfiguration(\n     dataDirectory: tempDataDir,\n     cacheDirectory: cacheDir,\n     socksPort: .ephemeral\n )\n \n let client = TorClient(configuration: config)\n try await client.start()\n try await client.waitUntilBootstrapped()\n ```\n \n ### Apple-only: URLSession via Tor\n\n\u003e [!NOTE]  \n\u003e This helper requires `CFNetwork` and is only available on Apple platforms.\n\n```swift\n #if canImport(CFNetwork)\n let session = try await client.makeURLSession()\n let (data, _) = try await session.data(from: URL(string: \"https://check.torproject.org/api/ip\")!)\n #endif\n ```\n \n ## Creating a Hidden Service\n\nCreate an ephemeral v3 onion service that forwards traffic to a local server:\n\n```swift\nimport Tor\n\n// Start Tor first\nlet client = TorClient(configuration: .makeDefault())\ntry await client.start()\ntry await client.waitUntilBootstrapped()\n\n// Get the control client\nlet control = try await client.control()\n\n// Create an ephemeral onion service\n// - Maps port 80 on the .onion to localhost:8080\n// - Private key is discarded (service won't survive restart)\nlet service = try await control.addOnion(\n    key: .newV3(discardPrivateKey: true),\n    ports: [.toLocalPort(80, localPort: 8080)]\n)\n\nprint(\"🧅 Hidden service running at: \\(service.onionAddress)\")\n// e.g., \"duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion\"\n\n// Your local HTTP server on port 8080 is now accessible via Tor!\n// Users can reach it at: http://\u003cserviceID\u003e.onion/\n\n// When done, clean up\ntry await control.delOnion(service)\nawait client.stop()\n```\n\n### Persistent Hidden Services\n\nTo create a hidden service that survives restarts, keep the private key:\n\n```swift\n// Create service and get the private key\nlet service = try await control.addOnion(\n    key: .newV3(discardPrivateKey: false),  // Keep the key\n    ports: [.toLocalPort(443, localPort: 8443)]\n)\n\n// Save service.privateKey securely for later use\nlet privateKey = service.privateKey!  // e.g., \"ED25519-V3:base64...\"\n\n// Later, recreate the same .onion address:\nlet restoredService = try await control.addOnion(\n    key: .providedV3(privateKey),\n    ports: [.toLocalPort(443, localPort: 8443)]\n)\n// restoredService.onionAddress == service.onionAddress\n```\n\n\u003e [!WARNING]  \n\u003e Store private keys securely (e.g., Keychain on Apple platforms). Anyone with the private key controls the .onion address.\n \n ## Demo\n \n Run the bundled demo:\n \n ```bash\n swift run TorDemo\n ```\n \n The demo starts Tor, fetches a clearnet URL via Tor, fetches an `.onion`, and creates/deletes an ephemeral onion service.\n \n ## Testing\n \n Run unit tests:\n \n ```bash\n swift test\n ```\n \n Integration tests are **env-gated** and skipped by default:\n \n ```bash\n TOR_INTEGRATION_TESTS=1 swift test --filter IntegrationTests\n ```\n \n ## Roadmap\n \n - **Linux support**: ✅ complete (Phase 1)\n - **Remove libbsd dependency**: ✅ complete (Phase 2)\n - **iOS Target Refactor**: 🔜 planned (Phase 3)\n - **Binary Size Optimization**: 🔜 planned (Phase 3.5)\n \nSee [roadmap.md](.specify/memory/roadmap.md) for full details.\n \n ## Security\n\nFor information on reporting security vulnerabilities in swift-tor, see [SECURITY.md](SECURITY.md). For other 21-DOT-DEV projects, see the [organization Security Policy](https://github.com/21-DOT-DEV/.github/blob/main/SECURITY.md).\n\n\u003e [!CAUTION]  \n\u003e Tor can't \"fix\" unsafe application behavior. Review the [Tor Project guidance](https://support.torproject.org/) on staying anonymous. Avoid logging sensitive information (credentials, onion private keys). Consider your threat model — Tor integration is only one part of privacy/security.\n\n ## Contributing\n\nContributions welcome! Please read the [21-DOT-DEV contributing guidelines](https://github.com/21-DOT-DEV/.github/blob/main/CONTRIBUTING.md) for general workflow. For swift-tor specific guidance and AI-assisted development, see [AGENTS.md](AGENTS.md).\n\n ## License\n \n This project is licensed under the MIT License. See `LICENSE`.\n \n Tor source code is vendored in `Vendor/tor` and is subject to its own license(s). See `Vendor/tor/LICENSE`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F21-dot-dev%2Fswift-tor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F21-dot-dev%2Fswift-tor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F21-dot-dev%2Fswift-tor/lists"}