So you just decided that your applications need a way to reach an endpoint under relative anonymity yet with simplicity in mind. That might be a good choice! Far too much of our traffic goes through bulk surveillance networks placed by three-letter agencies and other profiteers looking to capitalize off or monitor your precious data. So let's route our data through Tor, and make it a bit harder for the d-bags to know who or where we are.
That being said, Tor is not the one answer to all of your problems. Tor by no means guarantees your anonymity or security during every situation, and precautions should be taken when designing your application if you do not wish for it to be easily identified or manipulated. It remains up to you to make sure that your application is designed with safety in mind. Also remember that when handing your trust to the Tor network, your traffic is only encrypted all the way to the Tor exit node. People can instead log (and manipulate, if you're the node operator) all your traffic from there. They'll just have a harder time pinpointing where it's coming from. Use encryption as needed.
The code provided in this article uses the socks5-cpp library.
Full main code snippet at the bottom of the page.
1. What we need
Obviously we will need Tor. Go to their website and download the Expert bundle, and extract it to a folder named "Tor" on your desktop for now.
We will code this for Windows, and we're going to use the socks5-cpp
library. The code should be easy enough to port to most platforms though.
Let's start with including the stuff we need in our main
#include "socks.h"
#include <iostream>
using namespace std;
The library includes everything we need to start using Winsock and Tor as a proxy. Obviously, we have to have an instance of Tor running and listening on whatever port (usually 9050) on the local computer. Let's start by initializing Winsock and the SocksClient class provided by socks5-cpp in the socks
header.
int main()
{
WSADATA wsadata;
WSAStartup((WORD)0x202, &wsadata);
socks5cpp::SocksClient sockCli("127.0.0.1:9050", "google.com:80");
WSACleanup();
return 0;
}
That would be what we need for now. The SocksClient
constructor takes two arguments.
First the SOCKS5 proxy IP or domain name, which in our case is 127.0.0.1
(localhost) and port, 9050
in this case, where tor is waiting for our program.
The second argument is the IP or domain name of whom we want to connect to.
2. Creating our socket and connecting to the host
The library will be connecting the socket for us based off the info we gave it upon construction. Just add these few lines to the program before the call to WSACleanup
and return
SOCKET sock = 0;
if (sockCli.connect(sock) < 0 ||
!sock) {
cout << "fault at connect:" << WSAGetLastError() << endl;
WSACleanup();
cin.ignore();
return -1;
}
if (sockCli.getState() == sockCli.Closed) {
cout << "fault at connect:" << WSAGetLastError() << ". Connection closed." << endl;
WSACleanup();
cin.ignore();
return -1;
}
Now if our program hasn't returned at this point our connection to the host via Tor should be established.
At this point I modified the library slightly to make it easier in our specific use case, since we're connecting to a domain name. Replace lines 143
-147
in the file socks.cpp
with:
buffer.push_back(0x03); // IPv4 = 0x01, domain name = 0x03, IPv6 = 0x04
//buffer.push_back(targetUrl.ipv4[0]); // connecting to IPv4
//buffer.push_back(targetUrl.ipv4[1]);
//buffer.push_back(targetUrl.ipv4[2]);
//buffer.push_back(targetUrl.ipv4[3]);
buffer.push_back(targetUrl.ip.length()); // connecting to domain name
for(int i = 0; i < targetUrl.ip.length(); ++i)
buffer.push_back(targetUrl.ip.c_str()[i]);
3. Let's communicate!!
At this point we should be able to write the host some messages, let's go ahead and make a HTTP request for google.com whom we earlier configured our SocketClient object for staying connected to. Append to main before cleanup:
char buf[4096] = { 0 };
int iRes = -1;
string getReq =
"GET / HTTP/1.1\r\n"
"Host: google.com\r\n"
"\r\n";
iRes = sockCli.sendPacket(sock, getReq.c_str(), getReq.length());
if (iRes != getReq.length()) {
WSACleanup();
cout << "fault at send" << endl;
cin.ignore();
return -1;
}
do {
iRes = sockCli.recvPacket(sock, buf, 4095);
} while (WSAGetLastError() == 10035);
if (iRes < 0) {
cout << "fault at recv: " << WSAGetLastError() << endl;
WSACleanup();
cin.ignore();
return -1;
}
cout << buf << endl;
This code may be dangerous and should only be used if you understand the risks associated with the Tor protocol.
4. Testing our code
By now our code should be executable and enough behavior should be defined for us to try it out. In case you missed something I've posted the full main.cpp
at the bottom of the page. Let's fire up Tor on port 9050 and run our program!
In case you need help with that too, if you extracted the package in the folder "Tor" on your desktop, open up a command prompt, navigate to that folder using the cd
command. Then simply type tor.exe, press enter and leave the window open. You should see something like [notice] Opening Socks listener on 127.0.0.1:9050
followed by Bootstrapped 100%: Done
after a few seconds.
Nice! Now, when we request the resource '/' from google.com on port 80, they respond that the document has moved. To a french address. I'm not french :>.
Let's check our actual IP address out. You should be able to discern how to modify the HTTP request to ask for your IP address from api you choose. In this example I'll use canihazip.com/s
which sends us an answer containing only our perceived IP address upon our request. Here's the new request:
string getReq =
"GET /s HTTP/1.1\r\n"
"Host: canihazip.com\r\n"
"\r\n";
And let's set our initialization of the SocksClient object to canihazip.com as well.
SocksClient sockCli("127.0.0.1:9050", "canihazip.com:80");
Let's run and see what's up.
HTTP/1.1 200 OK
Date: Thu, 29 Jun 2017 17:15:20 GMT
Server: Apache
X-Powered-By: PHP/5.5.9-1ubuntu4.14
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
X-Frame-Options: sameorigin
Content-Length: 12
Content-Type: text/plain
51.15.63.229
That is not my IP address, that's a Tor exit node IP address =)
Success! Torifying an application was really super easy with the help of the socks5-cpp library.
Just remember that the exit node operators can both view and manipulate all traffic, so you'll have to take some further steps to stay anonymous and keep your data private.
Feel free to review the code of the library we used. It's short, concise and easily understandable.
This is my first blog post and I'd love to hear about what you guys think that I can do better.
Full main.cpp
code
#include "socks.h"
#include <iostream>
using namespace std;
int main()
{
WSADATA wsadata;
WSAStartup((WORD)0x202, &wsadata);
socks5cpp::SocksClient sockCli("127.0.0.1:9050", "canihazip.com:80");
SOCKET sock = 0;
if (sockCli.connect(sock) < 0 ||
!sock) {
cout << "fault at connect:" << WSAGetLastError() << endl;
WSACleanup();
cin.ignore();
return -1;
}
if(sockCli.getState() == sockCli.Closed){
cout << "fault at connect:" << WSAGetLastError() << endl;
WSACleanup();
cin.ignore();
return -1;
}
char buf[4096] = { 0 };
int iRes = -1;
string getReq =
"GET /s HTTP/1.1\r\n"
"Host: canihazip.com\r\n"
"\r\n";
iRes = sockCli.sendPacket(sock, getReq.c_str(), getReq.length());
if (iRes != getReq.length()) {
WSACleanup();
cout << "fault at send" << endl;
cin.ignore();
return -1;
}
do {
iRes = sockCli.recvPacket(sock, buf, 4095);
} while (WSAGetLastError() == 10035);
if (iRes < 0) {
cout << "fault at recv: " << WSAGetLastError() << endl;
WSACleanup();
cin.ignore();
return -1;
}
cout << buf << endl;
WSACleanup();
cin.ignore();
return 0;
}
Interesting thoughts
Congratulations @scriptkid! You have received a personal award!
1 Year on Steemit
Click on the badge to view your Board of Honor.
Do not miss the last post from @steemitboard!
Participate in the SteemitBoard World Cup Contest!
Collect World Cup badges and win free SBD
Support the Gold Sponsors of the contest: @good-karma and @lukestokes
Congratulations @scriptkid! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Do not miss the last post from @steemitboard:
Vote for @Steemitboard as a witness to get one more award and increased upvotes!