VPN. We all use, or at least have heard of, a VPN. But most of us don’t have a clear insight into what it actually is. Some will say they use it for online streaming, others for gaming, to exploit better prices, or even for “suspicious” activities. However, the core purpose of a VPN is privacy. And how good does your VPN score on it? Because there are too many paid reviews or misinformation out there. Considering all this, I started searching for a convenient and trustworthy way to check what and why. Unfortunately, still haven’t found any. And what do you do when you don’t find any? Yes, you guessed right, you develop your own. So, after much searching, Googling, asking, testing, disappointment, AI-ing, frustration, and insomnia, I am glad to introduce you to my solution: the JimCKD VPN AudiTool.
My tool “targets” to the main features that a VPN matters. I wish I could have found a way to check their log policy, but I still didn’t find a simple way to do so, so I had to rely on their written policy and well-regarded independent organisations. Still, you can use my tool (under development) to test your VPN and get a clearer picture of what it does and how. My core purpose is to provide my source code, and others in the community provide feedback or even improve it. My “dream” is to be the “one-stop-for-all” regarding VPN testing. Are you willing to help me? Thanks in advance.
PS: It is tested on MacOS, Android, and Windows OSes. Some instabilities were present (e.g., after a System Update), but no major issues were found. Sometimes, it might appear to do nothing (e.g., in 8.8.8.8), but please be patient; it works. You might notice a freeze at the TOR check at the initial run, but don’t worry, it works. Please note that I am not accountable for anything that might go wrong. The code is provided as it is, and that’s why I chose the “Source Code” way instead of an .exe, .apk. Feel free to compile it and build it if you want to, though. Any feedback or improvement is welcome. Part of the code is tidied or improved with the help of Gemini. Tested on Code:Blocks and C4Droid IDEs. Written on C++.
The Source Code
/*
* PROJECT: JimCKD VPN AudiTool
* COMPILATION INSTRUCTIONS (Windows / Code::Blocks):
* * 1. Linker Settings:
* – Go to Project -> Build options… -> Linker settings.
* – In ‘Link libraries’, add: ws2_32
* – In ‘Link libraries’, add: iphlpapi
Other Linker Settings:
-static-libgcc -static-libstdc++ -static
* * 2. Compiler Standard:
* – Go to Compiler Settings -> Compiler Flags.
* – Check: [-std=c++11] (or higher).
* * 3. Linux/Android (DroidC):
* – No extra steps needed. Simply compile and run.
*/
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstring>
#include <chrono>
#include <fstream>
#include <sstream>
#include <ctime>
#include <thread>
#include <limits>
#include <numeric>#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <direct.h>
#include <conio.h>
#pragma comment(lib, “iphlpapi.lib”)
#pragma comment(lib, “ws2_32.lib”)
#define GetCurrentDir _getcwd
#define close_socket closesocket
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <termios.h>
#include <fcntl.h>#ifdef __APPLE__
#include <TargetConditionals.h>
#endif#define GetCurrentDir getcwd
#define close_socket close
int _kbhit() {
struct termios oldt, newt;
int ch, oldf;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF) { ungetc(ch, stdin); return 1; }
return 0;
}
#endifstd::string global_log = “”;
void log_out(std::string text) {
std::cout << text << std::flush;
global_log += text;
}void clean_str(std::string &s) {
s.erase(std::remove(s.begin(), s.end(), ‘\n’), s.end());
s.erase(std::remove(s.begin(), s.end(), ‘\r’), s.end());
}void emergency_shutdown(std::string reason) {
log_out(“\n\n[!!!] EMERGENCY SHUTDOWN: ” + reason + “\n”);
log_out(“[!] Connection is unsafe. Terminating to prevent leaks…\n”);
#ifdef _WIN32
system(“ipconfig /flushdns > nul”);
WSACleanup(); exit(1);
#else
_exit(1);
#endif
}long long get_raw_latency(const char* ip_addr) {
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(80);
if (inet_pton(AF_INET, ip_addr, &server.sin_addr) <= 0) return -1;#ifdef _WIN32
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
DWORD timeout = 1200;
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout));
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
#else
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 200000;
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv));
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
#endifif (sock < 0 || (int)sock == -1) return -1;
// — PING: Network RTT —
auto t1 = std::chrono::high_resolution_clock::now();if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
close_socket(sock); return -1;
}auto t2 = std::chrono::high_resolution_clock::now();
close_socket(sock);
return std::chrono::duration_cast<std::chrono::milliseconds>(t2 – t1).count();
}bool detect_vpn_tunnels() {
bool found = false;
#ifdef _WIN32
ULONG outBufLen = 15000;
PIP_ADAPTER_ADDRESSES pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);
if (pAddresses && GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &outBufLen) == NO_ERROR) {
for (PIP_ADAPTER_ADDRESSES pCurr = pAddresses; pCurr != NULL; pCurr = pCurr->Next) {
// ignore interfaces
if (pCurr->OperStatus != IfOperStatusUp || pCurr->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue;// 1. just check
// 53 = IF_TYPE_PROP_VIRTUAL (Virtual adapters)
// 131 = IF_TYPE_TUNNEL (IP Tunnels)
if (pCurr->IfType == 53 || pCurr->IfType == 131) {
found = true;
break;
}// 2. TAP/TUN drivers)
std::wstring wsDesc(pCurr->Description);
std::string desc(wsDesc.begin(), wsDesc.end());
std::transform(desc.begin(), desc.end(), desc.begin(), ::tolower);if (desc.find(“tap”) != std::string::npos ||
desc.find(“tun”) != std::string::npos ||
desc.find(“vpn”) != std::string::npos ||
desc.find(“wireguard”) != std::string::npos ||
desc.find(“virtual”) != std::string::npos ||
desc.find(“secure”) != std::string::npos) {
found = true;
break;
}
}
}
if(pAddresses) free(pAddresses);
#else
// Logic Android/Linux (DroidC)
int s = socket(AF_INET, SOCK_DGRAM, 0);
if (s >= 0) {
struct ifconf ifc; char buf[4096];
ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf;
if (ioctl(s, SIOCGIFCONF, &ifc) >= 0) {
int n = ifc.ifc_len / sizeof(struct ifreq);
for (int i = 0; i < n; i++) {
std::string n_str = ifc.ifc_req[i].ifr_name;
std::transform(n_str.begin(), n_str.end(), n_str.begin(), ::tolower);
// Linux/Android VPN tun, wg, ppp, utun
if (n_str.find(“tun”) != std::string::npos ||
n_str.find(“wg”) != std::string::npos ||
n_str.find(“ppp”) != std::string::npos ||
n_str.find(“utun”) != std::string::npos) {
found = true;
break;
}
}
}
close_socket(s);
}
#endif
return found;
}
std::string Jim_Net_Get(const char* host, const char* path, bool full_resp = false, int family = AF_INET, const char* port = “80”) {
struct addrinfo hints, *res;
std::memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(host, port, &hints, &res) != 0) return “Error: DNS”;#ifdef _WIN32
SOCKET sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
DWORD timeout = 4000;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
#else
int sock = (int)socket(res->ai_family, res->ai_socktype, res->ai_protocol);
struct timeval tv; tv.tv_sec = 4; tv.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
#endifif (sock < 0 || (int)sock == -1) { freeaddrinfo(res); return “Error: Socket”; }
if (connect(sock, res->ai_addr, (int)res->ai_addrlen) < 0) {
freeaddrinfo(res); close_socket(sock); return “Error: Timeout”;
}
std::string req = std::string(“GET “) + path + ” HTTP/1.1\r\nHost: ” + host + “\r\nUser-Agent: JimDiag/8.6\r\nConnection: close\r\n\r\n”;
send(sock, req.c_str(), (int)req.length(), 0);
char t_buf[8192]; std::string resp; int b;
while ((b = recv(sock, t_buf, sizeof(t_buf)-1, 0)) > 0) {
resp.append(t_buf, b);
}
freeaddrinfo(res); close_socket(sock);
if (full_resp) return resp;
size_t pos = resp.find(“\r\n\r\n”);
return (pos != std::string::npos) ? resp.substr(pos + 4) : “Error: Data”;
}int main() {
#ifdef _WIN32
WSADATA wsa; WSAStartup(MAKEWORD(2,2), &wsa);
#endifbool is_online = false;
for(int i = 0; i < 3; i++) {
if (get_raw_latency(“1.1.1.1”) != -1) {
is_online = true;
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(600));
}if (!is_online) {
std::cout << “\n==============================================\n”;
std::cout << ” [!] ERROR: You appear to be offline.\n”;
std::cout << ” [!] Please check your internet connection.\n”;
std::cout << “==============================================\n”;
std::cout << “\nPress Enter or Return button to exit…”;
std::cin.ignore((std::numeric_limits<std::streamsize>::max)(), ‘\n’);
std::cin.get();
#ifdef _WIN32
WSACleanup();
#endif
return 1;
}int score = 0;
std::vector<std::string> reasons, tips;log_out(“==============================================\n”);
log_out(” JIMCKD VPN AudiTOOL – v8.6 (Test)\n”);
log_out(“==============================================\n”);log_out(“\n[0] ESTABLISHING BASELINE (Identity Check):\n”);
std::string baseline_raw = Jim_Net_Get(“ip-api.com”, “/line/?fields=query,country”);
std::stringstream ss_base(baseline_raw);
std::string real_ip, real_country;
std::getline(ss_base, real_ip);
std::getline(ss_base, real_country);
clean_str(real_ip); clean_str(real_country);log_out(” -> Detected Source: ” + real_ip + ” (” + real_country + “)\n”);
std::cout << ” Is this your UNPROTECTED location? (y/n): “;
std::string is_real; std::cin >> is_real;
log_out(“\n”);bool has_tun = detect_vpn_tunnels();
log_out(“[1] INTERFACE & PERFORMANCE:\n”);
log_out(std::string(” -> Tunnel/VPN: “) + (has_tun ? “ACTIVE (+20)\n” : “NONE\n”));
if(has_tun) score += 20;
else {
log_out(” [!] Info: No virtual interface found. Traffic is not tunneled.\n”);
reasons.push_back(“- Interface: Unsecured (No VPN).”);
tips.push_back(“[!] Use a VPN to encrypt your connection.”);
}
long long l1 = get_raw_latency(“1.1.1.1″);
log_out(std::string(” -> Network Ping (reference only): “) + (l1 > 0 ? std::to_string(l1) : “Timeout”) + “ms\n”);
if(l1 > 150) tips.push_back(“[!] High Latency: Optimize MTU settings (try 1350 for OpenVPN) or change server.”);std::string ipv4 = Jim_Net_Get(“icanhazip.com”, “/”);
clean_str(ipv4);
log_out(“[2] PUBLIC IPv4: ” + ipv4 + “\n”);log_out(“[3] ISP & SYSTEM AUDIT:\n”);
std::string isp_raw = Jim_Net_Get(“ip-api.com”, “/line/?fields=country,timezone,offset,isp,org,mobile,proxy,hosting”);
std::stringstream ss_isp(isp_raw);
std::string line; std::vector<std::string> lines;
while (std::getline(ss_isp, line)) {
if (!line.empty() && line.back() == ‘\r’) line.pop_back();
lines.push_back(line);
}
if (lines.size() >= 8) {
log_out(” -> Country: ” + lines[0] + “\n”);
log_out(” -> ISP: ” + lines[3] + “\n”);
log_out(” -> Organization: ” + lines[4] + “\n”);bool is_proxy_api = (lines[6].find(“true”) != std::string::npos);
log_out(std::string(” -> Proxy/DC Status: “) + (is_proxy_api ? “YES (+15)” : “No”) + “\n”);
if(is_proxy_api) score += 15;log_out(“[3a] TOR NODE CHECK: “);
std::string tor_check = Jim_Net_Get(“check.torproject.org”, “/api/ip”);
if (tor_check.find(“\”IsTor\”:true”) != std::string::npos) {
log_out(“DETECTED (+30)\n”);
score += 30; reasons.push_back(“- Identity: Tor Exit Node.”);
} else { log_out(“NONE\n”); }log_out(“[3b] VPN/PROXY RECOGNITION: “);
std::string org_l = lines[4];
std::transform(org_l.begin(), org_l.end(), org_l.begin(), ::tolower);std::string vpn_name = “Unknown/Custom”;
// E-Net Recognition
if (org_l.find(“surfshark”) != std::string::npos) vpn_name = “Surfshark”;
else if (org_l.find(“e-net”) != std::string::npos || org_l.find(“enet”) != std::string::npos) vpn_name = “E-Net Cloud VPN”;
else if (org_l.find(“nord”) != std::string::npos) vpn_name = “NordVPN”;
else if (org_l.find(“m247”) != std::string::npos) vpn_name = “M247 (Infrastructure)”;
else if (org_l.find(“datacamp”) != std::string::npos) vpn_name = “DataCamp (Infrastructure)”;
else if (org_l.find(“proton”) != std::string::npos) vpn_name = “ProtonVPN”;
else if (org_l.find(“mullvad”) != std::string::npos) vpn_name = “Mullvad VPN”;
else if (is_proxy_api) vpn_name = lines[4];log_out(“Provider Found -> ” + vpn_name + “\n”);
if (!has_tun) {
if (is_proxy_api ||
org_l.find(“m247”) != std::string::npos ||
org_l.find(“datacamp”) != std::string::npos ||
org_l.find(“choopa”) != std::string::npos ||
org_l.find(“leaseweb”) != std::string::npos ||
org_l.find(“packethub”) != std::string::npos ||
org_l.find(“vultr”) != std::string::npos ||
org_l.find(“ovh”) != std::string::npos ||
org_l.find(“cloud”) != std::string::npos ||
org_l.find(“hosting”) != std::string::npos) {has_tun = true;
score += 20;
log_out(” [!] Heuristic: Traffic routed via known Privacy Provider/Backbone. Status: SECURE.\n”);
}
}std::time_t now = std::time(nullptr);
char time_str[26];
std::string l_os;
#ifdef _WIN32
ctime_s(time_str, sizeof(time_str), &now);
l_os = “Windows”;
#elif __APPLE__
ctime_r(&now, time_str);
#if TARGET_OS_IPHONE
l_os = “iOS”;
#else
l_os = “macOS”;
#endif
#else
ctime_r(&now, time_str);
#ifdef __ANDROID__
l_os = “Android”;
#else
l_os = “Linux”;
#endif
#endifstd::string ts = time_str; if(!ts.empty()) ts.pop_back();
log_out(” -> System Time: ” + ts + “\n”);
log_out(” -> Local OS: ” + l_os + “\n”);
log_out(std::string(” -> Remote OS: “) + (is_proxy_api ? “Masked/Secure (+10)” : “Native OS Visible”) + “\n”);
if(is_proxy_api) score += 10;if (is_real == “y” && lines[0] == real_country) {
reasons.push_back(“- Location: Real country (” + real_country + “) still visible.”);
} else {
score += 10;
}
}log_out(“[4] DNS LEAK TEST: “);
std::string dns_json = Jim_Net_Get(“edns.ip-api.com”, “/json”);
if (lines.size() > 3 && dns_json.find(lines[3]) != std::string::npos) {
log_out(“LEAK DETECTED!\n”);
log_out(” -> Why: Queries handled by ISP: ” + lines[3] + “\n”);
log_out(” -> Risk: Browsing history is visible to ISP.\n”);
reasons.push_back(“- DNS: ISP Leak.”);
tips.push_back(“[!] Change DNS to 1.1.1.1 (Cloudflare) or 9.9.9.9 (Quad9).”);
} else {
log_out(“SECURE (+15)\n -> Info: DNS provider is hidden from ISP.\n”);
score += 15;
}log_out(“[5] SSL/HSTS TEST: “);
std::string hsts_check = Jim_Net_Get(“www.google.com”, “/”, true);
if (hsts_check.find(“Strict-Transport-Security”) != std::string::npos) {
log_out(“SECURE (+10)\n -> Info: Server enforces strict HTTPS. All the essential protocols (e.g., oVPN, etc.) and measures (anti-bleeding, etc.) are properly tuned.\n”);
score += 10;
} else {
log_out(“VULNERABLE!\n -> Risk: Potential for SSL Strip attacks.\n”);
reasons.push_back(“- SSL: No HSTS.”);
}log_out(“[6] IPv6 LEAK TEST: “);
std::string ipv6_leak = Jim_Net_Get(“ipv6.icanhazip.com”, “/”, false, AF_INET6);
clean_str(ipv6_leak);
if (ipv6_leak.find(“Error”) != std::string::npos) {
log_out(“SECURE (+15)\n -> Info: No IPv6 traffic leaked.\n”);
score += 15;
} else {
log_out(“LEAK DETECTED!\n”);
log_out(” -> Address: ” + ipv6_leak + “\n”);
log_out(” -> Risk: Real IPv6 exposed outside VPN tunnel.\n”);
reasons.push_back(“- IPv6: Identity leak.”);
tips.push_back(“[!] Disable IPv6 in settings (Not mandatory, if properly tuned).”);
}log_out(“[7] WebRTC PRIVACY: “);
std::string webrtc = Jim_Net_Get(“browserleaks.com”, “/ip”);
if (webrtc.find(“Error”) != std::string::npos) {
log_out(“SECURE (+10)\n -> Info: Local IP hidden from STUN probes.\n”);
score += 10;
} else {
log_out(“LEAK DETECTED!\n -> Risk: Local network IP is exposed.\n”);
reasons.push_back(“- WebRTC: Local IP leak.”);
tips.push_back(“[!] Disable WebRTC or use a well-regarded extension with ‘Prevent WebRTC leak’ on your browser’s settings (FireFox-based, fully supported. Chromium-based, partially-supported).”);
}log_out(“[8] PORT PROBE (8.8.8.8):\n”);
int ports[] = {22, 53, 80, 443}; bool p443 = false;
for(int p : ports) {
int ps = (int)socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in a; a.sin_family = AF_INET; a.sin_port = htons(p);
inet_pton(AF_INET, “8.8.8.8”, &a.sin_addr);#ifdef _WIN32
DWORD p_timeout = 1000;
setsockopt(ps, SOL_SOCKET, SO_SNDTIMEO, (const char*)&p_timeout, sizeof(p_timeout));
#else
struct timeval p_tv; p_tv.tv_sec = 1; p_tv.tv_usec = 0;
setsockopt(ps, SOL_SOCKET, SO_SNDTIMEO, (const char*)&p_tv, sizeof(p_tv));
#endifbool open = (connect(ps, (struct sockaddr*)&a, sizeof(a)) == 0);
if(p == 443 && open) p443 = true;
log_out(std::string(” -> Port “) + std::to_string(p) + “: ” + (open ? “OPEN\n” : “CLOSED\n”));
close_socket(ps);
}
if(p443) log_out(” -> Stealth Hint: Port 443 is open. Use TCP/443 for DPI bypass if needed.\n”);log_out(“[9] JITTER & STABILITY TEST: “);
std::vector<long long> samples;
int lost_packets = 0;
int total_probes = 5;
for(int i=0; i<total_probes; i++) {
long long lat = get_raw_latency(“1.1.1.1”);
if(lat != -1) samples.push_back(lat);
else lost_packets++;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}long long jitter = 0;
if(samples.size() > 1) {
for(size_t i=1; i<samples.size(); i++) jitter += std::abs(samples[i] – samples[i-1]);
jitter /= (samples.size()-1);
log_out(std::to_string(jitter) + “ms fluctuation | Packet Loss: ” + std::to_string((lost_packets * 100) / total_probes) + “%\n”);
if(jitter > 20) tips.push_back(“[!] High Jitter: Connection may be unstable for VOIP/Streaming.”);
if(lost_packets > 0) tips.push_back(“[!] Packet Loss: Data is being dropped. This may be due to high MTU or poor server quality.”);
} else if(lost_packets == total_probes) {
log_out(“100% Packet Loss (Timeout)\n”);
} else { log_out(“N/A\n”); }log_out(“[10] VPN SPAM/AD FILTERING: “);
std::string spam_test = Jim_Net_Get(“doubleclick.net”, “/”);
if (spam_test.find(“Error”) != std::string::npos || spam_test.empty()) {
log_out(“ACTIVE (+10)\n -> Info: VPN blocks known trackers/spam.\n”);
score += 10;
} else {
log_out(“INACTIVE\n -> Risk: VPN does not filter ad/tracking domains.\n”);
reasons.push_back(“- Spamlist: Inactive (Ads/Trackers visible).”);
}log_out(“[11] NO-LOGS POLICY INTEGRITY AUDIT: “);
if (lines.size() >= 5) {
std::string org_l = lines[4];
std::transform(org_l.begin(), org_l.end(), org_l.begin(), ::tolower);
if (org_l.find(“amazon”) != std::string::npos || org_l.find(“google”) != std::string::npos || org_l.find(“microsoft”) != std::string::npos) {
log_out(“WEAK\n -> Risk: Infrastructure is public cloud. No-Logs policy is hard to verify.\n”);
reasons.push_back(“- No-Logs: Infrastructure is not proprietary.”);
}
// E-Net Recognition
else if (org_l.find(“m247”) != std::string::npos || org_l.find(“datacamp”) != std::string::npos ||
org_l.find(“mullvad”) != std::string::npos || org_l.find(“proton”) != std::string::npos ||
org_l.find(“e-net”) != std::string::npos || org_l.find(“enet”) != std::string::npos) {
log_out(“STRONG (+10)\n -> Info: Provider uses privacy-focused infrastructure.\n”);
score += 10;
} else {
log_out(“UNVERIFIED\n -> Info: Infrastructure profile is unknown.\n”);
}
} else { log_out(“N/A\n”); }log_out(“[12] DNS HIJACKING TEST: “);
std::string hijack_raw = Jim_Net_Get(“ip-api.com”, “/line/?fields=query”);
clean_str(hijack_raw);
if (hijack_raw != ipv4 && hijack_raw.find(“Error”) == std::string::npos) {
log_out(“SUSPICIOUS!\n -> Risk: DNS resolver IP mismatch. Potential redirection.\n”);
reasons.push_back(“- DNS: Potential Hijacking/Redirection.”);
} else {
log_out(“SECURE (+10)\n -> Info: DNS responses match your exit node IP.\n”);
score += 10;
}// — SPEEDTEST LINKS —
log_out(“[13] SPEEDTEST (Ookla, visit these links:):\n”);
log_out(” -> Web: https://www.speedtest.net\n”);
log_out(” -> CLI: https://www.speedtest.net/apps/cli\n”);
// ———————————-
// — SECTION [14]: LOCAL VPN PORT AUDIT —
log_out(“[14] LOCAL VPN PORT AUDIT: “);// standard VPN
int vpn_ports[] = {1194, 51820, 500, 4500, 1701};
bool vpn_port_active = false;for(int p : vpn_ports) {
#ifdef _WIN32
// UDP socket Windows
SOCKET s_vpn = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s_vpn == INVALID_SOCKET) continue;
#else
// UDP socket Linux/Android
int s_vpn = socket(AF_INET, SOCK_DGRAM, 0);
if (s_vpn < 0) continue;
#endifstruct sockaddr_in v_addr;
v_addr.sin_family = AF_INET;
v_addr.sin_port = htons(p);
v_addr.sin_addr.s_addr = htonl(INADDR_ANY);// bind fails VPN service
if (bind(s_vpn, (struct sockaddr*)&v_addr, sizeof(v_addr)) < 0) {
vpn_port_active = true;
close_socket(s_vpn);
break;
}
close_socket(s_vpn);
}if (vpn_port_active) {
log_out(“ACTIVE PORTS DETECTED (+10)\n”);
if (!has_tun) {
has_tun = true; // Fail-safe trigger
log_out(” [!] Heuristic: Hidden VPN service detected via active local ports.\n”);
}
score += 10;
} else {
log_out(“NONE\n”);
}
// — END OF SECTION [14] —log_out(“\n>>> SECURITY SCORE: ” + std::to_string(score) + “/140\n”);
if(!reasons.empty()) {
log_out(“\nANALYSIS:\n”);
for(auto& r : reasons) log_out(r + “\n”);
log_out(“\nRECOMMENDATIONS:\n”);
for(auto& t : tips) log_out(t + “\n”);
}std::cout << “\nSave Report? (y/n): “;
std::string s_choice; std::cin >> s_choice;
if (s_choice == “y” || s_choice == “Y”) {
char cwd[1024];
std::string full_path = “jim_diag_report.txt”;
if (GetCurrentDir(cwd, sizeof(cwd)) != NULL) {
#ifdef _WIN32
full_path = std::string(cwd) + “\\” + “jim_diag_report.txt”;
#else
full_path = std::string(cwd) + “/” + “jim_diag_report.txt”;
#endif
}
std::ofstream o(“jim_diag_report.txt”);
o << global_log; o.close();
log_out(“\n[SUCCESS] Report saved at:\n” + full_path + “\n”);
}std::cout << “\nActivate Live Guardian Mode? (y/n): “;
std::cin >> s_choice;
if (s_choice == “y” || s_choice == “Y”) {
log_out(“\n[SYSTEM] GUARDIAN MODE: ACTIVE (Press ‘q’ to stop)\n”);
while (true) {
if (_kbhit()) {
#ifdef _WIN32
char c = _getch();
#else
char c = getchar();
#endif
if (c == ‘q’ || c == ‘Q’) break;
}
if (!detect_vpn_tunnels()) emergency_shutdown(“VPN DISCONNECTED”);
std::string cur_ip = Jim_Net_Get(“icanhazip.com”, “/”);
clean_str(cur_ip);
if (cur_ip.find(“Error”) == std::string::npos && cur_ip != ipv4)
emergency_shutdown(“IP LEAK DETECTED (New IP: ” + cur_ip + “)”);
log_out(” [LIVE] Status: PROTECTED | IP: ” + ipv4 + ” [Press ‘q’ to exit]\r”);
std::this_thread::sleep_for(std::chrono::seconds(5));
}
}log_out(“\nExiting JimCKD VPN AudiTool. Stay safe!\n”);
std::cin.ignore((std::numeric_limits<std::streamsize>::max)(), ‘\n’);
std::cout << “Press Enter or Return button to exit…”;
std::cin.get();
#ifdef _WIN32
WSACleanup();
#endif
return 0;
}
Keynotes
- Because of some limitations, it is best to download my zip file: CodeFiles9
- Ping relies on only three samples for testing. Don’t consider it accurate.
- The Guardian Mode tests every 5 seconds for any changes or when the Kill Switch is triggered. If any issue is found, the tool self-terminates to prevent any leaks. You can quit it by pressing ‘q’ (without the quotes) at any time.
- If no connection is present, the tool warns you.
- The provided score is a way to check how good is your VPN, and if it scores well in what matters.
- It is cross-platform.
- For simplicity and versatility, no GUI. I want it to work even in a toaster.
- It is best to run it on an IDE (written in C++).
- I can’t guarantee there won’t be any major issues, though I didn’t notice any (what I noticed, I corrected).
- Part of the code was improved by Gemini (believe me, it was handy).
- You can learn how the IP sites work.
- Feel free to modify it as you wish. Any feedback is welcome.
- This will be my core test engine for my upcoming “The Best VPNs” article (in combination with other tools).
- For any speed test, please visit Ookla. For developing my own speed test, I found it more than a challenge, so I didn’t.
- AudiTool is a combination of the words’ audit’ and ‘tool’. No relation to the Audi car company.
- It is still under development.




Another major update today. Feel free to check it.
1) Includes Spamlist.
2) A way to check for no logs policy.
3) DNS hijacking.
And more…
Stay tuned!
Thanks for the great work, much appreciated.
Thank you very much!
Please, check the latest and updated code. I improved and updated it after feedback. Thanx!