Files
OmniRoute/docs/i18n/phi/docs/security/STEALTH_GUIDE.md
Diego Rodrigues de Sa e Souza 8feea123bb feat(docs): mirror every docs/ page in all 65 locales (#14106)
* feat(docs): mirror every docs/ page in all 65 locales

Extends the documentation mirrors from the 22-page core set (#13940) to
every Markdown page under docs/: 152 sources x 65 locales = 9,880 mirrors
(6,208 new), language bars rewritten for the full locale list, state
adopted so the blocking drift gate now covers all 152 pages.

run-translation.mjs: an oversized block made only of table rows or list
items (PROVIDER_REFERENCE.md 244-row table, FREE_TIERS.md 71-item list) is
cut at item boundaries and rejoined without a blank line — the single
16-40 KB request outlived the backend socket for verbose scripts. 48
older mirrors whose tables had lost rows were retranslated with --force.

* docs(i18n): refresh mirrors for the sources the base changed since the branch cut

Section-level retranslation of the 29 docs (and README.md) whose source
or mirrors moved on release/v3.8.51 during the run, then state adoption;
the drift gate is green again on the merged tree.
2026-09-18 13:16:46 -03:00

25 KiB
Raw Blame History

Stealth Guide (Filipino)

🌐 Languages: 🇺🇸 English · 🇪🇹 am · 🇸🇦 ar · 🇦🇿 az · 🇧🇬 bg · 🇧🇩 bn · 🇨🇿 cs · 🇩🇰 da · 🇩🇪 de · 🇬🇷 el · 🇪🇸 es · 🇪🇪 et · 🇮🇷 fa · 🇫🇮 fi · 🇫🇷 fr · 🇮🇪 ga · 🇮🇳 gu · 🇳🇬 ha · 🇮🇱 he · 🇮🇳 hi · 🇭🇷 hr · 🇭🇺 hu · 🇦🇲 hy · 🇮🇩 id · 🇳🇬 ig · 🇮🇹 it · 🇯🇵 ja · 🇬🇪 ka · 🇰🇭 km · 🇮🇳 kn · 🇰🇷 ko · 🇱🇹 lt · 🇱🇻 lv · 🇮🇳 ml · 🇮🇳 mr · 🇲🇾 ms · 🇲🇹 mt · 🇲🇲 my · 🇳🇵 ne · 🇳🇱 nl · 🇳🇴 no · 🇮🇳 or · 🇮🇳 pa · 🇵🇱 pl · 🇵🇹 pt · 🇧🇷 pt-BR · 🇷🇴 ro · 🇷🇺 ru · 🇱🇰 si · 🇸🇰 sk · 🇸🇮 sl · 🇷🇸 sr · 🇸🇪 sv · 🇰🇪 sw · 🇮🇳 ta · 🇮🇳 te · 🇹🇭 th · 🇹🇷 tr · 🇺🇦 uk-UA · 🇵🇰 ur · 🇺🇿 uz · 🇻🇳 vi · 🇳🇬 yo · 🇨🇳 zh-CN · 🇹🇼 zh-TW


Pinagmumulan ng katotohanan: open-sse/utils/tlsClient.ts, open-sse/services/{tlsClientBase,claudeTlsClient,perplexityTlsClient,grokTlsClient,notionTlsClient,lmarenaTlsClient,claudeCodeCCH,claudeCodeFingerprint,claudeCodeObfuscation,claudeCodeCompatible}.ts, open-sse/config/cliFingerprints.ts, src/mitm/ Huling na-update: 2026-09-02 — v3.8.51 Para kanino: Mga engineer na nagpapanatili ng mga stealth integration na partikular sa provider.

Nakikipag-integrate ang OmniRoute sa mga provider na ang mga edge ay aktibong kumikilala sa mga hindi opisyal na client sa pamamagitan ng fingerprinting (TLS JA3/JA4, pagkakasunod-sunod ng header, anyo ng JSON body, mga integrity token). Inilalarawan ng pahinang ito ang mga stealth surface na inilalantad ng OmniRoute at kung saan ipinatupad ang mga ito.

Umiiral ang mga stealth feature upang makakilos ang OmniRoute bilang compatibility layer sa pagitan ng mga opisyal na account na pagmamay-ari ng user (Claude Code CLI, Codex, Antigravity, Cursor, atbp.) at ng pinag-isang API ng OmniRoute. Hindi nilayon ang mga ito para umiwas sa pagtukoy ng pandaraya, magbahagi ng mga credential, o lumabag sa Mga Tuntunin ng Serbisyo ng provider. Inaasahan ng mga maintainer na susunod ang mga operator sa upstream ToS na sinang-ayunan nila noong gumawa sila ng mga account.


Layer ng TLS Fingerprinting

open-sse/utils/tlsClient.ts — wreq-js (Chrome 124)

Ang mga persistent na session ng wreq-js ay ginagawa nang lazily para sa bawat saklaw ng account at nalutas na proxy. Ang process-wide na TlsClient ay nagpo-pool ng hindi hihigit sa 128 session na nagpapanggap bilang Chrome 124 sa macOS para sa mga upstream na nasa likod ng Cloudflare. Nagfa-fail closed ang TlsClient.fetch() kapag hindi available ang native runtime; maaaring tahasang pumili ang tumatawag ng fallback sa labas ng wrapper na ito.

  • Profile ng session: browser: "chrome_124", os: "macos"
  • Paglutas ng proxy (ayon sa priyoridad): HTTPS_PROXYHTTP_PROXYALL_PROXY (pati lower-case)
  • Timeout: TLS_CLIENT_TIMEOUT_MS (namamana mula sa FETCH_TIMEOUT_MS, default na 600000)
  • Fetch-compatible ang Response ng wreq-js (headers, text(), json(), clone(), body).
  • Watchdog ng unang byte (open-sse/utils/tlsFirstByteWatchdog.ts, #12656): Nagre-resolve ang TlsClient.fetch() sa sandaling dumating ang mga upstream header, kaya hindi kayang limitahan ng TLS_CLIENT_TIMEOUT_MS lamang ang isang body na hindi kailanman naglalabas ng unang byte. Pinagpapaligsahan ng guardTlsFirstByte() ang unang read() ng body laban sa TLS_FIRST_BYTE_WATCHDOG_MS (default na 10000, dini-disable ito ng 0); hindi naaapektuhan ang maayos na body, habang kinakansela ng isang naka-stall na body ang wreq reader at hinahayaang tumuloy ang umiiral na TLS-fallback logic ng proxyFetch sa direct/proxy dispatcher (ang request na hindi ligtas i-replay, hal. isang POST na may body, ay magti-throw pa rin sa halip na tahimik na subukang muli).

Ang open-sse/services/tlsClientBase.ts ang shared adapter para sa limang specialized na web-cookie transport sa ibaba. Pumipili ang bawat manipis na provider wrapper ng browser/OS profile. Ginagamit ng adapter ang iisang wreq runtime loader at transport pool sa open-sse/utils/tlsClient.ts, na naka-key ayon sa profile + OS + nalutas na proxy, habang gumagamit ang bawat request ng cookieMode: "ephemeral". Samakatuwid, pinagsasaluhan ng mga account at request ang mga koneksyon sa antas ng transport, ngunit hindi kailanman ang isang wreq session o cookie jar.

Provider Profile Ginagayang OS Patakaran sa EOF ng stream
Claude chrome_146 Linux isama ang [DONE]
Perplexity firefox_148 macOS isama ang event: end_of_stream
Grok chrome_146 Linux huwag isama ang [DONE]
Notion chrome_146 Windows isama ang [DONE]
LMArena chrome_146 Windows walang sentinel; isara sa native EOF
  • Direktang kinokonsumo ng streaming ang native response na ReadableStream; walang ginagawang temp file o sidecar.
  • Hanggang 256 na paunang byte ang sinusuri bago ilantad ang isang stream. Bina-buffer ng mga SSE provider ang mga error na hindi SSE; minamapa ng Grok/LMArena ang mga challenge ng Cloudflare sa 403 at ang mga HTML interstitial sa 502.
  • Nananatiling nakabalot ang native request timeout sa isang absolute na JS hard deadline. Pinapawalang-bisa at isinasara lamang ng hang ang apektadong profile/OS/proxy transport bago ito muling gawin ng susunod na request.
  • Ang priyoridad sa paglutas ng proxy ay per-call na proxyUrl → request-scoped na account/dashboard context → HTTPS_PROXY/HTTP_PROXY/ALL_PROXY (kabilang ang mga lower-case na variant). Nagfa-fail closed ang mga error sa paglutas sa halip na mag-leak ng direktang koneksyon. Sinasadyang mag-resolve ng LMArena laban sa arena.ai.
  • Nagbabalik ang byteResponse ng content-typed na data: URL nang walang UTF-8 corruption.
  • Ang mga error ay TlsClientUnavailableError (hindi available ang package/addon), TlsClientHangError (lumampas sa deadline), at WreqTransportCapacityError (ang shared na session-capacity error code) kapag aktibo o nagsasara ang lahat ng 128 bounded na profile/OS/proxy slot.

Nananatiling specialized ang generic na TlsClient session sa itaas para sa persistent na cookie state na sinusuportahan ng browser. Muling ginagamit ng parehong path ang iisang naka-cache na wreq module loader at process lifecycle hook; nananatiling magkahiwalay ang kanilang mga pool dahil sinadyang magkaiba ang lifecycle ng kanilang mga cookie.

Sinusuportahan ng naka-pin na package ang mga profile, ngunit maaaring magbago ang aktuwal na pagtanggap ng WAF nang hiwalay sa mga lokal na contract test. I-validate ang mga pagbabago sa fingerprint gamit ang isang tahasang awtorisadong live account bago magpahayag ng parity sa isang upstream browser.


Claude Code Stealth Bundle

Kapag naka-on ang cliCompatMode, binabago ng OmniRoute ang mga papalabas na Claude request upang hindi matukoy ang pagkakaiba ng mga ito sa trapiko ng claude-cli. Tatlong module ang nagtutulungan:

claudeCodeFingerprint.ts

Kinukuwenta ang 3-character na cc_version fingerprint na naka-embed sa billing header:

SHA256(SALT + msg[4] + msg[7] + msg[20] + version)[:3]
  • FINGERPRINT_SALT = "59cf53e54c78" (hardcoded; tumutugma sa opisyal na client)
  • Mga input: mga character sa index 4, 7, 20 ng text ng unang mensahe ng user + version string
  • Output: 3-character na hex prefix

claudeCodeCCH.ts (Client Content Hash)

Isang server-side integrity check na kinukuwenta ng opisyal na Claude Code CLI sa pamamagitan ng Bun/Zig. Muling ipinapatupad ito ng OmniRoute gamit ang xxhash-wasm:

  1. I-serialize ang body gamit ang cch=00000; placeholder
  2. xxhash64(bytes, seed) & 0xFFFFF
  3. 5-character na lowercase hex na nilagyan ng mga zero sa unahan
  4. Palitan ang cch=00000; ng nakuwentang token

Mga constant:

  • Seed: 0x6e52736ac806831e
  • Pattern: /\bcch=([0-9a-f]{5});/

claudeCodeObfuscation.ts

Naglalagay ng Unicode zero-width joiner (U+200D) pagkatapos ng unang character ng mga "sensitibong" pangalan ng client upang hindi ma-grep ng mga upstream filter ang mga ito. Default na listahan ng mga salita:

opencode, open-code, cline, roo-cline, roo_cline, cursor, windsurf,
aider, continue.dev, copilot, avante, codecompanion

Inilalapat sa: mga system block, lahat ng messages[].content, at tools[].description / tools[].function.description. Maaaring i-override ng operator sa pamamagitan ng setSensitiveWords().

claudeCodeCompatible.ts — mga anthropic-compatible-cc-* provider

Para sa mga third-party na Anthropic relay na tumatanggap lamang ng trapikong mula sa "tunay na Claude Code":

  • CLAUDE_CODE_COMPATIBLE_USER_AGENT = "claude-cli/2.1.258 (external, sdk-cli)"
  • CLAUDE_CODE_COMPATIBLE_STAINLESS_PACKAGE_VERSION = "0.112.1"
  • CLAUDE_CODE_COMPATIBLE_STAINLESS_RUNTIME_VERSION = "v26.3.0"
  • anthropic-beta = "claude-code-20250219,interleaved-thinking-2025-05-14,effort-2025-11-24" bilang default
  • Idinaragdag ng toggle na "Enable redact-thinking beta" sa bawat koneksyon ang redact-thinking-2026-02-12 kapag partikular na nangangailangan ang isang CC Compatible upstream ng mga ni-redact na thinking stream
  • Iniimbak ng toggle na "Enable summarized thinking display" sa bawat koneksyon ang providerSpecificData.requestDefaults.summarizeThinking at idinaragdag ang display: "summarized" sa mga CC Compatible thinking request na wala pang nakatakdang display mode
  • CONTEXT_1M_BETA_HEADER = "context-1m-2025-08-07" (pamilya ng Opus/Sonnet 4.x)
  • Default na path: /v1/messages?beta=true

Mga kaugnay na module sa parehong bundle:

  • claudeCodeConstraints.ts — mga panuntunan sa temperature + cache-control
  • claudeCodeToolRemapper.ts — muling pagmamapa ng mga pangalan ng tool
  • claudeCodeExtraRemap.ts — karagdagang normalisasyon ng payload

Antigravity Stealth

Pinapanatili ng mga Antigravity request ang text ng tumatawag nang eksaktong byte-for-byte. Hindi naglalagay ang OmniRoute ng mga zero-width character sa mga prompt o nagpapalit/nag-i-inject ng mga tool upang gayahin ang isang IDE client.

antigravityHeaderScrub.ts

Inaalis ang mga marker ng Stainless SDK (x-stainless-lang, x-stainless-package-version, x-stainless-os, x-stainless-arch, x-stainless-runtime, x-stainless-runtime-version, x-stainless-timeout, x-stainless-retry-count, x-stainless-helper-method) bago i-forward.

⚠️ Panganib: ANTIGRAVITY_CREDITS=always (pangunahing sanhi ng pag-ban ng account)

Ang ANTIGRAVITY_CREDITS=always (ginagamit ng open-sse/executors/antigravity.ts) ay nagruruta sa bawat request sa Antigravity AI Credit Overages (mga bayad na Google credit) sa halip na hayaang limitahan ng free-tier quota ng Google ang paggamit. Nakadokumento ito bilang isang feature, ngunit ito ang nag-iisang pinakakaraniwang ulat ng paglabag sa ToS na nakikita namin — maraming Google Ultra account ang na-ban nang may 403 / "service disabled for ToS violation" / insufficient_quota matapos tumakbo nang ilang oras gamit ang =always.

Ang pagpapatupad ng mga patakaran sa upstream ay nasa panig ng Google, at hindi ito mapipigilan ng OmniRoute. Dahil sa pangalan ng env var at sa umiiral na dokumentasyon, tila isa itong ligtas na opsyong i-enable; ngunit hindi.

Bakit mas agresibo nitong natitrigger ang pagtukoy ng pang-aabuso kaysa sa paggamit lamang ng free tier:

  • Naiiba ang pag-flag sa tuloy-tuloy na automated na paggastos sa iisang Google account kumpara sa free-tier na umaabot sa quota at pagkatapos ay humihinto.
  • Walang limitasyon sa rate ang mga credit overage, kaya maaaring makaubos ang isang maling na-configure na client ng ilang daang USD sa loob ng ilang minuto at magmukhang muling pagbebenta ng API key o trapiko ng bot.
  • Kapag maraming user ng OmniRoute ang sabay-sabay na gumagamit ng mga overage credit mula sa parehong external IP, lalo nitong pinalalakas ang signal.

Inirerekomendang pamamaraan:

  1. Panatilihin ang default na ANTIGRAVITY_CREDITS=off maliban kung tahasang tinatanggap ng operator ang panganib ng paggamit ng bayad na credit at pagpapatupad ng parusa sa account. Ipinapadala muna ng retry ang normal na request at nag-i-inject ng mga credit nang hindi hihigit sa isang beses pagkatapos ng kwalipikadong quota 429; nag-i-inject naman ang always ng mga credit sa unang request.
  2. Ipamahagi ang load sa iba't ibang provider sa pamamagitan ng Auto-Combo (model: "auto" o kr/glm/etc-combo) sa halip na sagarin ang iisang Antigravity account.
  3. Magtakda ng mga RPM limit sa bawat koneksyon sa edit page ng Antigravity provider (Dashboard → Providers → Antigravity → connection → rate limit). Ang 3060 RPM ay isang makatuwirang upper bound para sa tuloy-tuloy na paggamit.
  4. Gumamit ng stable at kontrolado ng operator na upstream networking at iwasang ibahagi ang isang account sa mga user o workload na walang kaugnayan sa isa't isa.
  5. Kung na-ban: magsumite ng apela sa pamamagitan ng support.google.com → "Restore Workspace/Account access" gamit ang eksaktong quota_exceeded / service disabled response body na ipinadala ng Google. Walang garantiya na maibabalik ang access.

Nakadokumento sa environment reference ang mga epekto ng bawat credits mode sa account at paggastos.

Mga touch point:

  • open-sse/executors/antigravity.ts — binabasa ang process.env.ANTIGRAVITY_CREDITS
  • src/lib/oauth/providers/antigravity.ts — pamamahala ng credential
  • Orihinal na ulat ng insidente: Talakayan #1183

Registry ng CLI Fingerprint — open-sse/config/cliFingerprints.ts

Talahanayan para sa bawat provider na nagtatakda ng eksaktong pagkakasunod-sunod ng mga header at ng mga field sa JSON body na nakuha mula sa mga mitmproxy trace ng mga opisyal na CLI. Kasalukuyang nakarehistro: codex, claude, pati ang mga profile na hinango sa runtime sa providerHeaderProfiles.ts para sa antigravity at github.

interface CliFingerprint {
  headerOrder: string[]; // sensitibo sa laki at liit ng titik
  bodyFieldOrder: string[]; // mga top-level na JSON key
  userAgent?: string | (() => string);
  extraHeaders?: Record<string, string>;
}

I-toggle para sa bawat provider sa pamamagitan ng env (tingnan sa ibaba). Kapag naka-disable, lalabas ang mga header/body key sa anumang pagkakasunod-sunod na ibinigay ng Node/JSON — madaling matukoy ang fingerprint.


MITM Proxy (Antigravity, Linux/macOS/Windows)

Para sa mga CLI na hindi maaaring i-redirect ang mga binary sa pamamagitan ng OPENAI_BASE_URL, nagpapatakbo ang OmniRoute ng lokal na proxy na nagwawakas ng TLS. Matatagpuan ang mga endpoint sa ilalim ng src/app/api/cli-tools/antigravity-mitm/.

Pamamaraan Endpoint Layunin
GET /api/cli-tools/antigravity-mitm Katayuan — tumatakbo, pid, dnsConfigured, certExists
POST /api/cli-tools/antigravity-mitm Simulan ang MITM (nangangailangan ng apiKey + sudoPassword)
DELETE /api/cli-tools/antigravity-mitm Ihinto ang MITM
GET /api/cli-tools/antigravity-mitm/alias Ilista ang mga alias ng modelo
PUT /api/cli-tools/antigravity-mitm/alias I-save ang mga alias ng modelo para sa isang tool

Target na naharang na host: daily-cloudcode-pa.googleapis.com (upstream ng Antigravity).

Pagkakasunod-sunod ng pagsisimula (src/mitm/manager.ts::startMitm)

  1. Bumuo ng self-signed cert sa pamamagitan ng selfsigned (RSA-2048, SHA-256, 1y) — cert/generate.ts
  2. I-install ang cert sa system trust store — cert/install.ts
  3. Idagdag ang hosts entry na 127.0.0.1 daily-cloudcode-pa.googleapis.comdns/dnsConfig.ts
  4. I-spawn ang src/mitm/server.cjs gamit ang ROUTER_API_KEY + MITM_LOCAL_PORT (default na 443)
  5. I-persist ang PID sa <DATA_DIR>/mitm/.mitm.pid

Dynamic na pagtukoy ng trust store sa Linux — cert/install.ts

Sinusuri ng getLinuxCertConfig() ang isang listahan ayon sa priyoridad at pinipili ang unang umiiral na directory:

Pamilya ng distro Directory Command sa pag-update
Debian / Ubuntu /usr/local/share/ca-certificates update-ca-certificates
Arch / CachyOS / Manjaro /etc/ca-certificates/trust-source/anchors update-ca-trust
Fedora / RHEL / CentOS /etc/pki/ca-trust/source/anchors update-ca-trust
openSUSE /etc/pki/trust/anchors update-ca-certificates

Filename ng cert: omniroute-mitm.crt. Pagtutugma ng fingerprint sa pamamagitan ng getCertFingerprint() (SHA-1 ng DER).

Bukod pa rito, nag-i-install ang updateNssDatabases() sa mga NSS DB ng bawat user kapag available ang certutil: ~/.pki/nssdb, ~/snap/chromium/.../nssdb, lahat ng profile ng Firefox (kabilang ang snap), sa ilalim ng palayaw na OmniRoute MITM Root CA.

macOS / Windows

  • macOS: security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain
  • Windows: PowerShell na may elevated privileges → certutil -addstore Root

Auth

Nangangailangan ang lahat ng MITM endpoint ng management auth (requireCliToolsAuth). Naka-cache ang sudo password sa module scope (hindi kailanman sa globalThis) at nililinis kapag tinawag ang stopMitm().


Mga Override ng User-Agent — mga env var (.env.example seksyon 12)

Variable Default
CLAUDE_USER_AGENT claude-cli/2.1.258 (external, cli)
CODEX_USER_AGENT codex-cli/0.149.0 (Windows 10.0.26200; x64)
GITHUB_USER_AGENT GitHubCopilotChat/0.54.0
ANTIGRAVITY_USER_AGENT antigravity/2.0.1 linux/arm64 google-api-nodejs-client/10.3.0
KIRO_USER_AGENT AWS-SDK-JS/3.0.0 kiro-ide/1.0.0
QODER_USER_AGENT Qoder-Cli
CURSOR_USER_AGENT Cursor/3.4

Ginagamit ng open-sse/executors/base.ts::buildHeaders() sa pamamagitan ng dinamikong lookup. I-update ang mga ito kapag naglabas ang mga provider ng mga bagong bersyon ng CLI — ang mga lumang UA string ay nagsisimulang tanggihan bilang mga lipas nang client.

Mga Toggle ng CLI Compatibility Mode (.env.example seksyon 13)

Variable Epekto
CLI_COMPAT_CODEX=1 Fingerprint ng Codex
CLI_COMPAT_CLAUDE=1 Fingerprint ng claude-cli
CLI_COMPAT_GITHUB=1 Fingerprint ng GitHub Copilot Chat
CLI_COMPAT_ANTIGRAVITY=1 Fingerprint ng Antigravity
CLI_COMPAT_KIRO=1 Kiro
CLI_COMPAT_CURSOR=1 Cursor
CLI_COMPAT_KIMI_CODING=1 Kimi Coding
CLI_COMPAT_KILOCODE=1 KiloCode
CLI_COMPAT_CLINE=1 Cline
CLI_COMPAT_ALL=1 I-enable ang lahat ng nasa itaas

Palaging pinananatili ang IP ng provider — binabago lamang ng toggle ang anyo ng request sa wire, hindi nito inililipat ang IP egress.


Paglilinis ng mga Papasok na Header

Inaalis ng OmniRoute ang mga papasok na header ng client bago mag-forward upang ang request na nagmula sa Cursor ay hindi maglantad ng User-Agent: Cursor/X.Y.Z sa isang Claude upstream. Tingnan ang src/shared/constants/upstreamHeaders.ts para sa denylist, na pinananatiling eksaktong nakaayon sa mga Zod schema at unit test.


Pag-update ng mga Fingerprint Kapag Nagpalit ang Isang Provider

  1. I-capture ang opisyal na trapiko ng CLI gamit ang mitmproxy (TLS interception + dump)
  2. I-extract ang JA3/JA4 at ang literal na pagkakasunod-sunod ng mga header
  3. I-update ang nauugnay na entry na CLI_FINGERPRINTS[...]
  4. I-update ang katugmang default na *_USER_AGENT sa .env.example
  5. Kung nagbago mismo ang TLS handshake, i-update ang nauugnay na provider wrapper o ang opsyong browser: ng wreq-js
  6. Patakbuhin ang mga TLS test na partikular sa provider at isang manu-manong canary laban sa live na provider
  7. I-release bilang patch release; idokumento sa CHANGELOG.md

Mga Test

  • open-sse/services/__tests__/claudeTlsClient.test.ts — gawi ng shared TLS wrapper
  • tests/unit/anthropic-cache-fingerprint.test.ts — determinismo ng fingerprint
  • tests/unit/chatgpt-web-source-retirement.test.ts — nananatiling wala ang karaniwang stealth source ng ChatGPT Web habang nananatiling naroon ang Codex Web

Tingnan Din