tor_stream/
lib.rs

1//! Provides an interface for proxying network streams over the Tor network.
2//!
3//! See [setup] for information on creating a local Tor SOCKS5 proxy.
4//!
5//! # Usage
6//!
7//! If your Tor proxy is running on the default address `127.0.0.1:9050`,
8//! you can use [`TorStream::connect()`]. If that is not the case,
9//! you can specify your address in a call to [`TorStream::connect_with_address()`].
10//!
11//! ```
12//! use tor_stream::TorStream;
13//! use std::io::prelude::*;
14//!
15//! let mut stream = TorStream::connect("www.example.com:80").expect("Failed to connect");
16//!
17//! // The stream can be used like a normal TCP stream
18//!
19//! stream.write_all(b"GET / HTTP/1.1\r\nConnection: Close\r\nHost: www.example.com\r\n\r\n").expect("Failed to send request");
20//!
21//! // If you want the raw stream, call `into_inner()`
22//!
23//! let mut stream = stream.into_inner();
24//!
25//! let mut buf = String::new();
26//! stream.read_to_string(&mut buf).expect("Failed to read response");
27//!
28//! println!("Server response:\n{}", buf);
29//! ```
30//!
31//! # Credits
32//!
33//! This crate is mostly a wrapper about Steven Fackler's [`socks`] crate.
34//!
35//! [setup]: setup/index.html
36//! [`socks`]: https://crates.io/crates/socks
37//! [`TorStream::connect()`]: struct.TorStream.html#method.connect
38//! [`TorStream::connect_with_address()`]: struct.TorStream.html#method.connect_with_address
39
40#![forbid(unsafe_code)]
41
42#[macro_use]
43extern crate lazy_static;
44pub extern crate socks;
45
46pub use socks::ToTargetAddr;
47
48use socks::Socks5Stream;
49use std::io::{self, Read, Write};
50use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpStream};
51use std::ops::Deref;
52
53lazy_static! {
54    /// The default TOR socks5 proxy address, `127.0.0.1:9050`.
55    /// The proxy can be configured in the SOCKS section of [`/etc/tor/torrc`].
56    /// See the [TOR manual] for more information on `torrc`.
57    ///
58    /// [`/etc/tor/torrc`]: file:///etc/tor/torrc
59    /// [TOR manual]: https://www.torproject.org/docs/tor-manual.html.en
60    pub static ref TOR_PROXY: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9050));
61}
62
63/// A stream proxied over the Tor network.
64/// After connecting, it can be used like a normal [`TcpStream`].
65///
66/// [`TcpStream`]: https://doc.rust-lang.org/std/net/struct.TcpStream.html
67pub struct TorStream(TcpStream);
68
69impl TorStream {
70    /// Connects to a destination address over the Tor network.
71    ///
72    /// # Requirements
73    ///
74    /// A Tor SOCKS5 proxy must be running at `127.0.0.1:9050`.
75    /// See [setup] for more details on configuring a local proxy.
76    ///
77    /// If you want to use a different Tor address, use [`connect_with_address`].
78    ///
79    /// [setup]: setup/index.html
80    /// [`connect_with_address`]: struct.TorStream.html#method.connect_with_address
81    pub fn connect(destination: impl ToTargetAddr) -> io::Result<TorStream> {
82        Socks5Stream::connect(TOR_PROXY.deref(), destination)
83            .map(|stream| TorStream(stream.into_inner()))
84    }
85
86    /// Connects to a destination address over the Tor network.
87    /// A Tor SOCKS5 proxy must be running at the `tor_proxy` address.
88    pub fn connect_with_address(
89        tor_proxy: SocketAddr,
90        destination: impl ToTargetAddr,
91    ) -> io::Result<TorStream> {
92        Socks5Stream::connect(tor_proxy, destination).map(|stream| TorStream(stream.into_inner()))
93    }
94
95    /// Gets a reference to the underlying TCP stream.
96    #[inline]
97    pub fn get_ref(&self) -> &TcpStream {
98        &self.0
99    }
100
101    /// Gets a mutable reference to the underlying TCP stream.
102    #[inline]
103    pub fn get_mut(&mut self) -> &mut TcpStream {
104        &mut self.0
105    }
106
107    #[doc(hidden)]
108    #[inline]
109    pub fn unwrap(self) -> TcpStream {
110        self.0
111    }
112
113    /// Unwraps the `TorStream`.
114    #[inline]
115    pub fn into_inner(self) -> TcpStream {
116        self.0
117    }
118}
119
120impl Read for TorStream {
121    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
122        self.0.read(buf)
123    }
124}
125
126impl Write for TorStream {
127    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
128        self.0.write(buf)
129    }
130
131    fn flush(&mut self) -> io::Result<()> {
132        self.0.flush()
133    }
134}
135
136/// # Instructions on setting up a local Tor proxy
137///
138/// First, install Tor locally.
139/// On Linux, you can just install the `tor` package in most cases.
140/// Visit the [Tor installation guide] for more specific instructions.
141///
142/// When Tor is installed, open Tor's configuration `torrc` (`/etc/tor/torrc`) file in an editor,
143/// and make sure the line `SocksPort 9050` is uncommented.
144/// You can then start Tor by running the Tor executable (`/usr/bin/tor`).
145///
146/// To check whether everything is working correctly, run `cargo run`.
147/// If you want to use a special Tor address, you can pass it as first argument
148/// or set the `TOR_PROXY` environment variable:
149///
150/// `cargo run -- 127.0.0.1:9050`
151///
152/// `TOR_PROXY=127.0.0.1:9050 cargo run`
153///
154/// [Tor installation guide]: https://www.torproject.org/docs/installguide.html.en
155#[allow(unused)]
156pub mod setup {}