---
id: 6e0bce9e22a4bf7d9672c59e67bcf5ec
author: Lemon Mint
title: 'gosuda.org/chromenet: Chromium hálózati veremje Go-hoz, reprodukálhatóan építve egy rögzített kiadásból'
description: CGO_ENABLED=0 Go http.RoundTripper, amely a Chromium saját //net vermén (HTTP/1.1, HTTP/2, QUIC/HTTP/3, BoringSSL) keresztül küldi el a kéréseket, egy izolált HQQ munkafolyamatban, a forráskóddal, az eszközláncokkal és a hat beágyazott bináris fájllal, amelyek SHA-256 ellenőrző összegekkel vannak rögzítve, és gvx homokozókban épülnek.
language: hu
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` egy Go `http.RoundTripper`, amely a kéréseket a Chromium saját hálózati veremén keresztül küldi el. A verem a hivatalos Chromium-kiadás `//net` komponense: ennek HTTP/1.1, HTTP/2 és QUIC/HTTP/3 implementációi, a BoringSSL, a Chrome TLS-konfigurációja és a Chrome Root Store. Külön munkafolyamatban fut, a `chrome_net_server` nevű folyamatban, a Go oldal pedig tiszta Go marad (`CGO_ENABLED=0`), és a munkafolyamattal az [HQQ](https://gosuda.org/hqq) osztott memórián alapuló RPC-n keresztül kommunikál.

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

## Miért futtassuk a Chromium hálózati vermét

Egy Go program, amely a `net/http` csomaggal kommunikál a weben, Go kliensként mutatkozik be a szerver felé. Ez a helyes alapbeállítás szolgáltatások közötti forgalomhoz. Helytelen viszont akkor, ha a szerver viselkedése attól függ, milyen típusú kliensnek gondolja a másik felet: böngészőhöz kötött végpontok, botellenes köztes szoftverek, olyan CDN-ek, amelyek eltérő TLS- és HTTP/2-ujjlenyomatokhoz eltérő protokollverziókat szolgálnak ki, valamint tesztek, amelyeknek egy valódi böngésző tapasztalatait kell reprodukálniuk.

A Go standard könyvtára nem tudja visszaadni a böngésző hálózati viselkedését. A `crypto/tls` saját titkosítócsomag-sorrenddel és kiterjesztéskészlettel dolgozik, a `net/http` pedig saját HTTP/2-beállításokkal. A böngészőt ClientHello-bájtjainak másolásával utánzó könyvtárak kiadásról kiadásra másolni kényszerülnek. A `chromenet` más utat választ: nem utánozza a Chromium hálózati vermét, hanem futtatja azt.

Az `darwin/arm64` motoron, egy nyilvános ujjlenyomat-szolgáltatás (`tls.peet.ws`) ellen mérve, az alapértelmezett konfiguráció a következőket jelzi:

| Tulajdonság                         | Megfigyelt érték                                                         |
| :---------------------------------- | :----------------------------------------------------------------------- |
| Egyeztetett protokoll               | `h2`                                                                     |
| JA4                                 | `t13d1516h2_8daaf6152771_806a8c22fdea`                                   |
| HTTP/2 ujjlenyomat (Akamai formátum) | `1:65536;2:0;4:6291456;6:262144\|15663105\|0\|m,a,s,p`                   |
| User-Agent                          | asztali Chrome a motor főverziójával, például `Chrome/157.0.0.0`         |

A `ForceHTTP3` beállítással a `cloudflare-quic.com` és a `www.google.com` címre irányuló kéréseket HTTP/3-on válaszolták meg. Ezek a számok egy platformon, egy napon mérve születtek. A motor maga a verem, ezért ezek a számok változnak, amikor a rögzített Chromium-kiadás megváltozik.

## Használat

A `NewTransport` egy `http.RoundTrippert` ad vissza. Bárhol használhatjuk, ahol `http.Transport`-ot használnánk:

```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))
}
```

Az első kérésnél a modul kiírja a beágyazott, az adott platformhoz tartozó munkafolyamat-bináris fájlt a felhasználói gyorsítótár könyvtárába, ellenőrzi annak SHA-256 ellenőrző összegét a `gosuda.org/hqq/secureexec` csomaggal, elindítja szülői életjellel (`--parent-stdin`, így kilép, amikor a folyamata kilép), majd megnyit egy munkamenet-készletet. Semmit sem kell telepíteni.

Néhány viselkedés az `http.Transport` mintáját követi, így az `http.Client` változatlanul működik:

- A Transport nem követi az átirányításokat, és nem tárol sütiket. Ezt a `http.Client` teszi meg, ahogy az `http.Transport`-tal is.
- A gzip, deflate, Brotli vagy zstd tömörítéssel érkező válaszok dekódolva érkeznek, és a `resp.Uncompressed` értéke igaz.
- Egy kérés addig tart egy motormunkamenetet, amíg a válasz törzse le nem záródik. A törzseket mindig zárjuk le.
- A kérés kontextusának megszakítása a kérést a Chromiumon belül is megszakítja.
- A hálózati hibák `*client.NetError` értékek, amelyek tartalmazzák a Chromium hibakódját és nevét:

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

### Beállítások

| Mező                          | Hatás                                                                                                  |
| :---------------------------- | :----------------------------------------------------------------------------------------------------- |
| `UserAgent`                   | Lecseréli az alapértelmezett Chrome User-Agent értéket. A kérés `User-Agent` fejléce továbbra is felülírja. |
| `AcceptLanguage`              | Lecseréli a `en-US,en;q=0.9` értéket.                                                                  |
| `Proxy`                       | Chromium proxyszabályok, például `http://127.0.0.1:8080` vagy `socks5://127.0.0.1:1080`. Üres érték esetén közvetlen kapcsolat. |
| `DisableHTTP2`, `DisableQUIC` | Kikapcsolják a protokollokat.                                                                          |
| `ForceHTTP3`                  | Minden eredethez QUIC-et használ, anélkül hogy megvárná az `Alt-Svc` hirdetést.                        |
| `InsecureSkipVerify`          | Bármely szerver tanúsítványát elfogadja.                                                               |
| `Pool`                        | A használandó motormunkamenetek. Nil esetén a `client.DefaultPool()` használatos, amely 64 egyidejű kérést enged. |

Az azonos beállításokkal rendelkező transportok egyetlen Chromium `URLRequestContext`-et osztanak meg, így a kapcsolatkészletek, HTTP/2-munkamenetek és QUIC-munkamenetek a kérések között újrahasznosulnak. A `HQQ_CHROME_NET_SERVER=/path/to/chrome_net_server` beállítás a beágyazott munkafolyamatot helyettesíti, például egy helyi build használatával.

## Működés

| Réteg               | Mi fut ott                                                                                                                                                                  |
| :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Az Ön programja     | `http.Client` és `chromenet.Transport`, tiszta Go.                                                                                                                          |
| Folyamathatár       | HQQ osztott memórián alapuló RPC. Az interfész a `chrome_net.idl`, amelyet a `hqq-bindgen` fordít le a Go kliensbe és a C szerveroldali összekötő kódba.                  |
| `chrome_net_server` | Egy kis C++ réteg a Chromium felett: egy hálózati szál, amely minden `//net` objektumot birtokol, és munkamenet-szálak, amelyek blokkolva várnak a kérésre, amíg a hálózati szál válaszol. |
| Chromium `//net`    | `URLRequestContext`, `URLRequest`, HTTP/2 és QUIC munkamenetek, BoringSSL.                                                                                                  |

Az IDL hat lényeges műveletet tartalmaz: motor létrehozása `key=value` beállításokból, kérés indítása a fejléccel (`METHOD URL` plusz fejlécsorok) és a törzs hosszával, a kérés törzsének darabjainak írása, a válasz fejlécére várakozás, a dekódolt törzs olvasása, valamint a kezelők megsemmisítése. A kérésfogantyú deklarálja a `@cancel` jelölést, így egy elhagyott hívás a Chromiumon belül megszakítja a kérést, ahelyett hogy befejezéséig futna.

A verem munkafolyamatba való izolálása ugyanannyira biztonsági tulajdonság, mint csomagolási kérdés. A Chromium hálózati kódja a nyílt internetről érkező, ellenőrizetlen bemenetet dolgoz fel. Ha összeomlik, a Go szolgáltatás nem omlik össze vele együtt: a hívás hibával végződik, a munkamenetet eldobják, és a kliens a következő igénynél új munkafolyamatot indít.

## Reprodukálhatóan épített, SHA-256 szerint rögzített

Egy 25 MB-os bináris fájl, amely a Chromiumot tartalmazza, csak akkor megbízható, ha pontosan meg tudjuk mondani, mi került bele. A `chromenet` úgy követi a Chromium Stable kiadásokat, ahogy a `gosuda.org/sqlite3` a SQLite-ot: a forrást soha nem vendorizálja, csak rögzíti.

| Rögzítés                                                                                                                  | Hely                           |
| :------------------------------------------------------------------------------------------------------------------------ | :----------------------------- |
| A Chromium-kiadás és annak hivatalos `-lite` forrásarchívuma                                                              | `third_party/chromium/VERSION` |
| Az archívum és a kiadás által rögzített összes eszközlánc SHA-256 értéke: clang, Rust, GN, ninja, a Windows clang futtatókörnyezet, xwin | `third_party/chromium/SHA256`  |
| Az xwinen keresztül letöltött MSVC CRT és Windows SDK verziók                                                             | `third_party/chromium/WINSDK`  |
| A homokozó futtatókörnyezet (`rungv`) kiadása, a vendég image digest és a Debian snapshot dátuma                          | `scripts/engine/BUILDENV`      |
| A HQQ C futtatókörnyezet                                                                                                  | `go.mod` és `go.sum`           |

A jelenlegi rögzítés a Chromium `157.0.8103.38`. Amelyik letöltés nem egyezik a rögzítésével, az megállítja a buildet. A kiadás pontosan egy foltot alkalmaz a Chromiumra: Linuxon a `chrome_net_server` NSS nélkül épül, és a szerver-tanúsítványokat kizárólag a Chrome Root Store ellen ellenőrzi, így a bináris fájlhoz a libc-n kívül semmi más nem kell.

A Linux és Windows motorok [gvx](https://gosuda.org/blog/posts/gvx-cross-platform-linux-containers-z48916d01) homokozókban épülnek: privilégiumok nélküli folyamatokban, rögzített vendég image-dzsel és host-daemon nélkül. A Windows motorokat Linuxon keresztetordítják (cross-compile) a Chromium clang-cl és lld-link eszközeivel, a xwin által a Microsofttól letöltött Windows SDK ellen. A macOS motorok natívan épülnek macOS runneren, mert a Chromium macOS-build Xcode-ot igényel.

Ugyanabból a commitból végzett újraépítések külön CI-futtatások között bájtra azonos binárisokat adtak. A kiadási binárisok bájtra azonosak azokkal, amelyeket egy korábbi CI-futtatás épített ahhoz a commithoz, amely a motort a monorepóba bevezette, mind a hat platformon.

| Platform        | Bináris méret |
| :-------------- | ------------: |
| `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 |

A Linux motorok csak a `libc`, `libm`, `libdl`, `libpthread` és `libgcc_s` könyvtáraktól függenek, és glibc 2.31 vagy újabb verziót igényelnek.

### A Chromium és a kiadások követése

Egy ütemezett munkafolyamat hatóránként ellenőrzi a Chromium Stable kiadásait. Új kiadás esetén átírja a rögzítéseket, felépíti és teszteli mind a hat motort a `chromium/<version>` ágon, hitelesíti a binárisokat, majd a rögzítéseket egyetlen commitban, a beágyazott binárisokkal, azok digestjeivel és a licencszövegekkel együtt a `main` ágra commitolja. A monorepóban a fájlonkénti `OWNERS` bejegyzések pontosan ezekre a fájlokra adnak jogot a munkafolyamat botjának, így a frissítés emberi lépés nélkül kerül be, ugyanakkor az építési recept maga (a Windows SDK rögzítése és a folt) változtatásaihoz továbbra is tulajdonos jóváhagyása szükséges.

Minden kiadási bináris hordoz egy build-eredet attesztációt attól a munkafolyamattól, amely felépítette:

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

Az egyes binárisokban található összetevők licencszövegeit (Chromium, BoringSSL, QUICHE és a build-gráf többi része) a Chromium saját `tools/licenses/licenses.py` eszköze generálja, és a kiadással együtt `NOTICE_<os>_<arch>.txt` néven szállítjuk.

## Korlátok

- A `DialWebSocket` tiszta Go RFC 6455 kliens, és nem használja a Chromium vermet.
- A `DialWebTransport` folyamaton belüli megvalósítás. Nem éri el a szervert.
- Az alapértelmezett JA4- és HTTP/2-ujjlenyomatok a rögzített Chromium-kiadásé. A Chromium ezeket kiadásonként megváltoztatja, a `chromenet` pedig követi ezt.
- A macOS binárisok ad-hoc aláírtak, és nincsenek notarizálva.
- A munkafolyamat-folyamatok memóriát igényelnek. Minden motorbináris 24–28 MB a lemezen, a Chromium futtatókörnyezete pedig szálkészletet és hálózati szálat indít.
- A motormunkamenet addig foglalt, amíg a válasz törzse le nem záródik. Az a program, amely nem zárja le a válasz törzseit, kimeríti a készletet.

## Forrás

A tároló a [github.com/gosuda/chromenet](https://github.com/gosuda/chromenet) címen érhető el, a gosuda monorepó `//net/chromenet` könyvtárából tükrözve. Az építési recept a `scripts/engine` könyvtárban található, a motor összekötő kódja az `engine/` könyvtárban, az interfész pedig a `chrome_net.idl` fájlban.
