A fully featured Tor Daemon and Onion Routing Client for your React Native iOS and Android Project! 📲 🔐 🌐
In your project:
npm i react-native-tor
// for ios builds
npx pod-install
then
import Tor from "react-native-tor";
// Initialize the module
const tor = Tor();
//...
const makeTorRequest = async()=>{
// Start the daemon and socks proxy (no need for Orbot and yes iOS supported!)
await tor.startIfNotStarted();
try{
// Use built in client to make REST calls to .onion urls routed through the Sock5 proxy !
const resp = await tor.get('http://some.onion',{'Authorization': 'sometoken'});
// Note: self signed https endpoints, custom headers and multiform/json payloads supported!
await tor.post('https://someother.onion',JSON.stringify(resp.json),{'Authorization': 'sometoken'},true);
} catch(error){
// Catch a network or server error like you normally with any other fetch library
}
}
makeTorRequest();
💥
If you think this is awesome, please consider contributing to Privacy and Opensource !
~~~ Beta software provided as is. I Accept no responsibility for use or misuse of Tor or this package. ~~~
Privacy is important and should not be hard.
Embeds Tor Daemon + Onion Routing into your App, removing the dependency on Orbot and allowing Tor usage on IOS
This module uses multiple layers:
npm install react-native-tor
or
yarn add react-native-tor
Android: open android/app/build.gradle
and add
implementation files("../../node_modules/react-native-tor/android/libs/sifir_android.aar")
iOS:
cd ios/
pod install
iOS Projects note:
Build Settings > Build Options > Enable Bitcode
to No
for both Debug and Release.import Tor from "react-native-tor";
// Intialize the module with some settings
const tor = Tor({
stopDaemonOnBackground :true, // Auto shut down daemon when app in background
});
// Start and boostrap the Tor daemon returning the socksProxy port that can be
// used to direct requests to.
const socksProxy = await tor.startIfNotStarted();
try{
// Use module built in proxied client to make a get request
const resp = tor.get('');
} catch(error){
// Client throws on Network errors and Response codes > 299
}
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`);
// ... moar writes
} catch (err) {
console.error('Error SendingTcpMSg', err);
}
await conn.close();
}
Note:
onData(data,null)
onData
will be called with the second parameter containing the error string (ie onData(null,'some error')
;
Please reference Typescript defs and JSDoc for details.
Documentation is a WIP, Contribute!
const tor = Tor({ ...params });
defined as :
/**
* Tor module factory function
* @param stopDaemonOnBackground
* @default true
* When set to true will shutdown the Tor daemon when the application is backgrounded preventing pre-emitive shutdowns by the OS
* @param startDaemonOnActive
* @default false
* When set to true will automatically start/restart the Tor daemon when the application is bought back to the foreground (from the background)
* @param os The OS the module is running on (Set automatically and is provided as an injectable for testing purposes)
* @default The os the module is running on.
*/
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 = {
/**
* Send a GET request routed through the SOCKS proxy on the native side
* Starts the Tor Daemon automatically if not already started
* @param url
* @param headers
* @param trustSSL @default true When true accepts *any* SSL cert for the onion URL
*/
get(url: string, headers?: RequestHeaders, trustSSL?: boolean): Promise<ProcessedRequestResponse>;
/**
* Send a POST request routed through the SOCKS proxy on the native side
* Starts the Tor Daemon automatically if not already started
* @param url
* @param body JSON encoded (JSON.stringify) string of the payload to send * *Note*: Client will treat the body as a JSON string and set request header accordingly
* The client also supports sending the payload as `application/x-www-form-urlencoded` by setting the `Content-Type` header to `application/x-www-form-urlencoded` in the header param
* @param headers
* @param trustSSL @default true When true accepts *any* SSL cert for the onion URL
*/
post(url: string, body: RequestBody[RequestMethod.POST], headers?: RequestHeaders, trustSSL?: boolean): Promise<ProcessedRequestResponse>;
/**
* Send a DELETE request routed through the SOCKS proxy on the native side
* Starts the Tor Daemon automatically if not already started
* @param url
* @param headers
* @param trustSSL @default true When true accepts *any* SSL cert for the onion URL
*/
delete(url: string, body?: RequestBody[RequestMethod.DELETE], headers?: RequestHeaders, trustSSL?: boolean): Promise<ProcessedRequestResponse>;
/** Starts the Tor Daemon if not started and returns a promise that fullfills with the socks port number when boostraping is complete.
* If the function was previously called it will return the promise without attempting to start the daemon again.
* Useful when used as a guard in your transport or action layer
*/
startIfNotStarted(): Promise<SocksPortNumber>;
/**
* Stops a running Tor Daemon
*/
stopIfRunning(): Promise<void>;
/**
* Returns the current status of the Daemon
* Some :
* NOTINIT - Not initialized or run (call startIfNotStarted to the startDaemon)
* STARTING - Daemon is starting and bootsraping
* DONE - Daemon has completed boostraing and socks proxy is ready to be used to route traffic.
* <other> - A status returned directly by the Daemon that can indicate a transient state or error.
*/
getDaemonStatus(): Promise<string>;
/**
* Accessor the Native request function
* Should not be used unless you know what you are doing.
*/
request: NativeTor['request'];
/**
* Factory function for creating a peristant Tcp connection to a target
* See createTcpConnectio;
*/
createTcpConnection: typeof createTcpConnection;
};
Tcp Stream API:
interface TcpStream {
/**
* Called to close and end the Tcp connection
*/
close(): Promise<boolean>;
/**
* Send a message (write on socket)
* @param msg
*/
write(msg: string): Promise<boolean>;
}
/**
* /**
* Factory function to create a persistent TcpStream connection to a target
* Wraps the native side emitter and subscribes to the targets data messages (string).
* The TcpStream currently 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 data read (by calling onData(data,null). If an error is received or the connection is dropped it onData will be called
* with the second parameter containing the error string (ie onData(null,'some error');
* Note: 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.
* @param param {target: String, writeTimeout: Number} :
* `target` onion to connect to (ex: kciybn4d4vuqvobdl2kdp3r2rudqbqvsymqwg4jomzft6m6gaibaf6yd.onion:50001)
* 'writeTimeout' in seconds to wait before timing out on writing to the socket (Defaults to 7)
* @param onData TcpConnDatahandler node style callback called when data or an error is received for this connection
* @returns TcpStream
*/
const createTcpConnection = async (
param: { target: string; writeTimeout?: number },
onData: TcpConnDatahandler
): Promise<TcpStream>
You can also check the provided Example Application for a quick reference.
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:
Funding = More time to focus on what matters.
If you found this useful please help fund development for this and other privacy focused projects,
Send some Bitcoin/SATS: bc1q8442hgk32h2x5undjlnu56q2ewnmnpys30zstj
Fund Tor projects and exit nodes https://blog.torproject.org/support-tor-network-donate-exit-node-providers
Librepay: https://liberapay.com/gabidi/
See the contributing guide to learn how to contribute to the repository and the development workflow.
There are 3 layers of libraries this project relies on:
Depending on the level of modifications needed you will need to work with 1 or all 3 layers.
https://github.com/Sifir-io/sifir-rs-sdk/ Use the helper scripts/
for both the Android Tor and iOS Tor modules to compile them.
./android/libs/
./ios/library/universal/
a. Modify Pod spec file if neededyarn bootstrap
cd example
yarn start
yarn ios
or yarn android
Know someone who want to add a bit more privacy to their Application / Product ? Help them out and tell them about this repo!
Author: Sifir-io
Source Code: https://github.com/Sifir-io/react-native-tor
#react-native #react #mobile-apps