Open-source project
IRNova/Nova-Proxy-App avatar
IRNova/Nova-Proxy-App

NovaProxy: a desktop proxy that terminates TLS locally and relays through Google

نوا پروکسی - ابزار پروکسی محلی قدرتمند با قابلیت‌های GSA (Google Apps Script) با Domain Fronting، تکه‌تکه‌سازی TLS، تزریق ECH، بازپخش QUIC، MITM و مسیریابی هوشمند. طراحی شده برای عبور از فیلترینگ سنگین و DPI پیشرفته.

865 stars129 forksGoLicense varies

At a glance

What is it?
NovaProxy is a Wails based desktop proxy in Go with two engines: a local MITM engine that terminates TLS with dynamically generated certificates, and a relay that carries traffic through Google Apps Script to a Cloudflare Worker. It is built to look like ordinary traffic to a middlebox, and the README is written in Persian.
Who is it for?
Adopt NovaProxy if you are on a network with heavy filtering and want a local client that tunnels through infrastructure that is unlikely to be blocked, and you are comfortable installing a local root certificate and running a MITM proxy on your own machine.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 26 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two engines: one on your machine, one on Google's infrastructure

NovaProxy is a desktop proxy written in Go with a Wails v3 interface, and the repository description is explicit about its purpose: it passes internet traffic through Google and Cloudflare infrastructure so that, from the point of view of a DPI system, the traffic looks like an ordinary connection to a Google domain while the real request goes to any site you choose.

The architecture diagram in the README makes the two halves explicit. The MITM engine terminates TLS, issues dynamic certificates, spoofs the SNI and fragments traffic. The GSA relay moves traffic from Google Apps Script to a Cloudflare Worker with HTTP/2 multiplexing.

bash
Client → CONNECT tunnel → TLS Termination (MITM Cert) → Upstream TLS (SNI spoofed) → Target
                            │
                     Dynamic Cert Generation
                     (ECDSA P256 signed by Root CA)

That split is the design. The first engine runs on your own machine, because that is where the browser's traffic has to be intercepted, and the second engine runs inside infrastructure that a filter is unlikely to touch, because that is where the tunnel has to survive inspection.

The application is a native desktop program rather than a command line tool, which follows from the fact that it has to install a certificate into the operating system's trust store and, in some cases, into Firefox. The README is in Persian with a separate English version in the repository, and the last push was on 2026-10-01 with releases v1.2, v1.1.1 and v1.1.0 landing in May 2026. The licence is not stated in the repository listing, which is worth settling before you install something that touches every request you make.

The local engine intercepts CONNECT and can forward, tunnel or terminate

The MITM engine is written as a decision tree over what a client does with the proxy, and the branches are named in the source layout of the README diagram.

bash
ProxyServer.handleConnect()

From there the paths are direct, which is a raw TCP tunnel, transparent, which passes TLS bytes through without terminating them, tls-rf, which fragments the ClientHello and then tunnels, quic, which performs the MITM over QUIC and HTTP/3, and mitm, which terminates the TLS and hands over to the upstream connection logic.

The upstream connection step is the interesting one, because it is where the fingerprinting happens:

bash
                    │  - resolve candidates
                    │  - uTLS handshake (fingerprint randomization)
                    │  - ALPN negotiation (h2 / http/1.1)
                    │  - ECH support

Resolving candidates and then handshaking with a randomised fingerprint is how the upstream connection is made to look like a browser rather than like a Go program, since a Go TLS client has a recognisable handshake. The ALPN negotiation decides whether the session continues over HTTP/2 or HTTP/1.1, and the ECH support means the client hello can carry an encrypted server name so that the real host is not visible in plaintext on the wire.

The certificate side is generated on the fly, per host:

bash
                    │  makeMITMTLSConfig()
                    │  - generateCert(host, CA cert, CA key)
                    │  - ECDSA P256 per-host cert
                    │  - cache certs in memory
                    │  - serve to client via tls.Server()

A root CA signed with RSA 2048 signs ECDSA P256 leaf certificates, one per host, and the leaf certificates are cached in memory. The root CA itself can be created, installed and removed across Windows, macOS, Linux and Firefox, and on Windows the installer runs the system commands in a hidden process with administrator rights. After the handshake, the traffic is copied both ways with pooled buffers.

The alternative to all of this is the transparent mode, which forwards the encrypted bytes untouched, and it is a reminder that the MITM is a choice rather than a necessity for every connection.

Fragmentation and ECH are the parts aimed at the middlebox

The feature table in the README is where the intent becomes explicit.

TLS fragmentation splits the ClientHello into several segments with an adjustable delay, and the stated purpose is passing a DPI. The mechanism is well known: a middlebox that only inspects the first packet of a connection sees a truncated, unparseable handshake, while the server reassembles the pieces. The cost is latency at connection start and a small risk that a middlebox treats the split as an attack.

Encrypted ClientHello support is the other one, and the README lists it as ECG, which is a typo for ECH, for hiding the SNI. It is the cleaner of the two methods because it does not rely on the middlebox being naive, only on the origin server and the client supporting it.

QUIC is handled with the quic-go library, and the MITM works over HTTP/3 as well as over HTTP/1.1 and HTTP/2. That matters because more and more traffic moves to QUIC by default, and a proxy that only handles TCP would either fail on those connections or force a downgrade.

Then there is the certificate verification options, with an allow_names mode that acts as a whitelist and support for custom CA pinning. That is the part of the feature set aimed at the security conscious user rather than at the middlebox: a MITM proxy that blindly signs everything for any host is a real risk on a shared machine, and a name whitelist plus pinning are the two controls that address it.

The trade-off is honest. Everything the tool does to look ordinary to a filter, it also does to the middlebox in front of the destination, and the traffic it produces is still your traffic, carried over a chain you do not own.

The relay chain is Apps Script, then a Worker, then the target

The second engine carries the traffic, and the diagram is the clearest description in the repository.

bash
Browser
    │
    ▼
GSA Proxy (127.0.0.1:8085)
    │  ← TLS Termination (MITM cert)
    ▼
H2 Connection → Google IP (SNI: www.google.com)

The GSA proxy listens on 127.0.0.1:8085, terminates TLS for the browser with the MITM certificate, and then opens an HTTP/2 connection to a Google IP with the SNI set to a Google domain. From there the traffic enters Google Apps Script, which relays it as JSON inside Google's infrastructure, and a Cloudflare Worker performs the final fetch to the target site and exits from a Cloudflare IP.

The request handling is where the engineering is:

bash
gsaProxyServer.start()
    │
    ├── acceptLoop() → handleHTTP(conn)
    │       │
    │       ├── CONNECT → handleCONNECT()
    │       │       ├── gsaShouldDirectConnect() → relayRawTCP()
    │       │       └── TLS: mitm.getCert() → TLS Server → relayHTTPOverTLS()
    │       │
    │       ├── OPTIONS + access-control-request → CORS Preflight
    │       │
    │       └── GET/POST → relayRequest()

A CONNECT can either be relayed raw or be terminated and carried over TLS. OPTIONS requests with an access control request header get a CORS preflight answer, which is what makes a browser accept the proxied response.

Beneath that, the relay path branches on the kind of request. A stateful request is relayed on its own with no caching and no batching. A plain GET with no range header tries to coalesce, so several waiters share one response. Everything else can be batched, with a five millisecond window and a maximum of fifty items per batch. Responses are cached in an LRU cache of 50 MB, with time to live values of an hour, thirty minutes, or the maximum age the origin sends.

At the transport level there is an HTTP/2 client with SNI pool rotation, and an HTTP/1.1 pool as a fallback with a maximum of fifty connections and a forty-five second time to live. A manager component handles start and stop, automatic failover by scanning for new IPs when errors appear, SNI rotation of the fronting domain, a heartbeat every thirty seconds, a scanner that uses twenty-six fixed Google addresses plus DNS, a real download speed test, and a TCP plus TLS connection test.

The module file replaces two dependencies with local forks

The go.mod file is short and reveals a lot. The module is named novaproxy and requires Go 1.25.5, with direct dependencies on brotli and the compress library for compression, the miekg/dns library for DNS, quic-go, uTLS from refraction-networking, the v2fly v2ray-core, the Wails v3 desktop framework, and the x/net and x/sys packages.

Then come the two replace directives that matter:

bash
replace github.com/v2fly/v2ray-core/v5 => ./v2ray-core-master

replace github.com/refraction-networking/utls => ./utls

Both dependencies are redirected to directories inside the repository rather than to their published versions. In practice that means the build expects a v2ray-core-master directory and an utls directory next to the module file.

The repository listing does not show either of those directories, so a fresh clone of the tree as published does not contain the sources those two replacements point at, and the build will not resolve until they are present. That is a packaging fact worth checking before you spend time on it, and it is the kind of thing that comes from a project that builds by dropping upstream trees into a working copy.

The rest of the layout is consistent with a desktop application. There is a cert/ directory for the certificate generation and installation code, a proxy/ directory for the MITM handler, the fragmentation logic, the certificate verification and a Cloudflare IP pool, plus scr/, server/ and sysproxy/ directories, a set of core_ files at the root for the client, runtime, markers and API, a wails.json for the desktop shell configuration, a versioninfo.json for Windows metadata, and a novaproxy.syso resource file that carries the icon into the executable.

Trust, licensing and the parts you do not control

Three questions deserve an answer before this tool goes on a work machine.

The first is the root certificate. The application creates a CA, installs it into the operating system trust store and, when relevant, into Firefox, which is what allows it to issue per-host certificates that browsers accept. On a machine you own, that is a normal arrangement for a local debugging proxy, and the README provides a removal path. On a shared or monitored machine, it means that any process able to read the key can impersonate any site to any application on it, and the operational security question is whether that trade is acceptable to your organisation.

The second is what you do not control. The chain depends on a Google Apps Script deployment that somebody owns, a Cloudflare Worker, and a fronting domain that the tool rotates. You do not own the Apps Script account, so a deployment being removed, a quota being exhausted or a policy being applied upstream will break the tunnel, and the README does not describe a fallback to a path you own.

The third is the licence. The repository listing records no licence, and the README does not carry a licence section, so there is no stated permission to modify and redistribute. For a tool you install on your own machine that does not stop you, but it is a gap that a team distributing the binary internally would want closed.

On maintenance, the project is being worked on, with the last push on 2026-10-01 and three releases in May 2026. The version numbers are conventional rather than date-based, and there is no homepage recorded, so the repository and the README are the whole documentation.

Editorial conclusion

Adopt NovaProxy if you are on a network with heavy filtering and want a local client that tunnels through infrastructure that is unlikely to be blocked, and you are comfortable installing a local root certificate and running a MITM proxy on your own machine. Do not adopt it as a general purpose VPN, because the design depends on domain fronting through Google Apps Script and on a Cloudflare Worker, both of which are outside your control, and do not assume the code in the repository builds as published, because the module file replaces two dependencies with local directories that are not part of the tree. Before you rely on it, check which fronting domain and Apps Script deployment it uses, since those are the parts that break first when the upstream changes.

Frequently asked questions

What is NovaProxy and how does it work?

NovaProxy is a Go desktop application built with Wails v3 that has two engines. The MITM engine terminates TLS locally with dynamically generated certificates and spoofs the SNI, and the GSA relay carries the traffic through Google Apps Script to a Cloudflare Worker with HTTP/2 multiplexing, so that filtering systems see traffic addressed to a Google domain.

Does NovaProxy install a certificate on my machine?

Yes. The root CA can be created, installed and removed across Windows, macOS, Linux and Firefox, and on Windows the installer runs the system commands in a hidden process with administrator rights. The MITM engine then issues a per-host ECDSA P256 certificate signed by that CA and serves it to the client.

How does NovaProxy avoid being detected by filtering?

The upstream connection uses a randomised TLS fingerprint to look like a browser, the ClientHello can be fragmented into several segments with an adjustable delay, and ECH support hides the real server name. The relay side rotates the fronting domain and uses a pool of Google addresses.

Can I build NovaProxy from the repository as published?

Probably not without extra work. The go.mod file replaces the v2fly v2ray-core and the refraction-networking utls dependency with local directories, ./v2ray-core-master and ./utls, and neither directory appears in the repository listing, so those sources have to be supplied before the build resolves.

What licence is NovaProxy released under?

The repository listing records the licence as unknown and the README does not carry a licence section, so there is no stated permission to modify or redistribute the code. The project is being worked on, with the last push on 2026-10-01 and releases v1.2, v1.1.1 and v1.1.0 in May 2026.

Official sources

  1. IRNova/Nova-Proxy-App on GitHub
  2. Issues
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/irnova-nova-proxy-app.svg)](https://hysenlabs.com/projects/irnova-nova-proxy-app)

Was this useful?