目标
由于众所周知的原因,golang.org 无法直接访问,golang 文档和安装包无法下载,golang.org/x/net 等官方包无法下载。
常见解决方案是无脑挂代理,解决一切问题,但为了以最小成本解决,我折腾出了这种方法,完全本机运行,无需外部代理和额外的服务器。是不是很爽?
思路
其实有官方镜像可以用:
- golang.org:https://golang.google.cn/
- 官方包:https://github.com/golang/
在本机自建 https 透明代理服务,通过 hosts 把 golang.org 解析到本机,代理服务再去请求镜像站。
这里就有另一个需要解决的问题,如 golang.org/x/net
包,经过透明代理后,实际访问的网址是 https://golang.google.cn/x/net
。虽然这个网址直接打开没问题,但并不能通过 go get
拉取到包。原因可以看网页源码,里面其实记录了一个跳转网址,告诉 go get
工具,应该到 https://go.googlesource.com/net
拉取源码。很不幸,go.googlesource.com
也无法访问,但可以用官方 github 镜像代替:https://github.com/golang/net
。
https 自签证书
这个教程已经遍地都是了,我这里就直接上代码了。由于我的电脑系统是 win10,这些命令其实是在 wsl 中执行的。
# 创建工作目录
mkdir ~/ssl
cd ~/ssl
# CA 证书
openssl genrsa -des3 -out ca.key 2048
openssl req -sha256 -new -x509 -days 365 -key ca.key -out ca.crt \
-subj "/C=CN/ST=HN/L=XC/O=wzv5/OU=wzv5/CN=wzv5Root"
# 这里会提示输入密码,记好密码,之后要用
# 要制作的证书名字及 DNS
export KEYNAME=golang
export DNSNAME="DNS:golang.org,DNS:go.googlesource.com"
# 创建 https 证书
openssl genrsa -des3 -out $KEYNAME.key 2048
# 这里会提示输入密码,随便输一个
openssl rsa -in $KEYNAME.key -out $KEYNAME.key
# 输入上一步的密码,这行命令其实是用来清除密码的
openssl req -new \
-sha256 \
-key $KEYNAME.key \
-out $KEYNAME.csr \
-subj "/C=CN/ST=HN/L=XC/O=wzv5/OU=wzv5/CN=$KEYNAME"
openssl x509 -req \
-days 365 -sha256 \
-CA ca.crt \
-CAkey ca.key \
-in $KEYNAME.csr \
-out $KEYNAME.crt \
-extensions SAN \
-extfile <(printf "[SAN]\nsubjectAltName=$DNSNAME")
# 这里会要求输入 CA 证书的密码
我们只需要 .crt 和 .key 文件,前者是公钥,后者是私钥。
CA 证书的密码要记好,之后如果需要其他域名的证书,可以重复使用 CA 证书。
caddy 透明代理
其实最初我是想用 nginx,配置文件都写一半了,突然意识到这算不算大炮打蚊子呢,这么简单一个需求,至于上 nginx 么,找个简单易用的工具凑合得了,于是就换成了 caddy。
caddy 是 go 语言写的 http 服务器,非常易用,也符合本文的 go 生态,用 go 解决 go 中遇到的问题,多么和谐。
从 https://github.com/mholt/caddy/releases/latest 下载 caddy,只需要压缩包内的可执行文件,其他文件无视。
仍然以 win10 的 wsl 作为运行环境来举例。把解压出来的 caddy 可执行文件放到 PATH 路径中,如 /usr/local/bin/caddy
。创建目录 /usr/local/etc/caddy/ssl
,把上面创建的 golang.crt
和 golang.key
文件放进来。创建文件 /usr/local/etc/caddy/Caddyfile
,写入以下内容:
https://golang.org {
tls /usr/local/etc/caddy/ssl/golang.crt /usr/local/etc/caddy/ssl/golang.key
proxy / https://golang.google.cn/
}
https://go.googlesource.com {
tls /usr/local/etc/caddy/ssl/golang.crt /usr/local/etc/caddy/ssl/golang.key
proxy / https://github.com/golang/
}
caddy 的配置文件格式是不是非常简洁?想想 nginx 要写多少。。
最后启动 caddy。
caddy -conf /usr/local/etc/caddy/Caddyfile
系统信任自签证书
由于不同的系统方法不一样,这里就拿我使用的 win10 系统举例。
双击 ca.crt
文件,系统会弹出证书信息界面,选择“安装证书”,安装到“当前用户”的“受信任的根证书颁发机构”。
对于 linux 系统,可以自己查阅 man update-ca-trust
,文档也很详细。
git 信任自签证书
网络上铺天盖地全是设置 http.sslVerify = false
,但是切记,不到万不得已千万不要这么干,证书链是网络安全的基础,禁用证书校验是非常危险的行为。并且作为程序员,你得为你的用户负责,确保自己的开发环境是安全的。
这里我选择为 git 设置自定义的 CA 证书列表,也就是 http.sslCAInfo
。
首先从 https://curl.haxx.se/ca/cacert.pem 下载默认证书,用文本编辑器打开 cacert.pem
,把上面我们自己创建的 ca.crt
文件的内容追加到末尾,保存退出,就得到了一个包含默认 CA 和我们自签 CA 的证书包文件。
修改 git 设置:
git config --global http.sslcainfo <改成你自己的路径>/cacert.pem
如果不想这么麻烦,还有一种方法,就是为指定的域名禁用证书校验。
直接编辑文件 $HOME/.gitconfig
,写入以下内容:
[http "https://go.googlesource.com"]
sslverify = false
也就是只对 go.googlesource.com
域名禁用证书验证。
修改 hosts
127.0.0.1 golang.org
127.0.0.1 go.googlesource.com
由于 DNS 缓存,或许你需要重启才能生效。
最终成果
go get -u -v golang.org/x/net
go get -u -v github.com/gin-gonic/gin
不出意外,上述命令能够在国内网络中正常运行,只不过速度可能有点慢,毕竟 github 在国内的访问并不稳定。
我在实际使用中,其实是把 caddy 开机启动了,这样电脑一启动就是直接可用的状态。同时,caddy 还兼顾修复 steam 社区的作用,具体方法就不说了,免得被封喽,原理都差不多,就是把不能访问的域名解析到本机,然后找到某种可以直接访问的方式,写到 caddy 配置文件中。