github 直连不稳定,clone 大仓库动不动断流,release 下载经常超时。用一台海外服务器反代 github,网页、clone、raw、release 一把梭,一劳永逸。
caddy 的安装与守护进程写法在上一篇已经详细介绍过,这里不再赘述,跳转链接。
快速搭建
配置caddyfile
根据笔者踩坑经验。netcraft等公司有专门扫描仿冒站点的业务,会批量抓取网页,反代域名的登录等页面会被视为欺诈。申请回复的流程极为繁琐,所以这里加了些取巧的配置方法供读者放心的复制粘贴。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
| # 换成你自己的域名
DOMAIN="example.com"
cat << EOF > /etc/caddy/Caddyfile
{
email you@example.com
}
gh.\${DOMAIN} {
reverse_proxy https://github.com {
header_up Host github.com
header_up origin https://github.com
header_down Location "https://github.com" "https://gh.\${DOMAIN}"
}
}
gh.\${DOMAIN} {
handle /robots.txt {
respond "User-agent: *\nDisallow: /" 200
}
# 白名单:只放行 git 协议与下载路径,网页一律 307 回原站
# 用 path_regexp,语义明确,不依赖 glob 通配符是否跨斜杠
@allow {
# 合并为单条正则(每个命名 matcher 中 path_regexp 只能出现一次)
# 覆盖:.git 协议形态(含 LFS/objects)、不带 .git 的首发请求、下载类路径
path_regexp ^/[^/]+/[^/]+(\\.git(/.*)?$|/(info/refs|git-upload-pack|git-receive-pack|HEAD)$|/archive/.*$|/releases/download/.*$|/raw/.*$|/(commit|commits|pull|pulls)/[^/]+\\.patch$)
}
@rest {
not {
path_regexp ^/[^/]+/[^/]+(\\.git(/.*)?$|/(info/refs|git-upload-pack|git-receive-pack|HEAD)$|/archive/.*$|/releases/download/.*$|/raw/.*$|/(commit|commits|pull|pulls)/[^/]+\\.patch$)
}
}
redir @rest https://github.com{uri} 307
reverse_proxy https://github.com {
header_up Host {upstream_hostport}
header_up X-Forwarded-Host {host}
header_up origin https://github.com
# 下载链 302 闭环:全部改写到自己镜像域名
header_down Location "https://raw.githubusercontent.com" "https://raw.gh.\${DOMAIN}"
header_down Location "https://codeload.github.com" "https://codeload.gh.\${DOMAIN}"
header_down Location "https://objects.githubusercontent.com" "https://objects.gh.\${DOMAIN}"
}
}
raw.gh.\${DOMAIN} {
handle /robots.txt {
respond "User-agent: *\nDisallow: /" 200
}
reverse_proxy https://raw.githubusercontent.com {
header_up Host raw.githubusercontent.com
}
}
objects.gh.\${DOMAIN} {
handle /robots.txt {
respond "User-agent: *\nDisallow: /" 200
}
reverse_proxy https://objects.githubusercontent.com {
header_up Host objects.githubusercontent.com
header_down Location "https://objects.githubusercontent.com" "https://objects.gh.\${DOMAIN}"
}
}
codeload.gh.\${DOMAIN} {
handle /robots.txt {
respond "User-agent: *\nDisallow: /" 200
}
reverse_proxy https://codeload.github.com {
header_up Host codeload.github.com
}
}
api.gh.\${DOMAIN} {
handle /robots.txt {
respond "User-agent: *\nDisallow: /" 200
}
reverse_proxy https://api.github.com {
header_up Host api.github.com
}
}
gist.gh.\${DOMAIN} {
handle /robots.txt {
respond "User-agent: *\nDisallow: /" 200
}
# gist 的 clone 有两种深度:/id.git 与 /user/id.git,其余网页 307 回原站
@allow {
# 单条正则:/id.git 与 /user/id.git 两种深度 + 不带 .git 的协议首发请求
path_regexp ^/(([^/]+/)?[^/]+\\.git(/.*)?$|([^/]+/)?[^/]+/(info/refs|git-upload-pack|git-receive-pack|HEAD)$)
}
@rest {
not {
path_regexp ^/(([^/]+/)?[^/]+\\.git(/.*)?$|([^/]+/)?[^/]+/(info/refs|git-upload-pack|git-receive-pack|HEAD)$)
}
}
redir @rest https://gist.github.com{uri} 307
reverse_proxy https://gist.github.com {
header_up Host gist.github.com
}
}
avatars.gh.\${DOMAIN} {
handle /robots.txt {
respond "User-agent: *\nDisallow: /" 200
}
reverse_proxy https://avatars.githubusercontent.com {
header_up Host avatars.githubusercontent.com
}
}
EOF
|
注意事项:
email 换成自己的邮箱- 证书不用管,Caddy 自动申请续期,配置里不用写任何
tls header_down 两个参数是删除、三个参数才是替换,且查找串要写上游实际域名(https://github.com 这种),写成"期望结果"不会生效- release 下载会 302 跳到
objects.githubusercontent.com,所以必须反代它并重写 Location,否则下载还是走原站 - 页面里的 css/js 在
github.githubassets.com、头像在 avatars.githubusercontent.com,这些静态资源仍然直连;如果它们也慢,把对应域名也加进反代 - 登录受 cookie 域名限制,反代域名登录不上就直连原站登录,浏览不受影响
- 配置里出现的域名必须都能解析,否则 Caddy 会一直重试签证书
配置dns
嫌麻烦就加一条泛解析 *.gh.example.com,前提是dns服务商支持泛解析。目前已知cloudflare支持
7 条 A 记录指向服务器公网 IP:
1
2
3
4
5
6
7
| gh.example.com
raw.gh.example.com
objects.gh.example.com
codeload.gh.example.com
api.gh.example.com
gist.gh.example.com
avatars.gh.example.com
|
验证部署
1
2
3
| sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -sI https://gh.example.com/
|
返回 200 OK 说明反代正常。再试一次 clone:
1
| git clone https://gh.example.com/octocat/Hello-World.git
|
release 下载验证(换成真实的 release 链接):
1
| curl -sIL https://gh.example.com/user/repo/releases/download/v1.0/file.zip
|
响应里的 Location 应该是 https://objects.gh.example.com/...,说明重写生效。
快速使用
git
1
| git config --global url."https://gh.example.com/".insteadOf "https://github.com/"
|
一劳永逸,记得换掉 example.com。之后 clone、pull 自动走反代,remote 地址不用改:
1
| git clone https://github.com/user/repo.git # 实际请求自动改写为 https://gh.example.com/user/repo.git
|
查看改写规则是否生效:
1
| git config --get-regexp '^url\.'
|
网页
直接访问 https://gh.example.com/,浏览仓库、代码、issue 都没问题。需要登录的操作(发 issue、提 PR)建议直连原站。
raw与release
1
2
| curl -sSL https://raw.gh.example.com/user/repo/main/install.sh
wget https://gh.example.com/user/repo/releases/download/v1.0/app.tar.gz
|
脚本安装场景很实用,把 curl ... | bash 里的地址换成反代域名即可。
稍作补充
用户目录下的 .gitconfig 通过 insteadOf 将 git@github.com: 开头的地址换为反代地址(见下方示例),防止 VSCode 将你识别为企业版 github 用户。
示例:
1
2
| [url "https://example.com/"]
insteadOf = git@github.com:
|
补充之外的进阶玩法
在.gitconfig中添加。
并在github配置token并赋予仓库相关的权限
1
2
| [credential "https://gh.example.com"]
provider = generic
|