arti/crates/arti-client
eta a12fffc66a Improve docs of more (potentially re-exported) arti-client types
Most of the structs in `arti-client` have example code now, to give a
clearer idea of how they're used.

Annoyingly, a lot of the types exposed in `arti-client` are actually
re-exports, which makes documentation a bit harder: example code that
references other parts of `arti-client` can't actually be run as a
doctest, since the crate it's in is a dependency of `arti-client`.

We might be able to fix this in future by doing the documentation in
`arti-client` itself, but rustdoc seems to have some weird behaviours
there that need to be investigated first (for example, it seems to merge
the re-export and original documentation, and also put the re-export
documentation on the `impl` block for some reason).

For now, though, this commit just writes the docs from the point of view
of an `arti-client` consumer, removing notes specific to the crate in
which they're defined. It's not ideal, but at least the end user
experience is decent.
2021-10-29 14:06:06 +01:00
..
examples Improve top-level arti-client documentation, add example code 2021-10-28 19:20:42 +01:00
src Improve docs of more (potentially re-exported) arti-client types 2021-10-29 14:06:06 +01:00
Cargo.toml Upgrade to latest tracing-{subscriber,journald} 2021-10-23 22:23:26 -04:00
README.md Update README.md files 2021-10-28 19:59:22 -04:00

README.md

arti-client

High-level functionality for accessing the Tor network as a client.

Overview

The arti-client crate aims to provide a safe, easy-to-use API for applications that want to use Tor network to anonymize their traffic. It hides most of the underlying detail, letting other crates decide how exactly to use the Tor crate.

This crate is part of Arti, a project to implement Tor in Rust. It is the highest-level library crate in Arti, and the one that nearly all client-only programs should use. Most of its functionality is provided by lower-level crates in Arti.

⚠ Warnings ⚠

Note that Arti is a work in progress; although we've tried to write all the critical security components, you probably shouldn't use Arti in production until it's a bit more mature.

Also note that all of the APIs for this crate, and for Arti in general, are not the least bit stable. If you use this code, please expect your software to break on a regular basis.

Using arti-client

The main entry point for this crate is the [TorClient], an object that lets you make connections over the Tor network.

Calling [TorClient::bootstrap] establishes a connection to the Tor network, pulling in necessary state about network consensus as required. This state gets persisted to the locations specified in the [TorClientConfig].

A client can then be used to make connections over Tor with [TorClient::connect], which accepts anything implementing [IntoTorAddr]. This returns a [DataStream], an anonymised TCP stream type that implements AsyncRead and AsyncWrite, as well as the Tokio versions of those traits if the tokio crate feature is enabled.

The [TorAddr] type is intended to ensure that DNS lookups are done via the Tor network instead of locally. Doing local DNS resolution can leak information about which hostnames you're connecting to to your local DNS resolver (i.e. your ISP), so it's much better to let Arti do it for you to maintain privacy.

If you really want to connect to a raw IP address and know what you're doing, take a look at [TorAddr::dangerously_from] -- but be careful!

Example: making connections over Tor

// The client config includes things like where to store persistent Tor network state.
let config = TorClientConfig::sane_defaults()?;
// Arti needs a handle to an async runtime in order to spawn async tasks.
// (See "Multiple runtime support" below.)
let rt = tor_rtcompat::tokio::current_runtime()?;

// Start the Arti client, and let it bootstrap a connection to the Tor network.
// (This takes a while to gather the necessary consensus state, etc.)
let tor_client = TorClient::bootstrap(rt, config).await?;

// Initiate a connection over Tor to example.com, port 80.
let mut stream = tor_client.connect(("example.com", 80), None).await?;

use futures::io::{AsyncReadExt, AsyncWriteExt};

// Write out an HTTP request.
stream
    .write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")
    .await?;

// IMPORTANT: Make sure the request was written.
// Arti buffers data by default due to the design of the Tor protocol, so flushing the
// buffer is usually required.
stream.flush().await?;

// Read and print the result.
let mut buf = Vec::new();
stream.read_to_end(&mut buf).await?;

println!("{}", String::from_utf8_lossy(&buf));
#

More advanced usage

This version of Arti includes basic support for "stream isolation": the ability to ensure that different TCP connections ('streams') go over different Tor circuits (and thus different exit nodes, making them originate from different IP addresses).

This is useful to avoid deanonymising users by correlation: for example, you might want a Tor connection to your bank and a Tor connection to an online forum to use different circuits, to avoid the possibility of the two identities being linked by having the same source IP.

Streams can be isolated in two ways:

  • by calling [TorClient::isolated_client], which returns a new [TorClient] whose streams will use a different circuit
  • by generating [IsolationToken]s, and passing them in via [ConnectPrefs] to [TorClient::connect].

Multiple runtime support

Arti uses the [tor_rtcompat] crate to support multiple asynchronous runtimes; currently, both Tokio and async-std are supported.

Functions in this crate, like [TorClient::bootstrap], will expect a type that implements [tor_rtcompat::Runtime], which can be obtained:

  • for Tokio:
    • by calling [tor_rtcompat::tokio::current_runtime], if a Tokio reactor is already running
    • by calling [tor_rtcompat::tokio::create_runtime], to start a new reactor if one is not already running
    • by manually creating a TokioRuntimeHandle from an existing Tokio runtime handle
  • for async-std:
    • by calling [tor_rtcompat::async_std::current_runtime], which will create a runtime or retrieve the existing one, if one has already been started

Feature flags

tokio -- (Default) Build with support for the Tokio backend.

async-std -- Build with support for the async_std backend.

experimental-api -- Build with experimental, unstable API support. Note that these APIs are NOT covered by semantic versioning guarantees: we might break them or remove them between patch versions.

License: MIT OR Apache-2.0