Introduction
At the time of writing, there is no Tor library that supports .NET Core. I needed one for one of my projects I am working on, called NTumbleBit, so I had to create it myself. It is not a full featured library, but rather a lean, robust one. Only implements essential Tor features.
- I want to make anonymous requests.
- I want to make requests to onion APIs.
These are the most common use cases that lead someone to use Tor inside their application. This library aims to serve these basic needs and nothing more.
Understanding the Problem
Why we even need to use a third party library for Tor.
Quote:
Some people attempt to launch the Tor process on their local machine, giving the process a port number for the SOCKS port, and then configure their browser to point to the Tor process. This will not work.
Tor is a SOCKS proxy which means that it is able to connect to IP addresses and ports, but it does not understand HTTP requests.
(Source)
Configure Tor
- Download Tor Expert Bundle
- Download the torrc config file sample
- Place torrc in the proper default location (depending on your OS) and edit it:
- Optionally uncomment and edit the SocksPort, if you don't uncomment, it will default to 9050 port anyway
- The default ControlPort in the sample is 9051, optionally edit it.
- Modify the password hash
- To run my tests, for the
ControlPortPassword = "ILoveBitcoin21"
the hash should be: HashedControlPassword 16:0978DBAF70EEB5C46063F3F6FD8CBC7A86DF70D2206916C1E2AE29EAF6
- For your application, you should use different one, a more complicated one. Then start tor like this:
tor --hash-password password
where password is the password
you've chosen. It will give you the HashedControlPassword
.
- Start tor, it will listen to the ports you set in the config file.
SocksPort vs ControlPort
Quote:
The control port is used for controlling Tor, usually via other software like Arm. The Socks port is the port running as a SOCKS5 proxy. This is the one you want to use. Please note that Tor is not an HTTP proxy, so your script will need to be configured to use a SOCKS5 proxy.
(Source)
Build & Test
If you are in a hurry, you can skip this section and just get the NuGet package and use it. Now get .NET Core, if you haven't already done so and fire up a terminal:
git clone https://github.com/nopara73/DotNetTor
cd DotNetTor/
dotnet restore
cd src/DotNetTor.Tests/
dotnet test
How to Use It
Consider the following simple console app, where:
- I write out your real IP
- Your Tor IP
- Change your Tor circuit
- Finally, write out the changed Tor IP.
var requestUri = "http://icanhazip.com/";
using (var httpClient = new HttpClient())
{
var message = httpClient.GetAsync(requestUri).Result;
var content = message.Content.ReadAsStringAsync().Result;
Console.WriteLine($"Your real IP: \t\t{content}");
}
using (var httpClient = new HttpClient(new SocksPortHandler("127.0.0.1", socksPort: 9050)))
{
var message = httpClient.GetAsync(requestUri).Result;
var content = message.Content.ReadAsStringAsync().Result;
Console.WriteLine($"Your Tor IP: \t\t{content}");
var controlPortClient = new ControlPort.Client
("127.0.0.1", controlPort: 9051, password: "ILoveBitcoin21");
controlPortClient.ChangeCircuitAsync().Wait();
message = httpClient.GetAsync(requestUri).Result;
content = message.Content.ReadAsStringAsync().Result;
Console.WriteLine($"Your other Tor IP: \t{content}");
}
Conclusion
While I did not provide a full-featured Tor library, but rather a minimal one, without any external dependency, I know I covered the most popular needs in a platform (.NET Core) where there is nothing else available at the time of writing.
Acknowledgements
- Originally, the
SocksPort
part of this project was a leaned down, modified and .NET Core ported version of the SocketToMe project. - Originally, the
ControlPort
part of this project was a leaned down, modified and .NET Core ported version of the Tor.NET project. - At this point of the development, you can still find parts of the former project in the codebase, however the latter has been completely replaced.
Updates
- 24th January, 2017
- Version 2.1 is out
- Limitations are removed
- You can request different addresses within the same `
HttpClient
`
- 19th January, 2017
- Version 2.0 is out
- Simplified usage
- Not breaking old userspace
- Async support
- Bug fixes
- Performance increase
- 27th December, 2016
- Fix torrc sample reference link
- Fix some typo and formatting mistake
- Add updates section
- Change licence to MIT