53 lines
No EOL
48 KiB
HTML
53 lines
No EOL
48 KiB
HTML
<!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="index, follow"><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’t scream “I am a VPN” to every censor and firewall out there?
|
||
Welcome to the world of Trojan over WebSocket + 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).
|
||
We’ll 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.51e3b550fcc0c3f3a10e2d7b70445c6cb21171bed36521d66dc7427208cafbf9.css integrity="sha256-UeO1UPzAw/OhDi17cERcbLIRcb7TZSHWbcdCcgjK+/k=" 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><meta property="og:url" content="http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/"><meta property="og:site_name" content="AlipourIm journeys"><meta property="og:title" content="Stealth Trojan VPN Behind Cloudflare Guide"><meta property="og:description" content="Introduction So you want a VPN that doesn’t scream “I am a VPN” to every censor and firewall out there?
|
||
Welcome to the world of Trojan over WebSocket + 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).
|
||
We’ll anonymise domains and secrets, so substitute with your own:"><meta property="og:locale" content="en"><meta property="og:type" content="article"><meta property="article:section" content="posts"><meta property="article:published_time" content="2025-09-09T11:05:00+02:00"><meta property="article:modified_time" content="2025-09-09T11:05:00+02:00"><meta property="article:tag" content="VPN"><meta property="article:tag" content="Trojan"><meta property="article:tag" content="Cloudflare"><meta property="article:tag" content="Xray"><meta property="article:tag" content="3x-Ui"><meta property="article:tag" content="Bypass"><meta name=twitter:card content="summary"><meta name=twitter:title content="Stealth Trojan VPN Behind Cloudflare Guide"><meta name=twitter:description content="Introduction
|
||
So you want a VPN that doesn’t scream “I am a VPN” to every censor and firewall out there?
|
||
Welcome to the world of Trojan over WebSocket + 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).
|
||
We’ll anonymise domains and secrets, so substitute with your own:"><script type=application/ld+json>{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Posts","item":"http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/"},{"@type":"ListItem","position":2,"name":"Stealth Trojan VPN Behind Cloudflare Guide","item":"http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/"}]}</script><script type=application/ld+json>{"@context":"https://schema.org","@type":"BlogPosting","headline":"Stealth Trojan VPN Behind Cloudflare Guide","name":"Stealth Trojan VPN Behind Cloudflare Guide","description":"Introduction So you want a VPN that doesn\u0026rsquo;t scream \u0026ldquo;I am a VPN\u0026rdquo; to every censor and firewall out there?\nWelcome to the world of Trojan over WebSocket + TLS behind Cloudflare.\nThis 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).\nWe’ll anonymise domains and secrets, so substitute with your own:\n","keywords":["VPN","Trojan","Cloudflare","Xray","3x-ui","Bypass","Privacy","Debugging"],"articleBody":"Introduction So you want a VPN that doesn’t scream “I am a VPN” to every censor and firewall out there?\nWelcome to the world of Trojan over WebSocket + TLS behind Cloudflare.\nThis 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).\nWe’ll anonymise domains and secrets, so substitute with your own:\nVPN domain: web.example.com Panel domain: panel.example.com Secret WS path: /stealth-path_abcd1234 Password: Architecture at a Glance Think of it as a disguise party:\nTrojan = the shy guest (your VPN protocol) Nginx = the bouncer checking IDs (reverse proxy) Cloudflare = the doorman who makes sure nobody sees who’s inside (CDN \u0026 proxy) Your fake website = the mask (camouflage page) Traffic flow:\nC l i e n t → C l o u d f l a r e ( 4 4 3 ) → N g i n x ( 4 4 3 ) → T r o j a n ( l o c a l h o s t : 5 4 3 2 1 ) Step 1: Panel Setup (panel.example.com) Bind the 3x-ui panel to localhost (e.g., 127.0.0.1:46309). Choose a funky web base path like /panel-bananas_42/. Proxy it through Nginx with HTTPS + Basic Auth. Test it at https://panel.example.com/panel-bananas_42/. Pro tip: If you see a blank page → your base path is mismatched or Nginx is eating it. Check logs!\nStep 2: Trojan Inbound In 3x-ui, create a Trojan inbound:\nLocal port: 54321 Transport: WebSocket Path: /stealth-path_abcd1234 Security: none Password: Step 3: Nginx for VPN Domain (web.example.com) Your Nginx is the gatekeeper. Sample config:\nserver { listen 443 ssl http2; server_name web.example.com; ssl_certificate /etc/letsencrypt/live/web.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/web.example.com/privkey.pem; # Fake website at root location / { root /var/www/html; index index.html; } # Real VPN under secret WS path location /stealth-path_abcd1234 { proxy_pass http://127.0.0.1:54321; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection \"upgrade\"; proxy_set_header Host $host; } } Step 4: Firewall Rules Lock things down! Only Cloudflare should reach you:\nufw allow 22/tcp ufw allow 80/tcp ufw allow 443/tcp ufw deny 54321/tcp Step 5: Client Config Trojan URI:\nt r o j a n : / / \u003c P A S S W O R D \u003e @ w e b . e x a m p l e . c o m : 4 4 3 ? t y p e = w s \u0026 s e c u r i t y = t l s \u0026 h o s t = w e b . e x a m p l e . c o m \u0026 p a t h = % 2 F s t e a l t h - p a t h _ a b c d 1 2 3 4 \u0026 s n i = w e b . e x a m p l e . c o m # M y S t e a l t h V P N iOS clients: Shadowrocket, Stash, FoXray\nAndroid clients: v2rayNG, Clash Meta, NekoBox\nDebugging Time (a.k.a. “Why the heck doesn’t it work?!”) Symptom: 520 Unknown Error (Cloudflare) Likely cause: Nginx couldn’t talk to Trojan. Check Nginx error log: tail -n 50 /var/log/nginx/error.log If you see upstream sent no valid HTTP/1.0 header → you’re mixing HTTPS/HTTP between Nginx and Trojan. Symptom: 526 Invalid SSL certificate Cloudflare → Nginx cert mismatch. Run: openssl s_client -connect web.example.com:443 -servername web.example.com -showcerts Make sure CN = web.example.com. If not, fix your cert. Symptom: Blank page on panel Check if the base path matches exactly (case-sensitive, slash-sensitive). Watch for sneaky trailing spaces! Test locally: curl -s -D- http://127.0.0.1:46309/panel-bananas_42/ Symptom: Client won’t connect Run a WebSocket test: curl -i -k -H \"Connection: Upgrade\" -H \"Upgrade: websocket\" https://web.example.com/stealth-path_abcd1234 Expect 101 Switching Protocols. If not, check Nginx config. Symptom: Censor still blocks you Did you expose another service (like SSH, Matrix, or Minecraft) on the same IP?\n→ They’ll find your origin IP. Use a second VPS or lock those ports down. Did you use an obvious path like /ws?\n→ Use a random-looking one like /cdn-assets-329df/. Pro Tips \u0026 Fun Tricks Serve a fake blog or portfolio at root so your domain looks legit. Rotate WebSocket paths occasionally. Use Cloudflare Page Rules to disable Rocket Loader \u0026 Minify for your VPN domain. Make friends with your Nginx error.log — it will roast you but it tells the truth. Conclusion By putting Trojan behind Cloudflare, you’ve given your VPN a shiny new disguise:\nLooks like normal HTTPS. Hides your origin IP. Forces censors into a tough choice: block Cloudflare (and half the web) or let you pass. Congrats — you’ve built a VPN with both style and stealth. 🥷\n","wordCount":"796","inLanguage":"en","datePublished":"2025-09-09T11:05:00+02:00","dateModified":"2025-09-09T11:05:00+02:00","author":{"@type":"Person","name":"Iman Alipour"},"mainEntityOfPage":{"@type":"WebPage","@id":"http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/posts/vpn/"},"publisher":{"@type":"Organization","name":"AlipourIm journeys","logo":{"@type":"ImageObject","url":"http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/favicon.ico"}}}</script></head><body id=top><script>localStorage.getItem("pref-theme")==="dark"?document.body.classList.add("dark"):localStorage.getItem("pref-theme")==="light"?document.body.classList.remove("dark"):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" 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 1111.21 3 7 7 0 0021 12.79z"/></svg><svg id="sun" 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"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></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> » <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> · 4 min · 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’t scream “I am a VPN”</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>We’ll 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><PASSWORD></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’s inside (CDN & proxy)</li><li><strong>Your fake website</strong> = the mask (camouflage page)</li></ul><p>Traffic flow:</p><div class="goat svg-container"><svg font-family="Menlo,Lucida Console,monospace" viewBox="0 0 536 25"><g transform="translate(8,16)"><text text-anchor="middle" x="0" y="4" fill="currentcolor" style="font-size:1em">C</text><text text-anchor="middle" x="8" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="16" y="4" fill="currentcolor" style="font-size:1em">i</text><text text-anchor="middle" x="24" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="32" y="4" fill="currentcolor" style="font-size:1em">n</text><text text-anchor="middle" x="40" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="56" y="4" fill="currentcolor" style="font-size:1em">→</text><text text-anchor="middle" x="72" y="4" fill="currentcolor" style="font-size:1em">C</text><text text-anchor="middle" x="80" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="88" y="4" fill="currentcolor" style="font-size:1em">o</text><text text-anchor="middle" x="96" y="4" fill="currentcolor" style="font-size:1em">u</text><text text-anchor="middle" x="104" y="4" fill="currentcolor" style="font-size:1em">d</text><text text-anchor="middle" x="112" y="4" fill="currentcolor" style="font-size:1em">f</text><text text-anchor="middle" x="120" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="128" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="136" y="4" fill="currentcolor" style="font-size:1em">r</text><text text-anchor="middle" x="144" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="160" y="4" fill="currentcolor" style="font-size:1em">(</text><text text-anchor="middle" x="168" y="4" fill="currentcolor" style="font-size:1em">4</text><text text-anchor="middle" x="176" y="4" fill="currentcolor" style="font-size:1em">4</text><text text-anchor="middle" x="184" y="4" fill="currentcolor" style="font-size:1em">3</text><text text-anchor="middle" x="192" y="4" fill="currentcolor" style="font-size:1em">)</text><text text-anchor="middle" x="208" y="4" fill="currentcolor" style="font-size:1em">→</text><text text-anchor="middle" x="224" y="4" fill="currentcolor" style="font-size:1em">N</text><text text-anchor="middle" x="232" y="4" fill="currentcolor" style="font-size:1em">g</text><text text-anchor="middle" x="240" y="4" fill="currentcolor" style="font-size:1em">i</text><text text-anchor="middle" x="248" y="4" fill="currentcolor" style="font-size:1em">n</text><text text-anchor="middle" x="256" y="4" fill="currentcolor" style="font-size:1em">x</text><text text-anchor="middle" x="272" y="4" fill="currentcolor" style="font-size:1em">(</text><text text-anchor="middle" x="280" y="4" fill="currentcolor" style="font-size:1em">4</text><text text-anchor="middle" x="288" y="4" fill="currentcolor" style="font-size:1em">4</text><text text-anchor="middle" x="296" y="4" fill="currentcolor" style="font-size:1em">3</text><text text-anchor="middle" x="304" y="4" fill="currentcolor" style="font-size:1em">)</text><text text-anchor="middle" x="320" y="4" fill="currentcolor" style="font-size:1em">→</text><text text-anchor="middle" x="336" y="4" fill="currentcolor" style="font-size:1em">T</text><text text-anchor="middle" x="344" y="4" fill="currentcolor" style="font-size:1em">r</text><text text-anchor="middle" x="352" y="4" fill="currentcolor" style="font-size:1em">o</text><text text-anchor="middle" x="360" y="4" fill="currentcolor" style="font-size:1em">j</text><text text-anchor="middle" x="368" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="376" y="4" fill="currentcolor" style="font-size:1em">n</text><text text-anchor="middle" x="392" y="4" fill="currentcolor" style="font-size:1em">(</text><text text-anchor="middle" x="400" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="408" y="4" fill="currentcolor" style="font-size:1em">o</text><text text-anchor="middle" x="416" y="4" fill="currentcolor" style="font-size:1em">c</text><text text-anchor="middle" x="424" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="432" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="440" y="4" fill="currentcolor" style="font-size:1em">h</text><text text-anchor="middle" x="448" y="4" fill="currentcolor" style="font-size:1em">o</text><text text-anchor="middle" x="456" y="4" fill="currentcolor" style="font-size:1em">s</text><text text-anchor="middle" x="464" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="472" y="4" fill="currentcolor" style="font-size:1em">:</text><text text-anchor="middle" x="480" y="4" fill="currentcolor" style="font-size:1em">5</text><text text-anchor="middle" x="488" y="4" fill="currentcolor" style="font-size:1em">4</text><text text-anchor="middle" x="496" y="4" fill="currentcolor" style="font-size:1em">3</text><text text-anchor="middle" x="504" y="4" fill="currentcolor" style="font-size:1em">2</text><text text-anchor="middle" x="512" y="4" fill="currentcolor" style="font-size:1em">1</text><text text-anchor="middle" x="520" y="4" fill="currentcolor" style="font-size:1em">)</text></g></svg></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><PASSWORD></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>"upgrade"</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="goat svg-container"><svg font-family="Menlo,Lucida Console,monospace" viewBox="0 0 1160 25"><g transform="translate(8,16)"><text text-anchor="middle" x="0" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="8" y="4" fill="currentcolor" style="font-size:1em">r</text><text text-anchor="middle" x="16" y="4" fill="currentcolor" style="font-size:1em">o</text><text text-anchor="middle" x="24" y="4" fill="currentcolor" style="font-size:1em">j</text><text text-anchor="middle" x="32" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="40" y="4" fill="currentcolor" style="font-size:1em">n</text><text text-anchor="middle" x="48" y="4" fill="currentcolor" style="font-size:1em">:</text><text text-anchor="middle" x="56" y="4" fill="currentcolor" style="font-size:1em">/</text><text text-anchor="middle" x="64" y="4" fill="currentcolor" style="font-size:1em">/</text><text text-anchor="middle" x="72" y="4" fill="currentcolor" style="font-size:1em"><</text><text text-anchor="middle" x="80" y="4" fill="currentcolor" style="font-size:1em">P</text><text text-anchor="middle" x="88" y="4" fill="currentcolor" style="font-size:1em">A</text><text text-anchor="middle" x="96" y="4" fill="currentcolor" style="font-size:1em">S</text><text text-anchor="middle" x="104" y="4" fill="currentcolor" style="font-size:1em">S</text><text text-anchor="middle" x="112" y="4" fill="currentcolor" style="font-size:1em">W</text><text text-anchor="middle" x="120" y="4" fill="currentcolor" style="font-size:1em">O</text><text text-anchor="middle" x="128" y="4" fill="currentcolor" style="font-size:1em">R</text><text text-anchor="middle" x="136" y="4" fill="currentcolor" style="font-size:1em">D</text><text text-anchor="middle" x="144" y="4" fill="currentcolor" style="font-size:1em">></text><text text-anchor="middle" x="152" y="4" fill="currentcolor" style="font-size:1em">@</text><text text-anchor="middle" x="160" y="4" fill="currentcolor" style="font-size:1em">w</text><text text-anchor="middle" x="168" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="176" y="4" fill="currentcolor" style="font-size:1em">b</text><text text-anchor="middle" x="184" y="4" fill="currentcolor" style="font-size:1em">.</text><text text-anchor="middle" x="192" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="200" y="4" fill="currentcolor" style="font-size:1em">x</text><text text-anchor="middle" x="208" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="216" y="4" fill="currentcolor" style="font-size:1em">m</text><text text-anchor="middle" x="224" y="4" fill="currentcolor" style="font-size:1em">p</text><text text-anchor="middle" x="232" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="240" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="248" y="4" fill="currentcolor" style="font-size:1em">.</text><text text-anchor="middle" x="256" y="4" fill="currentcolor" style="font-size:1em">c</text><text text-anchor="middle" x="264" y="4" fill="currentcolor" style="font-size:1em">o</text><text text-anchor="middle" x="272" y="4" fill="currentcolor" style="font-size:1em">m</text><text text-anchor="middle" x="280" y="4" fill="currentcolor" style="font-size:1em">:</text><text text-anchor="middle" x="288" y="4" fill="currentcolor" style="font-size:1em">4</text><text text-anchor="middle" x="296" y="4" fill="currentcolor" style="font-size:1em">4</text><text text-anchor="middle" x="304" y="4" fill="currentcolor" style="font-size:1em">3</text><text text-anchor="middle" x="312" y="4" fill="currentcolor" style="font-size:1em">?</text><text text-anchor="middle" x="320" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="328" y="4" fill="currentcolor" style="font-size:1em">y</text><text text-anchor="middle" x="336" y="4" fill="currentcolor" style="font-size:1em">p</text><text text-anchor="middle" x="344" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="352" y="4" fill="currentcolor" style="font-size:1em">=</text><text text-anchor="middle" x="360" y="4" fill="currentcolor" style="font-size:1em">w</text><text text-anchor="middle" x="368" y="4" fill="currentcolor" style="font-size:1em">s</text><text text-anchor="middle" x="376" y="4" fill="currentcolor" style="font-size:1em">&</text><text text-anchor="middle" x="384" y="4" fill="currentcolor" style="font-size:1em">s</text><text text-anchor="middle" x="392" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="400" y="4" fill="currentcolor" style="font-size:1em">c</text><text text-anchor="middle" x="408" y="4" fill="currentcolor" style="font-size:1em">u</text><text text-anchor="middle" x="416" y="4" fill="currentcolor" style="font-size:1em">r</text><text text-anchor="middle" x="424" y="4" fill="currentcolor" style="font-size:1em">i</text><text text-anchor="middle" x="432" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="440" y="4" fill="currentcolor" style="font-size:1em">y</text><text text-anchor="middle" x="448" y="4" fill="currentcolor" style="font-size:1em">=</text><text text-anchor="middle" x="456" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="464" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="472" y="4" fill="currentcolor" style="font-size:1em">s</text><text text-anchor="middle" x="480" y="4" fill="currentcolor" style="font-size:1em">&</text><text text-anchor="middle" x="488" y="4" fill="currentcolor" style="font-size:1em">h</text><text text-anchor="middle" x="496" y="4" fill="currentcolor" style="font-size:1em">o</text><text text-anchor="middle" x="504" y="4" fill="currentcolor" style="font-size:1em">s</text><text text-anchor="middle" x="512" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="520" y="4" fill="currentcolor" style="font-size:1em">=</text><text text-anchor="middle" x="528" y="4" fill="currentcolor" style="font-size:1em">w</text><text text-anchor="middle" x="536" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="544" y="4" fill="currentcolor" style="font-size:1em">b</text><text text-anchor="middle" x="552" y="4" fill="currentcolor" style="font-size:1em">.</text><text text-anchor="middle" x="560" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="568" y="4" fill="currentcolor" style="font-size:1em">x</text><text text-anchor="middle" x="576" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="584" y="4" fill="currentcolor" style="font-size:1em">m</text><text text-anchor="middle" x="592" y="4" fill="currentcolor" style="font-size:1em">p</text><text text-anchor="middle" x="600" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="608" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="616" y="4" fill="currentcolor" style="font-size:1em">.</text><text text-anchor="middle" x="624" y="4" fill="currentcolor" style="font-size:1em">c</text><text text-anchor="middle" x="632" y="4" fill="currentcolor" style="font-size:1em">o</text><text text-anchor="middle" x="640" y="4" fill="currentcolor" style="font-size:1em">m</text><text text-anchor="middle" x="648" y="4" fill="currentcolor" style="font-size:1em">&</text><text text-anchor="middle" x="656" y="4" fill="currentcolor" style="font-size:1em">p</text><text text-anchor="middle" x="664" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="672" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="680" y="4" fill="currentcolor" style="font-size:1em">h</text><text text-anchor="middle" x="688" y="4" fill="currentcolor" style="font-size:1em">=</text><text text-anchor="middle" x="696" y="4" fill="currentcolor" style="font-size:1em">%</text><text text-anchor="middle" x="704" y="4" fill="currentcolor" style="font-size:1em">2</text><text text-anchor="middle" x="712" y="4" fill="currentcolor" style="font-size:1em">F</text><text text-anchor="middle" x="720" y="4" fill="currentcolor" style="font-size:1em">s</text><text text-anchor="middle" x="728" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="736" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="744" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="752" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="760" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="768" y="4" fill="currentcolor" style="font-size:1em">h</text><text text-anchor="middle" x="776" y="4" fill="currentcolor" style="font-size:1em">-</text><text text-anchor="middle" x="784" y="4" fill="currentcolor" style="font-size:1em">p</text><text text-anchor="middle" x="792" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="800" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="808" y="4" fill="currentcolor" style="font-size:1em">h</text><text text-anchor="middle" x="816" y="4" fill="currentcolor" style="font-size:1em">_</text><text text-anchor="middle" x="824" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="832" y="4" fill="currentcolor" style="font-size:1em">b</text><text text-anchor="middle" x="840" y="4" fill="currentcolor" style="font-size:1em">c</text><text text-anchor="middle" x="848" y="4" fill="currentcolor" style="font-size:1em">d</text><text text-anchor="middle" x="856" y="4" fill="currentcolor" style="font-size:1em">1</text><text text-anchor="middle" x="864" y="4" fill="currentcolor" style="font-size:1em">2</text><text text-anchor="middle" x="872" y="4" fill="currentcolor" style="font-size:1em">3</text><text text-anchor="middle" x="880" y="4" fill="currentcolor" style="font-size:1em">4</text><text text-anchor="middle" x="888" y="4" fill="currentcolor" style="font-size:1em">&</text><text text-anchor="middle" x="896" y="4" fill="currentcolor" style="font-size:1em">s</text><text text-anchor="middle" x="904" y="4" fill="currentcolor" style="font-size:1em">n</text><text text-anchor="middle" x="912" y="4" fill="currentcolor" style="font-size:1em">i</text><text text-anchor="middle" x="920" y="4" fill="currentcolor" style="font-size:1em">=</text><text text-anchor="middle" x="928" y="4" fill="currentcolor" style="font-size:1em">w</text><text text-anchor="middle" x="936" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="944" y="4" fill="currentcolor" style="font-size:1em">b</text><text text-anchor="middle" x="952" y="4" fill="currentcolor" style="font-size:1em">.</text><text text-anchor="middle" x="960" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="968" y="4" fill="currentcolor" style="font-size:1em">x</text><text text-anchor="middle" x="976" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="984" y="4" fill="currentcolor" style="font-size:1em">m</text><text text-anchor="middle" x="992" y="4" fill="currentcolor" style="font-size:1em">p</text><text text-anchor="middle" x="1e3" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="1008" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="1016" y="4" fill="currentcolor" style="font-size:1em">.</text><text text-anchor="middle" x="1024" y="4" fill="currentcolor" style="font-size:1em">c</text><text text-anchor="middle" x="1032" y="4" fill="currentcolor" style="font-size:1em">o</text><text text-anchor="middle" x="1040" y="4" fill="currentcolor" style="font-size:1em">m</text><text text-anchor="middle" x="1048" y="4" fill="currentcolor" style="font-size:1em">#</text><text text-anchor="middle" x="1056" y="4" fill="currentcolor" style="font-size:1em">M</text><text text-anchor="middle" x="1064" y="4" fill="currentcolor" style="font-size:1em">y</text><text text-anchor="middle" x="1072" y="4" fill="currentcolor" style="font-size:1em">S</text><text text-anchor="middle" x="1080" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="1088" y="4" fill="currentcolor" style="font-size:1em">e</text><text text-anchor="middle" x="1096" y="4" fill="currentcolor" style="font-size:1em">a</text><text text-anchor="middle" x="1104" y="4" fill="currentcolor" style="font-size:1em">l</text><text text-anchor="middle" x="1112" y="4" fill="currentcolor" style="font-size:1em">t</text><text text-anchor="middle" x="1120" y="4" fill="currentcolor" style="font-size:1em">h</text><text text-anchor="middle" x="1128" y="4" fill="currentcolor" style="font-size:1em">V</text><text text-anchor="middle" x="1136" y="4" fill="currentcolor" style="font-size:1em">P</text><text text-anchor="middle" x="1144" y="4" fill="currentcolor" style="font-size:1em">N</text></g></svg></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 doesn’t 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 couldn’t 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> → you’re 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 won’t 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>"Connection: Upgrade"</span> -H <span style=color:#e6db74>"Upgrade: websocket"</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>→ They’ll 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 & 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 & 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, you’ve 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 — you’ve built a VPN with both <strong>style</strong> and <strong>stealth</strong>. 🥷</p></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 + PaperMod</span>
|
||
</a><a class=next href=http://fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion/phd_journey/augest_2025/><span class=title>Next »</span><br><span>Augest '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-isso><section id=isso-thread></section><script src=/isso/js/embed.min.js data-isso=/isso data-isso-css=true 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><div id=panel-giscus style=display:none><section id=giscus-thread></section></div><script>(function(){var t=document.getElementById("btn-isso"),n=document.getElementById("btn-giscus"),o=document.getElementById("panel-isso"),i=document.getElementById("panel-giscus"),s=!1;function e(e){var a,r=e==="isso";o.style.display=r?"":"none",i.style.display=r?"none":"",t.setAttribute("aria-pressed",r),n.setAttribute("aria-pressed",!r),!r&&!s&&(a=document.createElement("script"),a.src="https://giscus.app/client.js",a.async=!0,a.crossOrigin="anonymous",a.setAttribute("data-repo","AlipourIm/blog-comments"),a.setAttribute("data-repo-id","R_kgDOQGARyA"),a.setAttribute("data-category","Comments"),a.setAttribute("data-category-id","DIC_kwDOQGARyM4Cw3x-"),a.setAttribute("data-mapping","pathname"),a.setAttribute("data-strict","0"),a.setAttribute("data-reactions-enabled","1"),a.setAttribute("data-emit-metadata","0"),a.setAttribute("data-input-position","bottom"),a.setAttribute("data-theme","preferred_color_scheme"),a.setAttribute("data-lang","en"),document.getElementById("giscus-thread").appendChild(a),s=!0)}t.addEventListener("click",function(){e("isso")}),n.addEventListener("click",function(){e("giscus")}),e("isso")})()</script></article></main><footer class=footer><span>© 2025 <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 viewBox="0 0 12 6" fill="currentcolor"><path d="M12 6H0l6-6z"/></svg>
|
||
</a><a href=/index.xml rel=alternate type=application/rss+xml title=RSS class=rss-link><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 019 9"/><path d="M4 4a16 16 0 0116 16"/><circle cx="5" cy="19" r="1"/></svg>
|
||
<span>RSS</span>
|
||
</a><script>let menu=document.getElementById("menu");menu&&(menu.scrollLeft=localStorage.getItem("menu-scroll-position"),menu.onscroll=function(){localStorage.setItem("menu-scroll-position",menu.scrollLeft)}),document.querySelectorAll('a[href^="#"]').forEach(e=>{e.addEventListener("click",function(e){e.preventDefault();var t=this.getAttribute("href").substr(1);window.matchMedia("(prefers-reduced-motion: reduce)").matches?document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView():document.querySelector(`[id='${decodeURIComponent(t)}']`).scrollIntoView({behavior:"smooth"}),t==="top"?history.replaceState(null,null," "):history.pushState(null,null,`#${t}`)})})</script><script>var mybutton=document.getElementById("top-link");window.onscroll=function(){document.body.scrollTop>800||document.documentElement.scrollTop>800?(mybutton.style.visibility="visible",mybutton.style.opacity="1"):(mybutton.style.visibility="hidden",mybutton.style.opacity="0")}</script><script>document.getElementById("theme-toggle").addEventListener("click",()=>{document.body.className.includes("dark")?(document.body.classList.remove("dark"),localStorage.setItem("pref-theme","light")):(document.body.classList.add("dark"),localStorage.setItem("pref-theme","dark"))})</script><script>document.querySelectorAll("pre > code").forEach(e=>{const n=e.parentNode.parentNode,t=document.createElement("button");t.classList.add("copy-code"),t.innerHTML="copy";function s(){t.innerHTML="copied!",setTimeout(()=>{t.innerHTML="copy"},2e3)}t.addEventListener("click",t=>{if("clipboard"in navigator){navigator.clipboard.writeText(e.textContent),s();return}const n=document.createRange();n.selectNodeContents(e);const o=window.getSelection();o.removeAllRanges(),o.addRange(n);try{document.execCommand("copy"),s()}catch{}o.removeRange(n)}),n.classList.contains("highlight")?n.appendChild(t):n.parentNode.firstChild==n||(e.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName=="TABLE"?e.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(t):e.parentNode.appendChild(t))})</script></body></html> |