---
id: 6e0bce9e22a4bf7d9672c59e67bcf5ec
author: Lemon Mint
title: 'gosuda.org/chromenet: Sieťový zásobník Chromium pre Go, vytvorený reprodukovateľne z pevne určeného vydania'
description: CGO_ENABLED=0 Go http.RoundTripper, ktorý odosiela požiadavky cez vlastný zásobník //net prehliadača Chromium (HTTP/1.1, HTTP/2, QUIC/HTTP/3, BoringSSL) v izolovanom HQQ workeri, so zdrojovým kódom, toolchainmi a šiestimi vnorenými binárnymi súbormi pripnutými pomocou SHA-256 a zostavenými v sandboxoch gvx.
language: sk
date: 2026-11-09T00:00:00Z
path: /chromenet
go_package: gosuda.org/chromenet
go_repourl: https://github.com/gosuda/chromenet.git
category: network
---

`gosuda.org/chromenet` je Go `http.RoundTripper`, ktorý odosiela požiadavky cez vlastný sieťový zásobník Chromium. Zásobník je `//net` z oficiálneho vydania Chromium: jeho implementácie HTTP/1.1, HTTP/2 a QUIC/HTTP/3, BoringSSL, konfigurácia TLS prehliadača Chrome a Chrome Root Store. Beží v samostatnom pracovnom procese `chrome_net_server` a strana Go zostáva čisto Go (`CGO_ENABLED=0`), pričom s pracovným procesom komunikuje prostredníctvom RPC so zdieľanou pamäťou [HQQ](https://gosuda.org/hqq).

```bash
go get gosuda.org/chromenet@v0.1.10157081033800
```

## Prečo spúšťať sieťový zásobník Chromium

Program v Go, ktorý komunikuje s webom pomocou `net/http`, sa voči serveru prezentuje ako klient Go. Je to správny predvolený postup pre komunikáciu medzi službami. Je to však nevhodné vtedy, keď správanie servera závisí od toho, za aký typ klienta ho považuje: koncové body chránené kontrolou prehliadača, middleware proti botom, CDN, ktoré poskytujú rôzne verzie protokolov podľa odtlačkov TLS a HTTP/2, a testy, ktoré musia reprodukovať to, čo zažíva skutočný prehliadač.

Štandardná knižnica Go nedokáže poskytnúť sieťové správanie prehliadača. `crypto/tls` má vlastné poradie šifrovacích sád a množinu rozšírení a `net/http` má vlastné nastavenia HTTP/2. Knižnice, ktoré napodobňujú prehliadač kopírovaním bajtov ClientHello, ich kopírujú vydanie za vydaním. `chromenet` ide inou cestou: nenapodobňuje sieťový zásobník Chromium, ale spúšťa ho.

Meraním na `darwin/arm64` s verejnou službou na zisťovanie odtlačkov (`tls.peet.ws`) predvolená konfigurácia hlási:

| Vlastnosť                          | Pozorovaná hodnota                                                    |
| :--------------------------------- | :-------------------------------------------------------------------- |
| Dohodnutý protokol                 | `h2`                                                                  |
| JA4                                | `t13d1516h2_8daaf6152771_806a8c22fdea`                                |
| Odtlačok HTTP/2 (formát Akamai)    | `1:65536;2:0;4:6291456;6:262144\|15663105\|0\|m,a,s,p`                |
| User-Agent                         | desktopový Chrome s hlavnou verziou enginu, napr. `Chrome/157.0.0.0`  |

S `ForceHTTP3` boli požiadavky na `cloudflare-quic.com` a `www.google.com` zodpovedané cez HTTP/3. Tieto čísla pochádzajú z jednej platformy v jeden deň. Engine je samotný zásobník, takže sa zmenia vždy, keď sa zmení pripnuté vydanie Chromium.

## Použitie

`NewTransport` vracia `http.RoundTripper`. Použite ho všade, kde by ste použili `http.Transport`:

```go
package main

import (
	"fmt"
	"io"
	"net/http"

	"gosuda.org/chromenet"
)

func main() {
	client := &http.Client{Transport: chromenet.NewTransport(chromenet.Options{})}

	resp, err := client.Get("https://example.com/")
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.Proto, resp.StatusCode, len(body))
}
```

Pri prvej požiadavke modul zapíše vloženú binárku pracovného procesu pre vašu platformu do používateľského adresára cache, overí jej digest SHA-256 pomocou `gosuda.org/hqq/secureexec`, spustí ju s rodičovským životným prepojením (`--parent-stdin`, takže skončí, keď skončí váš proces) a otvorí pool relácií. Nič nie je potrebné inštalovať.

Niekoľko správaní nasleduje `http.Transport`, aby `http.Client` fungoval bez zmien:

- Transport nesleduje presmerovania a neuchováva cookies. `http.Client` robí obe veci, rovnako ako pri `http.Transport`.
- Odpovede komprimované pomocou gzip, deflate, Brotli alebo zstd prichádzajú dekódované a `resp.Uncompressed` je true.
- Požiadavka drží jednu reláciu enginu, kým sa telo odpovede nezatvorí. Telá zatvárajte.
- Zrušenie kontextu požiadavky zruší požiadavku vnútri Chromium.
- Sieťové chyby sú hodnoty `*client.NetError` obsahujúce chybový kód Chromium a jeho názov:

```go
var ne *client.NetError
if errors.As(err, &ne) {
	fmt.Println(ne.Code, ne.Name) // -105 ERR_NAME_NOT_RESOLVED
}
```

### Možnosti

| Pole                          | Účinok                                                                                                  |
| :---------------------------- | :------------------------------------------------------------------------------------------------------ |
| `UserAgent`                   | Nahradí predvolený User-Agent Chrome. Hlavička požiadavky `User-Agent` má stále prednosť.              |
| `AcceptLanguage`              | Nahradí `en-US,en;q=0.9`.                                                                               |
| `Proxy`                       | Pravidlá proxy Chromium, napríklad `http://127.0.0.1:8080` alebo `socks5://127.0.0.1:1080`. Prázdna hodnota znamená priame pripojenie. |
| `DisableHTTP2`, `DisableQUIC` | Vypnú protokoly.                                                                                        |
| `ForceHTTP3`                  | Použije QUIC pre každý pôvod bez čakania na oznámenie `Alt-Svc`.                                        |
| `InsecureSkipVerify`          | Prijme ľubovoľný certifikát servera.                                                                    |
| `Pool`                        | Relácie enginu na použitie. Nil používa `client.DefaultPool()`, ktorý povoľuje 64 súbežných požiadaviek. |

Transporty s rovnakými možnosťami zdieľajú jeden Chromium `URLRequestContext`, takže connection pooly, relácie HTTP/2 a relácie QUIC sa znovu používajú naprieč požiadavkami. Nastavenie `HQQ_CHROME_NET_SERVER=/path/to/chrome_net_server` nahradí vložený pracovný proces, napríklad lokálnym buildom.

## Ako to funguje

| Vrstva              | Čo tam beží                                                                                                                                                                                  |
| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Váš program         | `http.Client` a `chromenet.Transport`, čisté Go.                                                                                                                                             |
| Hranica procesov    | RPC so zdieľanou pamäťou cez HQQ. Rozhranie je `chrome_net.idl`, ktoré `hqq-bindgen` skompiluje do klienta v Go a C glue kódu servera.                                                      |
| `chrome_net_server` | Malá vrstva v C++ nad Chromium: jedno sieťové vlákno, ktoré vlastní všetky objekty `//net`, a vlákna relácií, ktoré blokujú, kým sieťové vlákno neodpovie na požiadavku.                     |
| Chromium `//net`    | `URLRequestContext`, `URLRequest`, relácie HTTP/2 a QUIC, BoringSSL.                                                                                                                          |

IDL obsahuje šesť operácií, ktoré sú dôležité: vytvorenie enginu z možností `key=value`, spustenie požiadavky s jej hlavičkou (`METHOD URL` plus riadky hlavičiek) a dĺžkou tela, zápis častí tela požiadavky, čakanie na hlavičku odpovede, čítanie dekódovaného tela a zničenie handle. Handle požiadavky deklaruje `@cancel`, takže opustené volanie preruší požiadavku vnútri Chromium namiesto toho, aby ju nechalo bežať až do konca.

Izolácia zásobníka v pracovnom procese je rovnako bezpečnostná vlastnosť ako vlastnosť balíkovania. Sieťový kód Chromium spracúva nedôveryhodný vstup z otvoreného internetu. Ak zlyhá, vaša služba v Go s ním nespadne: volanie zlyhá s chybou, relácia sa zahodí a klient pri ďalšej potrebe spustí nový pracovný proces.

## Reprodukovateľne zostavené, pripnuté pomocou SHA-256

Binárka s veľkosťou 25 MB, ktorá obsahuje Chromium, je dôveryhodná len vtedy, ak viete presne povedať, čo do nej vstúpilo. `chromenet` sleduje Chromium Stable rovnako, ako `gosuda.org/sqlite3` sleduje SQLite: zdroj sa nikdy nevendoruje, iba pripne.

| Pin                                                                                                                              | Kde                            |
| :------------------------------------------------------------------------------------------------------------------------------- | :----------------------------- |
| Vydanie Chromium a jeho oficiálny archív zdrojov `-lite`                                                                         | `third_party/chromium/VERSION` |
| SHA-256 archívu a každého nástroja, ktorý vydanie pripína: clang, Rust, GN, ninja, runtime clang pre Windows, xwin              | `third_party/chromium/SHA256`  |
| Verzie MSVC CRT a Windows SDK sťahované cez xwin                                                                                 | `third_party/chromium/WINSDK`  |
| Vydanie sandbox runtime (`rungv`), digest obrazu hosťa, dátum snapshotu Debianu                                                  | `scripts/engine/BUILDENV`      |
| C runtime HQQ                                                                                                                    | `go.mod` a `go.sum`            |

Aktuálny pin je Chromium `157.0.8103.38`. Stiahnutie, ktoré nezodpovedá svojmu pinu, zastaví zostavenie. Vydanie aplikuje na Chromium presne jednu záplatu: na Linuxe sa `chrome_net_server` zostavuje bez NSS a overuje certifikáty serverov iba voči Chrome Root Store, takže binárka potrebuje okrem libc nič iné.

Engine pre Linux a Windows sa zostavujú vnútri sandboxov [gvx](https://gosuda.org/blog/posts/gvx-cross-platform-linux-containers-z48916d01): neprivilegovaných procesov s pripnutým obrazom hosťa a bez démona na hostiteľovi. Engine pre Windows sa krížovo kompilujú na Linuxe pomocou clang-cl a lld-link od Chromium proti Windows SDK, ktoré xwin sťahuje od Microsoftu. Engine pre macOS sa zostavujú natívne na macOS runneri, pretože zostavenie Chromium pre macOS vyžaduje Xcode.

Opätovné zostavenie rovnakého commitu vytvorilo bajtovo identické binárky naprieč oddelenými behmi CI. Vydané binárky sú bajtovo identické s tými, ktoré zostavil skorší beh CI pre commit, ktorý dostal engine do monorepa, na všetkých šiestich platformách.

| Platforma       | Veľkosť binárky |
| :-------------- | --------------: |
| `linux/amd64`   |         27.9 MB |
| `linux/arm64`   |         27.4 MB |
| `darwin/amd64`  |         26.2 MB |
| `darwin/arm64`  |         23.9 MB |
| `windows/amd64` |         27.3 MB |
| `windows/arm64` |         25.8 MB |

Engine pre Linux závisia iba od `libc`, `libm`, `libdl`, `libpthread` a `libgcc_s` a vyžadujú glibc 2.31 alebo novšiu verziu.

### Sledovanie Chromium a vydaní

Naplánovaný workflow kontroluje Chromium Stable každých šesť hodín. Pri novom vydaní prepíše piny, zostaví a otestuje všetkých šesť enginov vo vetve `chromium/<version>`, atestuje binárky a commitne piny spolu s vloženými binárkami, ich digestami a licenčnými textami do `main` v jednom commite. V monorepe súbory `OWNERS` pre jednotlivé súbory udeľujú botovi workflowu presne tieto súbory, takže aktualizácia sa dostane do repozitára bez ľudského kroku, zatiaľ čo zmeny samotného receptu zostavenia (pin Windows SDK a záplata) stále vyžadujú vlastníka.

Každá vydaná binárka nesie atestáciu pôvodu zostavenia z workflowu, ktorý ju zostavil:

```bash
gh attestation verify chrome_net_server_linux_amd64 --repo gosuda/chromenet
```

Licenčné texty obsahu každej binárky (Chromium, BoringSSL, QUICHE a zvyšok zostavovacieho grafu) generuje vlastný nástroj Chromium `tools/licenses/licenses.py` a dodávajú sa s vydaním ako `NOTICE_<os>_<arch>.txt`.

## Obmedzenia

- `DialWebSocket` je čistý Go klient RFC 6455 a nepoužíva sieťový zásobník Chromium.
- `DialWebTransport` je implementácia v rámci procesu. Na server nedosiahne.
- Predvolené odtlačky JA4 a HTTP/2 sú odtlačky pripnutého vydania Chromium. Chromium ich mení vydanie za vydaním a `chromenet` ich sleduje.
- Binárky pre macOS sú podpísané ad-hoc a nie sú notarizované.
- Pracovný proces stojí pamäť. Každá binárka enginu má na disku 24 až 28 MB a runtime Chromium spúšťa thread pool a sieťové vlákno.
- Relácia enginu je držaná, kým sa telo odpovede nezatvorí. Program, ktorý necháva telá odpovedí neuzavreté, vyčerpá pool.

## Zdroj

Repozitár je [github.com/gosuda/chromenet](https://github.com/gosuda/chromenet), zrkadlený z `//net/chromenet` v monorepe gosuda. Recept zostavenia sa nachádza v `scripts/engine`, glue enginu v `engine/` a rozhranie v `chrome_net.idl`.
