mysite/public-onion/posts/vpn/index.html

708 lines
33 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en" dir="auto">
<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex, nofollow">
<title>Stealth Trojan VPN Behind Cloudflare Guide | AlipourIm journeys</title>
<meta name="keywords" content="VPN, Trojan, Cloudflare, Xray, 3x-ui, Bypass, Privacy, Debugging">
<meta name="description" content="Introduction
So you want a VPN that doesn&rsquo;t scream &ldquo;I am a VPN&rdquo; to every censor and firewall out there?
Welcome to the world of Trojan over WebSocket &#43; TLS behind Cloudflare.
This guide not only shows you how to set it up but also sprinkles in some debugging magic so you can figure out why things break (and they will break, trust me).
Well anonymise domains and secrets, so substitute with your own:">
<meta name="author" content="Iman Alipour">
<link rel="canonical" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/">
<link crossorigin="anonymous" href="/assets/css/stylesheet.31b150d909186c48d6dbbf653acc2489945fa9ac2c8f8cd3fe8448e89e40fccf.css" integrity="sha256-MbFQ2QkYbEjW279lOswkiZRfqawsj4zT/oRI6J5A/M8=" rel="preload stylesheet" as="style">
<link rel="icon" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/favicon.ico">
<link rel="icon" type="image/png" sizes="16x16" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/favicon-16x16.png">
<link rel="icon" type="image/png" sizes="32x32" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/favicon-32x32.png">
<link rel="apple-touch-icon" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/apple-touch-icon.png">
<link rel="mask-icon" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/safari-pinned-tab.svg">
<meta name="theme-color" content="#2e2e33">
<meta name="msapplication-TileColor" content="#2e2e33">
<link rel="alternate" hreflang="en" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/">
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
</noscript><script>
(function () {
window.goatcounter = { endpoint: "/count" };
const s = document.createElement("script");
s.async = true;
s.src = "/js/count.js";
document.head.appendChild(s);
})();
</script>
<script>
(function () {
const GC = "";
const nf = new Intl.NumberFormat();
const SING = "visit";
const PLUR = "visits";
function ready(fn) {
if (document.readyState === "complete" || document.readyState === "interactive") setTimeout(fn, 0);
else document.addEventListener("DOMContentLoaded", fn);
}
function gcPath() {
try {
return window.goatcounter && window.goatcounter.get_data
? window.goatcounter.get_data().p
: location.pathname;
} catch (_) {
return location.pathname;
}
}
async function fetchCount(path, period) {
try {
const q = new URLSearchParams({ t: String(Date.now()) });
if (period) q.set("start", period);
const url = `${GC}/counter/${encodeURIComponent(path)}.json?${q}`;
const r = await fetch(url, { credentials: "omit" });
if (r.status === 404) return 0;
if (!r.ok) throw 0;
const j = await r.json();
const n = Number(String(j.count).replace(/,/g, ""));
return Number.isFinite(n) ? n : 0;
} catch {
return null;
}
}
const labelVisits = (n) =>
n === null ? "—" : `${nf.format(n)} ${n === 1 ? SING : PLUR}`;
ready(async function () {
const post = document.querySelector(".post-single");
if (post) {
const meta = post.querySelector(
".post-header .post-meta, .post-header .entry-meta, .post-meta"
);
const visits = await fetchCount(gcPath());
if (meta) {
let span = meta.querySelector(".post-views");
if (!span) {
span = document.createElement("span");
span.className = "post-views";
meta.appendChild(span);
}
span.textContent = labelVisits(visits ?? 0);
}
}
const cards = document.querySelectorAll("article.post-entry");
await Promise.all(
Array.from(cards).map(async (card) => {
const meta = card.querySelector(".entry-footer, .post-meta");
const link = card.querySelector("a.entry-link, h2 a, .entry-title a");
if (!meta || !link) return;
try {
const u = new URL(link.getAttribute("href"), location.origin);
if (u.origin !== location.origin) return;
let span = meta.querySelector(".post-views");
if (!span) {
span = document.createElement("span");
span.className = "post-views";
meta.appendChild(span);
}
span.textContent = labelVisits((await fetchCount(u.pathname)) ?? 0);
} catch {}
})
);
const uvEl = document.getElementById("gc_site_visitors_week");
if (uvEl) {
const n = await fetchCount("TOTAL", "week");
uvEl.textContent = n === null ? "—" : nf.format(n);
}
});
})();
</script>
</head>
<body class="" id="top">
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
<header class="header">
<nav class="nav">
<div class="logo">
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/" accesskey="h" title="AlipourIm journeys (Alt + H)">AlipourIm journeys</a>
<div class="logo-switches">
<button id="theme-toggle" accesskey="t" title="(Alt + T)" aria-label="Toggle theme">
<svg id="moon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg id="sun" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
</div>
</div>
<ul id="menu">
<li>
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/" title="Posts">
<span>Posts</span>
</a>
</li>
<li>
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/phd_journey/" title="PhD_journey">
<span>PhD_journey</span>
</a>
</li>
<li>
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/about/" title="About">
<span>About</span>
</a>
</li>
</ul>
</nav>
</header>
<main class="main">
<article class="post-single">
<header class="post-header">
<div class="breadcrumbs"><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/">Home</a>&nbsp;»&nbsp;<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/">Posts</a></div>
<h1 class="post-title entry-hint-parent">
Stealth Trojan VPN Behind Cloudflare Guide
</h1>
<div class="post-meta"><span title='2025-09-09 11:05:00 +0200 +0200'>September 9, 2025</span>&nbsp;·&nbsp;4 min&nbsp;·&nbsp;Iman Alipour
<span class="post-meta-item">
<a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/#isso-thread" class="isso-comments-link">Comments</a>
</span>
</div>
</header>
<div class="post-content"><h2 id="introduction">Introduction<a hidden class="anchor" aria-hidden="true" href="#introduction">#</a></h2>
<p>So you want a VPN that <strong>doesn&rsquo;t scream &ldquo;I am a VPN&rdquo;</strong> to every censor and firewall out there?<br>
Welcome to the world of <strong>Trojan over WebSocket + TLS behind Cloudflare</strong>.</p>
<p>This guide not only shows you how to set it up but also sprinkles in some <strong>debugging magic</strong> so you can figure out why things break (and they <em>will</em> break, trust me).</p>
<p>Well anonymise domains and secrets, so substitute with your own:</p>
<ul>
<li>VPN domain: <code>web.example.com</code></li>
<li>Panel domain: <code>panel.example.com</code></li>
<li>Secret WS path: <code>/stealth-path_abcd1234</code></li>
<li>Password: <code>&lt;PASSWORD&gt;</code></li>
</ul>
<hr>
<h2 id="architecture-at-a-glance">Architecture at a Glance<a hidden class="anchor" aria-hidden="true" href="#architecture-at-a-glance">#</a></h2>
<p>Think of it as a disguise party:</p>
<ul>
<li><strong>Trojan</strong> = the shy guest (your VPN protocol)</li>
<li><strong>Nginx</strong> = the bouncer checking IDs (reverse proxy)</li>
<li><strong>Cloudflare</strong> = the doorman who makes sure nobody sees who&rsquo;s inside (CDN &amp; proxy)</li>
<li><strong>Your fake website</strong> = the mask (camouflage page)</li>
</ul>
<p>Traffic flow:</p>
<div class="mermaid">Client → Cloudflare (443) → Nginx (443) → Trojan (localhost:54321)</div>
<hr>
<h2 id="step-1-panel-setup-panelexamplecom">Step 1: Panel Setup (<code>panel.example.com</code>)<a hidden class="anchor" aria-hidden="true" href="#step-1-panel-setup-panelexamplecom">#</a></h2>
<ul>
<li>Bind the 3x-ui panel to localhost (e.g., <code>127.0.0.1:46309</code>).</li>
<li>Choose a funky <strong>web base path</strong> like <code>/panel-bananas_42/</code>.</li>
<li>Proxy it through Nginx with HTTPS + Basic Auth.</li>
<li>Test it at <code>https://panel.example.com/panel-bananas_42/</code>.</li>
</ul>
<p><strong>Pro tip:</strong> If you see a blank page → your base path is mismatched or Nginx is eating it. Check logs!</p>
<hr>
<h2 id="step-2-trojan-inbound">Step 2: Trojan Inbound<a hidden class="anchor" aria-hidden="true" href="#step-2-trojan-inbound">#</a></h2>
<p>In 3x-ui, create a Trojan inbound:</p>
<ul>
<li>Local port: <code>54321</code></li>
<li>Transport: WebSocket</li>
<li>Path: <code>/stealth-path_abcd1234</code></li>
<li>Security: none</li>
<li>Password: <code>&lt;PASSWORD&gt;</code></li>
</ul>
<hr>
<h2 id="step-3-nginx-for-vpn-domain-webexamplecom">Step 3: Nginx for VPN Domain (<code>web.example.com</code>)<a hidden class="anchor" aria-hidden="true" href="#step-3-nginx-for-vpn-domain-webexamplecom">#</a></h2>
<p>Your Nginx is the gatekeeper. Sample config:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nginx" data-lang="nginx"><span style="display:flex;"><span><span style="color:#66d9ef">server</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">listen</span> <span style="color:#ae81ff">443</span> <span style="color:#e6db74">ssl</span> <span style="color:#e6db74">http2</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">server_name</span> <span style="color:#e6db74">web.example.com</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate</span> <span style="color:#e6db74">/etc/letsencrypt/live/web.example.com/fullchain.pem</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">ssl_certificate_key</span> <span style="color:#e6db74">/etc/letsencrypt/live/web.example.com/privkey.pem</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#75715e"># Fake website at root
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">location</span> <span style="color:#e6db74">/</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">root</span> <span style="color:#e6db74">/var/www/html</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">index</span> <span style="color:#e6db74">index.html</span>;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#75715e"># Real VPN under secret WS path
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> <span style="color:#f92672">location</span> <span style="color:#e6db74">/stealth-path_abcd1234</span> {
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_pass</span> <span style="color:#e6db74">http://127.0.0.1:54321</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_http_version</span> <span style="color:#ae81ff">1</span><span style="color:#e6db74">.1</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Upgrade</span> $http_upgrade;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Connection</span> <span style="color:#e6db74">&#34;upgrade&#34;</span>;
</span></span><span style="display:flex;"><span> <span style="color:#f92672">proxy_set_header</span> <span style="color:#e6db74">Host</span> $host;
</span></span><span style="display:flex;"><span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><hr>
<h2 id="step-4-firewall-rules">Step 4: Firewall Rules<a hidden class="anchor" aria-hidden="true" href="#step-4-firewall-rules">#</a></h2>
<p>Lock things down! Only Cloudflare should reach you:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ufw allow 22/tcp
</span></span><span style="display:flex;"><span>ufw allow 80/tcp
</span></span><span style="display:flex;"><span>ufw allow 443/tcp
</span></span><span style="display:flex;"><span>ufw deny 54321/tcp
</span></span></code></pre></div><hr>
<h2 id="step-5-client-config">Step 5: Client Config<a hidden class="anchor" aria-hidden="true" href="#step-5-client-config">#</a></h2>
<p>Trojan URI:</p>
<div class="mermaid">trojan://&lt;PASSWORD&gt;@web.example.com:443?type=ws&amp;security=tls&amp;host=web.example.com&amp;path=%2Fstealth-path_abcd1234&amp;sni=web.example.com#MyStealthVPN</div>
<p>iOS clients: Shadowrocket, Stash, FoXray<br>
Android clients: v2rayNG, Clash Meta, NekoBox</p>
<hr>
<h2 id="debugging-time-aka-why-the-heck-doesnt-it-work">Debugging Time (a.k.a. “Why the heck doesnt it work?!”)<a hidden class="anchor" aria-hidden="true" href="#debugging-time-aka-why-the-heck-doesnt-it-work">#</a></h2>
<h3 id="symptom-520-unknown-error-cloudflare">Symptom: <strong>520 Unknown Error (Cloudflare)</strong><a hidden class="anchor" aria-hidden="true" href="#symptom-520-unknown-error-cloudflare">#</a></h3>
<ul>
<li>Likely cause: Nginx couldnt talk to Trojan.</li>
<li>Check Nginx error log:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>tail -n <span style="color:#ae81ff">50</span> /var/log/nginx/error.log
</span></span></code></pre></div></li>
<li>If you see <code>upstream sent no valid HTTP/1.0 header</code> → youre mixing HTTPS/HTTP between Nginx and Trojan.</li>
</ul>
<hr>
<h3 id="symptom-526-invalid-ssl-certificate">Symptom: <strong>526 Invalid SSL certificate</strong><a hidden class="anchor" aria-hidden="true" href="#symptom-526-invalid-ssl-certificate">#</a></h3>
<ul>
<li>Cloudflare → Nginx cert mismatch.</li>
<li>Run:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>openssl s_client -connect web.example.com:443 -servername web.example.com -showcerts
</span></span></code></pre></div></li>
<li>Make sure CN = <code>web.example.com</code>. If not, fix your cert.</li>
</ul>
<hr>
<h3 id="symptom-blank-page-on-panel">Symptom: <strong>Blank page on panel</strong><a hidden class="anchor" aria-hidden="true" href="#symptom-blank-page-on-panel">#</a></h3>
<ul>
<li>Check if the base path matches exactly (case-sensitive, slash-sensitive).</li>
<li>Watch for sneaky trailing spaces!</li>
<li>Test locally:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -s -D- http://127.0.0.1:46309/panel-bananas_42/
</span></span></code></pre></div></li>
</ul>
<hr>
<h3 id="symptom-client-wont-connect">Symptom: <strong>Client wont connect</strong><a hidden class="anchor" aria-hidden="true" href="#symptom-client-wont-connect">#</a></h3>
<ul>
<li>Run a WebSocket test:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>curl -i -k -H <span style="color:#e6db74">&#34;Connection: Upgrade&#34;</span> -H <span style="color:#e6db74">&#34;Upgrade: websocket&#34;</span> https://web.example.com/stealth-path_abcd1234
</span></span></code></pre></div>Expect <code>101 Switching Protocols</code>. If not, check Nginx config.</li>
</ul>
<hr>
<h3 id="symptom-censor-still-blocks-you">Symptom: <strong>Censor still blocks you</strong><a hidden class="anchor" aria-hidden="true" href="#symptom-censor-still-blocks-you">#</a></h3>
<ul>
<li>Did you expose another service (like SSH, Matrix, or Minecraft) on the same IP?<br>
→ Theyll find your origin IP. Use a second VPS or lock those ports down.</li>
<li>Did you use an obvious path like <code>/ws</code>?<br>
→ Use a random-looking one like <code>/cdn-assets-329df/</code>.</li>
</ul>
<hr>
<h2 id="pro-tips--fun-tricks">Pro Tips &amp; Fun Tricks<a hidden class="anchor" aria-hidden="true" href="#pro-tips--fun-tricks">#</a></h2>
<ul>
<li>Serve a fake blog or portfolio at root so your domain looks legit.</li>
<li>Rotate WebSocket paths occasionally.</li>
<li>Use Cloudflare <strong>Page Rules</strong> to disable Rocket Loader &amp; Minify for your VPN domain.</li>
<li>Make friends with your Nginx error.log — it will roast you but it tells the truth.</li>
</ul>
<hr>
<h2 id="conclusion">Conclusion<a hidden class="anchor" aria-hidden="true" href="#conclusion">#</a></h2>
<p>By putting Trojan behind Cloudflare, youve given your VPN a shiny new disguise:</p>
<ul>
<li>Looks like normal HTTPS.</li>
<li>Hides your origin IP.</li>
<li>Forces censors into a tough choice: block Cloudflare (and half the web) or let you pass.</li>
</ul>
<p>Congrats — youve built a VPN with both <strong>style</strong> and <strong>stealth</strong>. 🥷</p>
<hr>
<div class="signature-block" style="margin-top:1rem">
<p><strong>Downloads:</strong>
<a href="/sources/posts/vpn.md">Markdown</a> ·
<a href="/sources/posts/vpn.md.asc">Signature (.asc)</a>
</p><details class="signature">
<summary>View OpenPGP signature</summary>
<pre style="font-size:0.85em; overflow-x:auto; padding:0.75rem;">-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEVaKl3oR5K6zGyu4/tYgoUOBMjSoFAmpkbuAACgkQtYgoUOBM
jSo4Yw//T40cakj/BOL/Zh0gxoW4PnH014B7h67Yirq6pB3epUix6bFaZCJnndbD
9ZIhmnWMRzbkcA3SVhW1Y3NLpHvhK5UMXNY1qGqrGATQcoVCP7EewhL/3vXgTo5l
jFsQFzNxcgOXKKWevuRtL5MY8RuC&#43;PbsfG2ry2jiOtJa9H2UixVJ5E8Imj&#43;VS47O
S3XAlxr85O9CEh/TFkS/TuY5P5&#43;VPoOLn6WfdCH5W2IdkW&#43;Vi3bZFJ46LBm6cNBh
Iydo&#43;r2msTrqOozimc9hVorPjHZVZLMADJhcsa4pSZ4pDShBYMOZWATQErROPsdl
5iyRbmdFb4zWcG5SgjngHnRHFrJ8PVgnFXObb3yZMqA&#43;38RGmRNFgtR0mhMdtKNt
QxQDOO/IfO/oNfZzIERUqUnUy/iXs44v8ttTXXE6SkYYoHW335xmDuk8ntrmQA6g
YfXO4rJCXxsMaT6RkJaoK5YirKF/9hJYaUYY62SzdfhTmY1TFGGK0&#43;CD&#43;M1kQILC
E8pXSfGhaG2bFCzQ&#43;BRMe4o1BXLNjUhvovUgWEBnYTdGF5oXNS1MM29WxD/HC3md
d17noEPwOujrtLxEQcAOUcQe02VOfYcX36pbr&#43;ql32hsQMQHZtho1nx5HEGCoCWG
3sO7WQTpdBDtkwdHnRJqKBcuWqrVd3YNMwtZE0S6oXVyWkEbB4Y=
=IovZ
-----END PGP SIGNATURE-----
</pre>
</details><p><em>Verify locally:</em></p>
<pre style="font-size:0.85em; overflow-x:auto; padding:0.75rem;">torsocks curl -fSLO http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/sources/posts/vpn.md
torsocks curl -fSLO http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/sources/posts/vpn.md.asc
gpg --verify vpn.md.asc vpn.md
</pre>
</div>
</div>
<footer class="post-footer">
<ul class="post-tags">
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/vpn/">VPN</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/trojan/">Trojan</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/cloudflare/">Cloudflare</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/xray/">Xray</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/3x-ui/">3x-Ui</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/bypass/">Bypass</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/privacy/">Privacy</a></li>
<li><a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/tags/debugging/">Debugging</a></li>
</ul>
<nav class="paginav">
<a class="prev" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/tor_clearnet_blog/">
<span class="title">« Prev</span>
<br>
<span>Running my blog on Tor (.onion) and the Clearnet with Hugo &#43; PaperMod</span>
</a>
<a class="next" href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/phd_journey/augest_2025/">
<span class="title">Next »</span>
<br>
<span>Augest &#39;25</span>
</a>
</nav>
</footer><div class="comments-switch" style="display:flex;gap:.5rem;margin:.5rem 0 1rem;">
<button id="btn-isso" type="button" aria-pressed="true">Anonymous (Isso)</button>
<button id="btn-giscus" type="button" aria-pressed="false">GitHub (Giscus)</button>
<a href="https://github.com/AlipourIm/blog-comments/discussions/categories/comments" target="_blank" rel="noopener">Open on GitHub ↗</a>
</div>
<div id="panel-giscus" style="display:none">
<section id="giscus-thread"></section>
</div>
<div id="panel-isso">
<section id="isso-thread"
data-isso-id="/posts/vpn/"
data-title="Stealth Trojan VPN Behind Cloudflare Guide">
<noscript>Javascript needs to be activated to view comments.</noscript>
</section>
<script
src="/isso/js/embed.min.js"
data-isso="/isso/"
data-isso-css="false"
data-isso-lang="en"
data-isso-max-comments-nested="5"
data-isso-sorting="newest"
async>
</script>
<small class="isso-powered" style="display:block;margin:.5rem 0;color:var(--secondary,#888)">
Comments powered by <a href="https://isso-comments.de" target="_blank" rel="noopener">Isso</a>
</small>
</div>
<script>
(function () {
var panelIsso = document.getElementById('panel-isso');
var panelGisc = document.getElementById('panel-giscus');
var issoBtn = document.getElementById('btn-isso');
var giscBtn = document.getElementById('btn-giscus');
var gLoaded = false;
function isDark() {
var pref = localStorage.getItem('pref-theme');
if (pref === 'dark') return true;
if (pref === 'light') return false;
var html = document.documentElement, body = document.body;
if (
(html.classList && html.classList.contains('dark')) ||
(body.classList && body.classList.contains('dark')) ||
html.getAttribute('data-theme') === 'dark' ||
body.getAttribute('data-theme') === 'dark' ||
(html.classList && html.classList.contains('theme-dark')) ||
(body.classList && body.classList.contains('theme-dark'))
) return true;
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}
function gTheme(){ return isDark() ? 'dark_dimmed' : 'noborder_light'; }
function loadGiscus() {
if (gLoaded) return;
var s = document.createElement('script');
s.src = 'https://giscus.app/client.js';
s.async = true;
s.crossOrigin = 'anonymous';
s.setAttribute('data-repo','AlipourIm/blog-comments');
s.setAttribute('data-repo-id','R_kgDOQGARyA');
s.setAttribute('data-category','Comments');
s.setAttribute('data-category-id','DIC_kwDOQGARyM4Cw3x-');
s.setAttribute('data-mapping','pathname');
s.setAttribute('data-strict','0');
s.setAttribute('data-reactions-enabled','1');
s.setAttribute('data-emit-metadata','0');
s.setAttribute('data-input-position','bottom');
s.setAttribute('data-lang','en');
s.setAttribute('data-theme', gTheme());
document.getElementById('giscus-thread').appendChild(s);
function reTheme(){
var iframe = document.querySelector('iframe.giscus-frame');
if (iframe && iframe.contentWindow) {
iframe.contentWindow.postMessage(
{ giscus: { setConfig: { theme: gTheme() } } },
'https://giscus.app'
);
}
}
var tbtn = document.getElementById('theme-toggle');
if (tbtn) tbtn.addEventListener('click', function(){ setTimeout(reTheme, 0); });
var mo = new MutationObserver(function(){ reTheme(); });
mo.observe(document.documentElement, { attributes:true, attributeFilter:['class','data-theme'] });
mo.observe(document.body, { attributes:true, attributeFilter:['class','data-theme'] });
gLoaded = true;
}
function show(which) {
var showIsso = which === 'isso';
panelIsso.style.display = showIsso ? 'block' : 'none';
panelGisc.style.display = showIsso ? 'none' : 'block';
if (issoBtn) issoBtn.setAttribute('aria-pressed', showIsso ? 'true' : 'false');
if (giscBtn) giscBtn.setAttribute('aria-pressed', showIsso ? 'false' : 'true');
if (!showIsso) loadGiscus();
}
if (issoBtn) issoBtn.addEventListener('click', function(e){ e.preventDefault(); show('isso'); });
if (giscBtn) giscBtn.addEventListener('click', function(e){ e.preventDefault(); show('giscus'); });
show('isso');
})();
</script>
</article>
</main>
<footer class="footer">
<span>&copy; 2026 <a href="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/">AlipourIm journeys</a></span> ·
<span>
Powered by
<a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> &
<a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a>
</span>
</footer>
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
<div class="site-meta-row" style="display:flex;align-items:center;gap:.75rem;flex-wrap:wrap;">
<a href="/index.xml" rel="alternate" type="application/rss+xml" title="RSS"
class="rss-link" style="display:inline-flex;align-items:center;gap:.35rem;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M4 11a9 9 0 0 1 9 9" />
<path d="M4 4a16 16 0 0 1 16 16" />
<circle cx="5" cy="19" r="1" />
</svg>
<span>RSS</span>
</a>
<span aria-hidden="true">·</span>
<span>Visitors this week: <span id="gc_site_visitors_week"></span></span>
</div>
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
<script>
document.querySelectorAll('pre > code').forEach((codeblock) => {
const container = codeblock.parentNode.parentNode;
const copybutton = document.createElement('button');
copybutton.classList.add('copy-code');
copybutton.innerHTML = 'copy';
function copyingDone() {
copybutton.innerHTML = 'copied!';
setTimeout(() => {
copybutton.innerHTML = 'copy';
}, 2000);
}
copybutton.addEventListener('click', (cb) => {
if ('clipboard' in navigator) {
navigator.clipboard.writeText(codeblock.textContent);
copyingDone();
return;
}
const range = document.createRange();
range.selectNodeContents(codeblock);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
try {
document.execCommand('copy');
copyingDone();
} catch (e) { };
selection.removeRange(range);
});
if (container.classList.contains("highlight")) {
container.appendChild(copybutton);
} else if (container.parentNode.firstChild == container) {
} else if (codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName == "TABLE") {
codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(copybutton);
} else {
codeblock.parentNode.appendChild(copybutton);
}
});
</script>
</body>
</html>