TT Lab
开始
学习 学习路径 课程

隔离网络镜像与私有 CA

Go 模块:用文件代理和 vendor 做隔离网络构建

在 TT Lab 中继续学习

目标

在联网的一侧用新的模块缓存下载 Go 模块,并搬到文件代理中,然后在隔离网络一侧用 GOPROXY=file:// 和 vendor 两条路构建。亲自确认把 go.sum 用作导入清单的方法,以及一行 GOFLAGS 会让 vendor 被忽略的陷阱。

为什么重要

Go 默认从 proxy.golang.org 下载,并向 sum.golang.org 询问哈希。在隔离网络中这两者都连不上。模块缓存的 cache/download 本身就是代理协议的形态,只要搬过去就成了代理,而且 go.sum 完整的话,就不必再去询问校验和数据库。这个 Pod 能访问互联网(80/443),所以承担下载端的角色,而隔离网络一侧的确认,由评分器把发往外部的 HTTP(S) 转到关闭的代理上,在封闭的状态下进行。

步骤

  1. 在 /root/goair/app 中创建模块 example.com/airgap-hello,并编写输出 rsc.io/quote v1.5.2 的 quote.Hello() 的 main.go。用新的模块缓存 GOMODCACHE=/root/goair/outside-cache 下载,并一直执行到 go mod tidy。
  2. 把 /root/goair/outside-cache/cache/download 的内容搬到 /srv/goproxy。
  3. 在隔离网络一侧的配置 /root/goair/inside.env 中写入 GOPROXY=file:///srv/goproxy 和 GOFLAGS=-mod=readonly。
  4. 读取该配置,在外部被封闭的状态下,用新的模块缓存 /root/goair/inside-cache 构建,生成 /root/goair/bin/hello-proxy。
  5. 在 /root/goair/app 中生成 vendor 目录。
  6. 保持镜像中的 GOFLAGS=-mod=mod 不变,用 GOPROXY=off 和空的模块缓存试着构建。把失败消息保存到 /root/goair/gomod-trap.txt。
  7. 在 GOPROXY=off 下,仅用 vendor 构建,生成 /root/goair/bin/hello-vendor。
  8. 编写导入记录 /root/goair/intake.txt,把 go.sum 中模块 zip 的哈希行(不带 /go.mod 的行)写成 모듈 버전 해시(占位符依次为模块、版本和哈希)的形式。每个哈希都必须与 /srv/goproxy 中的 .ziphash 相同。

参考

下载端:用新的模块缓存下载依赖

在 /root/goair/app 中创建模块 example.com/airgap-hello 和 main.go,用 GOMODCACHE=/root/goair/outside-cache 下载 rsc.io/quote v1.5.2,并一直执行到 go mod tidy。

用 go mod init 创建模块,用 go get 准确下载版本。把新的缓存目录作为 GOMODCACHE,这次下载的内容就只会堆放在其中。tidy 会把被使用的依赖整理为直接依赖。

把模块缓存搬成文件代理

把 /root/goair/outside-cache/cache/download 的内容搬到 /srv/goproxy。

模块缓存的 cache/download 之下已经是代理协议的形态(@v/list、.info、.mod、.zip)。请保持目录结构原样复制。缓存中存放已解压源码的其他目录不需要。

隔离网络一侧的 Go 环境文件

在 /root/goair/inside.env 中写入 GOPROXY=file:///srv/goproxy 和 GOFLAGS=-mod=readonly。

这是 shell 可以直接读取的“名称=值”的行。file 协议后面是绝对路径,所以会有三个斜杠。-mod=readonly 可以防止构建偷偷修改 go.mod。

封闭外部,用文件代理构建

读取 inside.env,在外部被封闭的状态下,用新的模块缓存 /root/goair/inside-cache 构建,生成 /root/goair/bin/hello-proxy。

把环境文件以 export 的方式读取后,把 GOMODCACHE 设为新的目录,并把外部地址转到关闭的代理上。如果用已经下载好的缓存构建,就不算测试了代理。

第二条路:vendor

在 /root/goair/app 中生成 vendor 目录。

go mod 的子命令中,有一个是把依赖源码复制到仓库内。请看结果中是否生成了 vendor/modules.txt。

明明有 vendor 却失败的构建

保持镜像中的 GOFLAGS=-mod=mod 不变,用 GOPROXY=off 和空的模块缓存试着构建,并把失败消息保存到 /root/goair/gomod-trap.txt。

这一步是记录失败的步骤。请先用 go env GOFLAGS 查看当前的值。回想阅读材料中 -mod=mod 如何处理 vendor,就能理解这条消息。

在 GOPROXY=off 下用 vendor 构建

在 GOPROXY=off 下,仅用 vendor 构建,生成 /root/goair/bin/hello-vendor。

有一个 -mod 的值可以让它使用 vendor。请覆盖环境中的 GOFLAGS,或者直接在命令行中给出。即使模块缓存是空的,也必须能成功。

用 go.sum 编写导入记录

编写 /root/goair/intake.txt,把 go.sum 中模块 zip 的哈希行写成 모듈 버전 해시(占位符依次为模块、版本和哈希)的形式。每个哈希都必须与 /srv/goproxy 中的 .ziphash 相同。

go.sum 的行有模块、版本、h1: 哈希三栏。版本之后带有 /go.mod 的行是 go.mod 文件的哈希,与 zip 不同。请与代理目录中的 .ziphash 文件逐行核对。