真實需求#
繞過備案檢測使自托管 Gitlab URL 不帶端口號
問題#
訪問通過 Nginx 反代後的帶端口的 URL 會被重定向到不帶端口的 URL
原因#
Nginx 按照 gitlab.rb 的配置將用戶重定向到了 external_url,也就是 gitlab.rb 中的設定,此設定改成帶端口的 URL 也會導致問題(過多的重定向導致現代瀏覽器報錯)。
解決方案#
使用 Argo Tunnel 接管內置 Nginx,直接與 Gitlab Workhorse 連接
原理#
通過分析 Gitlab-CE 源代碼可以找到內置 Nginx 的工作方式
https://gitlab.com/gitlab-org/gitlab-foss/-/blob/master/lib/support/nginx/gitlab-ssl
# 前面忽略
upstream gitlab-workhorse {
# GitLab socket file,
# for Omnibus this would be: unix:/var/opt/gitlab/gitlab-workhorse/sockets/socket
server unix:/home/git/gitlab/tmp/sockets/gitlab-workhorse.socket fail_timeout=0;
}
# 中間忽略
server {
#中間忽略
location / {
client_max_body_size 0;
gzip off;
## https://github.com/gitlabhq/gitlabhq/issues/694
## Some requests take more than 30 seconds.
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade_gitlab_ssl;
proxy_pass http://gitlab-workhorse;
}
}
#後面忽略
可以發現幾乎就是直接把流量交給 Gitlab Workhorse 處理,Nginx 只負責重定向,提供靜態資源,之間通過 Socket 連接。
Argo Tunnel 可以將本地的服務映射到公網,也可作為網關轉發流量。
因此使用 Argo Tunnel 代替 Nginx 可行。
步驟#
Step1. 註冊 Cloudflare 帳號,將域名轉移到 Cloudflare,然後打開 Zero Trust -> Access -> Tunnels
Step2. 在 Gitlab 主機上安裝 cloudflared 並按照 Cloudflare 的指示配置連接。
Step3. 修改 gitlab.rb
external_url 'https://git.targetdomain.com'
# 修改成最終呈現的 URL
gitlab_rails['trusted_proxies'] = ['0.0.0.0/0']
# 允許目標 IP 與 Gitlab Workhorse 建立連接
# Warning: 因為 Argo Tunnel 的遠程主機 IP 並不固定,我也沒測出來所有的 IP 段(太多了),因此這裡允許所有主機建立連接。
# 出於安全原因你需要配置本地防火牆禁止外部連接(關閉對應端口,即 Gitlab Workhorse 監聽的端口),Argo Tunnel 不會因此無法建立連接(在本地建立的自然不影響)
gitlab_workhorse['listen_network'] = "tcp"
gitlab_workhorse['listen_addr'] = "0.0.0.0:10080"
# 讓 Workhorse 在 10080 監聽
# 接應上文,你需要阻止一切外部主機連接 10080 端口
# 你也可以使用 Unix Socket
# gitlab_workhorse['listen_network'] = "unix"
# gitlab_workhorse['listen_addr'] = "...省略/socket"
# 使用 Socket 不需要配置防火牆
nginx['enable'] = false
# 禁用 Gitlab 自帶的 Nginx
Step4. 配置 Tunnel
在 Tunnel 管理界面 -> Public Hostname 新建一個主機名
Subdomain 與 Domain 按需填寫,需要與 gitlab.rb 中保持一致
在示例配置中 URL 是 https://git.targetdomain.com,因此需要設置 Subdomain 為 git,設置 Domain(需要接入 Cloudflare)為 targetdomain.com,Path 留空
Service Type 選擇 TCP,URL 填寫 localhost:10080,同理需要與 gitlab.rb 中保持一致,在示例配置中它是 10080 端口。
Notice: 如果你使用的是 Unix Socket,Service Type 需要選擇 UNIX,URL 需要填寫絕對路徑。
Step5. 現在訪問你的 Gitlab,它應該已經可以正常使用了,並且所有的 URL 與重定向都是正確的。