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