React Native Tor
A fully featured Tor Daemon and Onion Routing Client for your React Native iOS and Android Project!
:calling: :closed_lock_with_key: :globe_with_meridians:
TL;DR
In your project:
npm i react-native-tor
// for ios builds
npx pod-install
then
import Tor from "react-native-tor";
const tor = Tor();
const makeTorRequest = async()=>{
await tor.startIfNotStarted();
try{
const resp = await tor.get('http://some.onion',{'Authorization': 'sometoken'});
await tor.post('https://someother.onion',JSON.stringify(resp.json),{'Authorization': 'sometoken'},true);
} catch(error){
}
}
makeTorRequest();
:boom:
If you think this is awesome, please consider contributing to Privacy and Opensource !
Highlights
- Embeds a fully functional Tor Daemon, with its own circuit (non exit) removing the dependency on Orbot and allowing Tor usage on IOS.
- Provides a Socks5 proxy enabled REST client to allow you to make Rest calls on Onion URLs directly from JS just as you would with Axios, Frisbee etc..
- Tcp socket support via a event like interface!
- [WIP] Start a hidden service accessible via an Onion URL directly on your phone (in final test for upcoming 0.0.2 release)
- Provides guard functions and state management options to autostart/stop the daemon when REST calls are initiated and/or the application is backgrounded/foregrounded
- TS Typed API for sanity.
Disclaimer
~~~ Beta software provided as is. I Accept no responsibility for use or misuse of Tor or this package. ~~~
Why This ?
Privacy is important and should not be hard.
- Users shouldn't be expected to install 3rd party apps and setup custom VPNS to get more privacy.
- Devs shouldn't have to jump through hoops to get Onion urls routing correctly
- React native is an awesome tool and this brings awesome privacy to it.
What This Does ?
Embeds Tor Daemon + Onion Routing into your App, removing the dependency on Orbot and allowing Tor usage on IOS
How it Does it ?
This module uses multiple layers:
- Pre-compiled rust sdk (sifir-rs-sdk) for the Tor daemon and Control code (Check CODE section for details)
- Swift/Kotlin wrappers to access and control the daemon and provide native proxified clients.
- TS/JS Native bridges to allow access from your components.
Requirements
- ios > 11.1
- Android minSdk > 26
Installation
npm install react-native-tor
or
yarn add react-native-tor
iOS Projects note:
- iOS 11.1 > only: Support iOS Version is 11.1 and higher (#6)
- Bitcode not supported: Set
Build Settings > Build Options > Enable Bitcode
to No
for both Debug and Release.
REST Usage Example
import Tor from "react-native-tor";
const tor = Tor({
stopDaemonOnBackground :true,
});
const socksProxy = await tor.startIfNotStarted();
try{
const resp = tor.get('');
} catch(error){
}
Socket Usage Example
import Tor from 'react-native-tor';
const tor = Tor();
await tor.startIfNotStarted()
const target = 'kciybn4d4vuqvobdl2kdp3r2rudqbqvsymqwg4jomzft6m6gaibaf6yd.onion:50001';
const conn = await tor.createTcpConnection({ target }, (data, err) => {
if(err){
console.error('error sending msg',err);
return
}
console.log('recieved tcp msg', data);
} );
try {
await conn.write(`{ "id": 1, "method": "blockchain.scripthash.get_balance", "params": ["716decbe1660861c3d93906cb1d98ee68b154fd4d23aed9783859c1271b52a9c"] }\n`);
await conn.write(`{ "id": 2, "method": "blockchain.scripthash.get_balance", "params": ["716decbe1660861c3d93906cb1d98ee68b154fd4d23aed9783859c1271b52a9c"] }\n`);
} catch (err) {
console.error('Error SendingTcpMSg', err);
}
await conn.close();
}
Note:
- The current TcpStream implementation emits per line of data received. That is it reads data from the socket until a new line is reached, at which time it will emit the string line received (by calling
onData(data,null)
- Ergo sum the current implementation is only suited for text data that is line delineated (Electrum server, etc..)
- Future implementations will support constant streams of buffered base64 data.
- If an error is received, or the connection is dropped
onData
will be called with the second parameter containing the error string (ie onData(null,'some error')
;
- Receiving an 'EOF' error from the target we're connected to signifies the end of a stream or the target dropped the connection.
- This will cause the module to drop the TcpConnection and remove all data event listeners.
- Should you wish to reconnect to the target you must initiate a new connection by calling createTcpConnection again.
API reference
Please reference Typescript defs and JSDoc for details.
Documentation is a WIP, Contribute!
const tor = Tor({ ...params });
defined as :
declare const _default: ({ stopDaemonOnBackground, startDaemonOnActive, os, }?: {
stopDaemonOnBackground?: boolean | undefined;
startDaemonOnActive?: boolean | undefined;
os?: "ios" | "android" | "windows" | "macos" | "web" | undefined;
}) => TorType;
This returns an instance of TorType module which gives control over the Tor daemon and access to the Socks5 enabled client:
declare type TorType = {
get(url: string, headers?: RequestHeaders, trustSSL?: boolean): Promise<ProcessedRequestResponse>;
post(url: string, body: RequestBody[RequestMethod.POST], headers?: RequestHeaders, trustSSL?: boolean): Promise<ProcessedRequestResponse>;
delete(url: string, body?: RequestBody[RequestMethod.DELETE], headers?: RequestHeaders, trustSSL?: boolean): Promise<ProcessedRequestResponse>;
startIfNotStarted(): Promise<SocksPortNumber>;
stopIfRunning(): Promise<void>;
getDaemonStatus(): Promise<string>;
request: NativeTor['request'];
createTcpConnection: typeof createTcpConnection;
};
Tcp Stream API:
interface TcpStream {
close(): Promise<boolean>;
write(msg: string): Promise<boolean>;
}
const createTcpConnection = async (
param: { target: string; writeTimeout?: number },
onData: TcpConnDatahandler
): Promise<TcpStream>
You can also check the provided Example Application for a quick reference.
Acknowledgments
- Torproject for everything they do.
- @afilini for his amazing work on libtor and constant support!
- @GodSaysHodl for his generosity and backing of FOSS Bitcoin projects with financial bounties and encouragement.
Contributing to Privacy and Opensource
This module is the product of love and dedication for principles I believe in.
If you find this module helpful or useful please do consider support it by contributing in the best way that suits you, here are some ideas:
Fund Privacy and Open Source !
Funding = More time to focus on what matters.
If you found this useful please help fund development for this and other privacy focused projects,
Coding
- Check the TODO list below for some ideas on items flagged as valuable for users of Tor.
- Check Development section below for instructions
See the contributing guide to learn how to contribute to the repository and the development workflow.
Development and Building from Scratch
Building for Native projects
There are 3 layers of libraries this project relies on:
- The Sifir Rust SDK
providing lower level control of the Tor daemon and where building the iOS and Android libraries is done.
- The iOS and Android wrapper Code to bridge and provide a socks client.
This is where the mobile native code interacts with the prebuilt Rust libraries with step1 via FFI and exposes that functionality
to React. It is also where the proxied client forwards requests recieved from React.
- The Typescript module. This is the module React interacts with.
Depending on the level of modifications needed you will need to work with 1 or all 3 layers.
Building Android AAR and adding to Android Project
https://github.com/Sifir-io/sifir-rs-sdk/
Use the helper scripts/
for both the Android Tor and iOS Tor modules to compile them.
Adding compiled libs to this repo
- Copy the compiled Android AAR to the folder
./android/libs/
- Copy the compiled Universal iOS dylib to the folder
./ios/library/universal/
a. Modify Pod spec file if needed
- Bootstrap and run the example app to verify all is good
yarn bootstrap
cd example
- in one terminal
yarn start
- in another terminal
yarn ios
or yarn android
Modify Native code
Modify Typescript Code
Share and Tell your friends
Know someone who want to add a bit more privacy to their Application / Product ? Help them out and tell them about this repo!
TODOs
WIP
- Better API Docs
- Event emitter from Rust to Native on Boostrap status
- Enable secret service API
- Start new hidden service on phone.
- Restore hidden service from key.
- Capture daemon logs into files.
Backlog
- Search for available ports for socks proxy for iOS
- Return a Context API (status, etc..) as part of the package to make it easier for developers to build reactive components on topof.
- Build on Request capability
- PUT calls
- DELETE
Sockets
- Streaming ?
Investigate stability builds on older mobile API's (Currently minSdk is Android 26 and iOS 10)
- Investigate the possibility of creating a NetworkExtension on iOS which act as a VPN for the app which regular REST libaries can be used on.
License
MIT