I am building a P2P C++ application that uses tor as a socks proxy to connect to the internet. This P2P app will only connect to other users running the same application, so all the communication between this app and the wild world would be through Tor.

I am very new to Tor, but the first thing I think of would be to configure Tor to create a hidden service (with an .onion url) and that would be the IP for other users to connect to? Is this procedure is safe enough or should I try other methods? Could I connect to a port of that specific .onion url to avoid http requests (myonionurlf2e9k51a.onion:8751)?

  • Using P2P over Tor is generally frowned upon due to its high level of bandwidth use... – Richard Horrocks Nov 15 '15 at 22:09
  • @RichardHorrocks Not all P2P applications need a high level of bandwidth. There are a lot of P2P applications that use less bandwidth that normal websites. – Nathan Parker Nov 18 '15 at 20:19

"the IP for other users to connect to?"

Onion services don't use IPs. You should use SOCKS5's remote hostname functionality, this hands over the hostname to Tor and will ensure you do not try to resolve the onion address locally and potentially leak DNS. I have a simple C implementation of SOCKS5 intended for use with Tor here.

"configure Tor to create a hidden service"

You probably want to use the control port for this. You can create and maintain a connection to the control port and use the ADD_ONION request to create the onion. This will make the app more portable, one of the issues with ricochet was that it (until recently) came with its own copy of Tor and used that exclusively which mean in tor enforcing environments like Whonix or Subgraph it resulted in Tor-over-Tor situations.

"Could I connect to [any] port [...] to avoid http requests?"

Yes, onion services are not exclusively http, it's just a very common use case for them. They can transport any kind of arbitrary TCP connection, as exampled by ricochet (mentioned above) which uses it's own protocol.

Some thoughts I'd like to add

Ricochet is already an extensible peer-to-peer service written in C++. You should consider making your functionality a general extension of ricochet. This will remove a lot of the effort on your part of re-inventing the wheel.

Imagine a scenario where two users wish to establish a peer-to-peer channel over onions. Alice wants to talk to Bob, so Alice's client makes a connection to bob.onion. Alice is able to establish a connection and talk to Bob and Alice knows that she is talking to Bob with reasonable certainty because Bob has shown proof of ownership of the public key that the b.onion address is derived from...but how does Bob know that the incoming connection is from Alice? All Bob can see is a connection from his Tor instance to his service.

Two possible solutions that are currently implemented are:

  1. mod_onions for Prosody in XMPP. This uses a pre-existing XMPP extension XEP-0220. In this scenario, Bob provides the incoming claimed Alice with a cryptographic nonce and then Bob makes a connection to Alice's onion. Bob then requests the nonce value through the outbound connection made, this proves that the incoming Alice connection and the connection he made out to Alice are, at least, controlled by the same entity. On DNS this protection is quite weak, on onions this is a much stronger form of verification.

  2. ricochet instead requires that the incoming Alice connection take a 16 byte value provided by Bob concatenated with another 16 byte value provided by Alice as the key to an HMAC-SHA256 of Alice's onion address and Bob's onion address concatenated. This resulting hash is then signed by Alice's onion's private key. This signature then acts as proof that the incoming Alice owns the private key associated with Alice's onion address.

Be very careful when approaching these sorts of problems, rolling your own crypto is almost invariably bad, another reason to use preexisting solutions.

Similarly be very careful writing C++ or any non-memory-safe language.


Secure enough for what? Surely using the method you provide data will be encrypted on transport by the tor network, but it would not provide any method of integrity.

If what you plan is doing a peer to peer chat application, it already exists,it's called Ricochet. If not, it's open source and it's design can help you find ways to achieve what you want.


You need to maintain just three main rules using Tor as a transport for your app, they are :

  • Never resolve! Use an option to pass all the resolving behavior on a proxy side
  • Use telnet-based Tor control protocol It's a simple task to communicate through a TCP stream to Tor binary using cleartext protocol. Do not use external libraries for that - standard socket library + LibC string functions are just fine to do the job.
  • Use no IP addresses Try to utilize ini-like config file with IP's for Tor SOCKS proxy, Tor control port and IP addresses for both, I.e. a proxy can be open for a local network too and have an address like on a LAN interface only, but the ControlPort will be secured on, for example

That's it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.