## Onion Browser
[Official Site][official] | [Support][help] | [Changelog][changelog]
© 2012-2014 [Mike Tigas][miketigas] ([@mtigas](https://twitter.com/mtigas))
A minimal, open-source web browser for iOS that tunnels web traffic through
the [Tor network][tor]. See the [official site][official] for more details
and App Store links.
* **OnionBrowser**: 1.4 (20140201.1) — [See changelog][changelog]
* **[Tor][tor]**: 0.2.4.20 (Dec 23 2013)
* **[libevent][libevent]**: 2.0.21-stable (Nov 18 2012)
* **[OpenSSL][openssl]**: 1.0.1f (Jan 06 2014)
Screenshots: iPhone 4/4S, iPhone 5, iPad 3
#### Integration notes
As of version 1.3.14 (January 30 2014),
Onion Browser responds to two URL schemes: `onionbrowser://` and
`onionbrowsers://`, representing HTTP and HTTPS URLs, respectively. These
work like the URI schemes [in iOS Google Chrome][crios] and other popular
third-party web browsers.
* A URL of `onionbrowser://opennews.org/` will launch Onion Browser and
navigate the app to `http://opennews.org/`.
* A URL of `onionbrowsers://mike.tig.as/` will launch Onion Browser and
navigate the app to `https://mike.tig.as/`.
Allowing your own app to launch Onion Browser instead of Safari works similarly
to [iOS Google Chrome][crios]:
1. Check if Onion Browser is installed by seeing if iOS can open a
2. If so, replace the `http://` prefix with `onionbrowser://` and replace
the `https://` prefix with `onionbrowsers://`.
3. Then tell iOS to open the newly defined URL (`newURL`) by executing
`[[UIApplication sharedApplication] openURL:newURL];`
See [the Google Chrome iOS instructions][crios] for more details -- just note
that you should replace their `googlechrome://` URL schemes with the proper
#### Compilation notes
The app, when compiled, contains static library versions of [Tor][tor] and it's
dependencies, [libevent][libevent] and [openssl][openssl].
The build scripts for Tor and other dependencies are based on
[build-libssl.sh][build_libssl] from [x2on/OpenSSL-for-iPhone][openssliphone].
The scripts are configured to compile universal binaries for armv7 and
i386 (for the iOS Simulator).
The tor `build-tor.sh` script patches one file in Tor (`src/common/compat.c`)
to remove references to `ptrace()` and `_NSGetEnviron()`. This first is only used
for the `DisableDebuggerAttachment` feature (default: True) implemented in Tor
0.2.3.9-alpha. (See [changelog][tor_changelog] and [manual][tor_manual].)
`ptrace()` and `_NSGetEnviron()` calls are not allowed in App Store apps; apps
submitted with `ptrace()` symbols are rejected on upload by Apple's
auto-validation of the uploaded binary. (The `_NSGetEnviron()` code does not
even compile when using iPhoneSDK due to that function being undefined.)
See the patch files in `build-patches/` if you are interested in the changes.
0.2.3.17-beta introduced compiler and linker "hardening" ([Tor ticket 5210][ticket5210]),
which is incompatible with the iOS Device build chain. The app (when building
for iOS devices) is configured with `--disable-gcc-hardening --disable-linker-hardening`
to get around this issue. (Due to the isolation of executable code on iOS devices,
this should not cause a significant change in security.)
Because iOS applications cannot launch subprocesses or otherwise execute other
binaries, the tor client is run in-process in a `NSThread` subclass which
executes the `tor_main()` function (as an external `tor` executable would)
and attempts to safely wrap Tor within the app. (`libor.a` and
`libtor.a`, intermediate binaries created when compiling Tor, are used to
provide Tor.) Side-effects of this method have not yet been fully evaluated.
Management of most tor functionality (status checks, reloading tor on connection
changes) is handled by accessing the Tor control port in an internal, telnet-like
session from the `AppDelegate`.
The app uses a `NSURLProtocol` subclass (`ProxyURLProtocol`), registered to
handle HTTP/HTTPS requests. That protocol uses the `CKHTTPConnection` class
which nearly matches the `NSURLConnection` class, providing wrappers and access
to the underlying `CFHTTP` Core Framework connection bits. This connection
class is where SOCKS5 connectivity is enabled. (Because we are using SOCKS5,
DNS requests are sent over the Tor network, as well.)
(I had WireShark packet logs to support the claim that this app protects all
HTTP/HTTPS/DNS traffic in the browser, but seem to have misplaced them. You'll
have to take my word for it or run your own tests.)
The app uses [Automatic Reference Counting (ARC)][arc] and was developed against
iOS 5.X or greater. (It *may* work when building against iOS 4.X, since most
of the ARC behavior exists in that older SDK, with the notable exception
1. Check Xcode version
2. Build dependencies via command-line
3. Build application in XCode
### Check Xcode version
Double-check that the "currently selected" Xcode Tools correspond to the version
of Xcode you have installed:
For the newer Xcode 4.3+ installed via the App Store, the directory should be
`/Applications/Xcode.app/Contents/Developer`, and not the straight `/Developer`
(used by Xcode 4.2 and earlier). If you have both copies of Xcode installed
(or if you have updated to Xcode 4.3 but `/Developer` still shows), do this:
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
### Building dependencies
**Optional** PGP key verification. (Currently in testing.) The build scripts
for OpenSSL, libevent, and tor, verify that the package downloaded is PGP
signed by one of the users responsible for packaging the library. You'll
need to have GnuPG installed and import their public keys to allow this to
* OpenSSL: [core developers](https://www.openssl.org/about/). 1.0.1f is known
to be signed by Dr Stephen Henson
* libevent: [Nick Mathewson](http://www.wangafu.net/~nickm/)
([0xC2009841](http://www.citi.umich.edu/u/provos/pgp.key)). 2.0.21 is known
to be signed by Nick Matthewson 0x8D29319A (subkey of 0x165733EA).
* tor: [signing key info](https://www.torproject.org/docs/signing-keys.html.en).
0.2.4.20 is known to be signed by Roger Dingledine
If you don't care about PGP key verification, you'll need to run each of
the scripts with the `--noverify` option or change `VERIFYGPG` to `false`
in each of the `build-*.sh` scripts before continuing.)
`cd` to the root directory of this repository and then run these commands in
the following order to build the dependencies. (This can take anywhere between
five and thirty minutes depending on your system speed.)
This should create a `dependencies` directory in the root of the repository,
containing the statically-compiled library files.
### Build OnionBrowser.xcodeproj in Xcode
Open `OnionBrowser/OnionBrowser.xcodeproj`. You should be
able to compile and run the application at this point.
The app and all dependencies are compiled to run against `armv7s` (iPhone 5's
"A6" processor), `armv7`, and `i386` targets, meaning that all devices since the
iPhone 4 (running at least iOS 5.0) and the iOS Simulators should be able to
run the application.
The app currently is not compiled for `arm64` (64-bit ARM processor in the
iPhone 5S) because apps compiled for this target may only support iOS 6.1
and later. This optimization may be revisited once support for iOS 5.X is
dropped at a later date.
### Information for forks
1. If you're distributing an app that builds off of the Onion Browser code,
you need to use your own app name and logo.
2. If you're distributing an app that builds off of the Onion Browser code,
you need to cite Onion Browser within your app's credits as part of
the terms of the normal MIT License.
[See the LICENSE file][license] for information -- generally you need to
include everything from the "ONION BROWSER LICENSE" section down through
the rest of the file, but see the "TRADEMARK / LICENSE / FORK INFORMATION"
3. You'll need to make sure the "Bundle identifier" (under "Info" in the
app's Target Properties) is set to your own identifier and not
4. You'll need to make sure the URL handlers for your app (see *Integration
notes* above) don't conflict with the ones for Onion Browser. Make sure
you edit your `-Info.plist` file and edit values under "URL types".
Change "URL identifier" to your own' app's identifier from #3, change
the URL Schemes to the URL schemes your app should open if another app
tries to open a URL with that prefix. ("test" and "tests" will make
your app open if another app tries to open URLs starting with "test://"
You'll also need to edit code in `AppDelegate.m` that checks for your
bundle identifier and handles these URL protocol prefixes.