# gh-proxy **Repository Path**: neal11/gh-proxy ## Basic Information - **Project Name**: gh-proxy - **Description**: gh-proxy - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-19 - **Last Updated**: 2026-10-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # gh-proxy · GitHub 工作台 基于 hunshcn/gh-proxy 二开:在一个需要认证的站点内搜索公开 GitHub 仓库、浏览目录/README/代码,并通过代理下载或执行只读 clone/fetch/pull。不在服务器保存仓库副本,不提供 push。 ## 两种部署的实际能力 | 能力 | Python / Docker | Cloudflare Workers | | --- | --- | --- | | Token / 浏览器登录、公开仓库搜索与浏览 | 支持 | 支持 | | 文件/源码包代理、只读 Git Smart HTTP | 支持 | 支持 | | HTTP / HTTPS / SOCKS5 上游代理 | 支持,所有业务出口统一配置 | **当前不支持**;配置后明确503,绝不退回直连 | Worker 代理技术验证遇到 Workerd TLS/Undici 不兼容,详见 [验证记录](docs/worker-proxy-feasibility.md)。没有增加额外网关或自行实现协议栈。**需要上游代理时,请使用 Python/Docker 版。** ## Python 本地运行 需要 Python 3.12+。生产环境以 HTTPS 反代本程序;不要把本地 HTTP 例外当公网配置。 ```powershell python -m venv .venv .\.venv\Scripts\python.exe -m pip install -r requirements.lock.txt $env:PROXY_TOKEN = '替换为足够长的随机密钥' $env:ALLOW_INSECURE_LOCAL_DEV = '1' # 仅本机 HTTP 开发 .\.venv\Scripts\python.exe -m app.main ``` 打开 `http://127.0.0.1:8080/`。Linux/macOS 使用 `.venv/bin/python` 并通过环境变量设置相同配置。`.env.example` 仅作示例,程序不会自动读取 `.env`。 ### Docker 静态前端资源已经随源码提供,构建 Python 镜像不需要 Node。旧 Python 3.7/Nginx/uWSGI 镜像已替换为 Python 3.12 + Waitress,容器端口改为8080。 ```sh docker build -t gh-proxy-browser . docker run -d --name gh-proxy --restart unless-stopped \ -p 127.0.0.1:8080:8080 \ -e PROXY_TOKEN="$PROXY_TOKEN" \ -e GITHUB_TOKEN="$GITHUB_TOKEN" \ -e PROXY="$PROXY" \ gh-proxy-browser ``` 在 HTTPS 反向代理之后运行。若反代设置 `X-Forwarded-Proto` / `X-Forwarded-Host`,通过 `TRUSTED_PROXY` 指定反代实际来源IP,让 Waitress只信任该来源。不要在不可信网络上设置通配信任。反代若移除子路径前缀,需要与 `PREFIX` 配置协同,避免再次重复剥离。 容器的 `127.0.0.1` 指容器自身,不是宿主机代理。Docker Desktop 的宿主机代理可用 `host.docker.internal`;Linux请配置容器可达的代理地址/host-gateway。不要将代理凭据写进镜像或命令历史。 ## 配置 代理配置统一使用 `PROXY`,已有部署需更新环境变量并重新创建容器,不读取旧代理变量。`PROXY_TOKEN` 仍是访问本站的密钥,名称和用途不变。 | 配置 | 说明 | | --- | --- | | `PROXY_TOKEN` | 必填的入站访问密钥;缺失时受保护接口503,不匿名开放 | | `GITHUB_TOKEN` | 可选GitHub REST凭据;仅浏览模块使用,不发给Git/文件上游、不下发页面。建议配置以缓解GitHub API限流 | | `PROXY` | Python可选的统一代理URL,支持 `http://`、`https://`、`socks5://` 和 `socks5h://`,例如 `https://proxy.example.com:443` | | `PREFIX` | 默认 `/`;子路径例如 `/gh/`。两版UI/API/Cookie/clone命令均使用同一前缀 | | `ALLOW_INSECURE_LOCAL_DEV` | 仅本地HTTP开发设为 `1`;默认Cookie为Secure,公网必须HTTPS | | `HOST` / `PORT` | Python默认 `127.0.0.1:8080`;容器内默认 `0.0.0.0:8080` | | `TRUSTED_PROXY` | Python可选的HTTPS反代来源IP;只在确实有该反代时配置 | HTTP、HTTPS和SOCKS5均支持账号密码,例如 `https://username:password@proxy.example.com:443`;特殊字符使用标准百分号编码。配置含秘密,应通过部署平台安全注入,不在浏览器或日志显示;反代访问日志也应遮蔽 X-Proxy-Token、Cookie 与代理认证信息。 ### 出站规则 - 未设置 `PROXY` 时明确直连;设置后所有GitHub API、Git upload-pack、Release/archive/raw/gist/CDN及每跳重定向都经该代理。 - SOCKS5统一采用远端目标DNS:`socks5h://`;`socks5://` 输入也会按远端DNS归一。代理地址自身仍需引导解析,如不允许本地DNS应使用代理IP或系统级策略。 - 代理不可用、错误认证、TLS校验失败时明确报错,**不自动直连**。环境 `HTTP_PROXY/HTTPS_PROXY/ALL_PROXY/NO_PROXY` 不覆盖程序配置。 - HTTPS代理使用现有网络库的默认TLS行为;代理连接与目标站连接均保留校验,不增加证书管理页面。HTTP/SOCKS本身不保证客户端到代理的链路加密,应使用可信网络/可信代理。 - 不用站外302让浏览器或Git绕过出口控制;上游重定向由服务端完成。原pass/jsDelivr资源选择保留,但改为中继,增加本站带宽;大小限制命中返回413,不跳回原站。 - 以上控制本服务运行时业务请求,不替开发机Git、pip/npm、Docker构建或Cloudflare平台内部流量配置代理;用户主动点击“GitHub原站”属于离开本站。 Python原有 `white_list`、`black_list`、`pass_list`、`jsdelivr`、`size_limit` 设置仍在 `app/main.py`。Worker可通过 `WHITE_LIST` / `BLACK_LIST` / `PASS_LIST` 换行配置以及 `JSDELIVR=1` 使用对应规则。名单按仓库身份匹配,不区分大小写并识别Git的`.git`后缀;URL编码和点路径不能用来绕过规则。 ## Worker 部署 需要 Node.js 22+。不再是复制单个JS文件:现在需要Worker模块和同源静态Assets一起部署。 ```sh npm ci npx wrangler secret put PROXY_TOKEN # 可选:npx wrangler secret put GITHUB_TOKEN npm run deploy:worker ``` `wrangler.toml` 包含Assets和 `run_worker_first = true`,不能关闭后让静态路由绕过入口。Worker的 `PROXY` 目前会使需要出站的请求返回明确503;原生fetch的dispatcher参数不能保证走代理。 本地开发可通过忽略的 `.dev.vars` 配置合成密钥、`ALLOW_INSECURE_LOCAL_DEV=1`,再执行 `npm run dev:worker`。不要提交 `.dev.vars` 或真实Token。 ## 使用 浏览器输入访问Token登录,然后搜索关键词/常用仓库搜索条件,例如 `language:Python stars:>10000`,或直接输入 `owner/repo` / GitHub仓库根地址。 - 切换分支或标签,浏览目录、README、UTF-8文本代码;下载原文件或当前ref源码包。 - 搜索仅公开仓库;浏览接口也核验公开属性,不利用服务器GitHub Token暴露私有内容。 - README外部图片/徽章复用GitHub渲染结果中的Camo地址,再经本站的认证图片接口和统一出口加载;点击链接保持不变,浏览器不直连图片站。单图预览上限8MiB;GitHub未提供可用图片地址、图片失效或超限时退为替代文字,不显示技术占位文案。首次解析外部图片会额外消耗GitHub API额度。 - 不支持完整GitHub网页、Issues/PR、全仓代码搜索或在线编辑。空仓库、无README、二进制、超过1MiB的文件有明确提示;达到1000条的目录提示可能不完整,不假装展示全部。 - 浏览器会话为12小时签名Cookie;退出删除本机Cookie,但无法单独撤销已被复制的共享会话。更换 `PROXY_TOKEN` 并重启/部署会使全部旧会话失效。 ### Git clone / fetch / pull 下面将 `proxy.example.com` 换成实际域名,子路径部署也要包含子路径。配置只匹配本站,不影响直接访问GitHub/Gitee。 ```sh git config --global "http.https://proxy.example.com/.extraHeader" "X-Proxy-Token: 替换为访问Token" git config --global "http.https://proxy.example.com/.followRedirects" false git clone https://proxy.example.com/https://github.com/owner/repo.git ``` Token会明文保存在本机Git用户配置中,命令历史也可能保留它;建议使用合适的本机凭据保护。页面只提供占位配置,不会把浏览器Token插入可复制命令。查询和移除: ```sh git config --global --get-all "http.https://proxy.example.com/.extraHeader" git config --global --unset-all "http.https://proxy.example.com/.extraHeader" git config --global --unset-all "http.https://proxy.example.com/.followRedirects" ``` 服务端允许upload-pack的GET发现和POST,拒绝receive-pack的发现/执行及未知Git服务。**不只是UI没有push按钮。** GitHub私有仓库仍需GitHub自身凭据,代理认证不会替代它;原有HTTP Authorization转发只限适用上游,跨主机重定向移除它。新增搜索/浏览不支持私有仓库。未做LFS专项代理或子模块URL自动改写。 ### 脚本下载 ```sh curl --fail --header "X-Proxy-Token: $PROXY_TOKEN" \ https://proxy.example.com/https://github.com/owner/repo/archive/main.zip -o source.zip ``` 不要把本站Token放查询参数/路径里,也不要依赖自定义头会在客户端跨域重定向时自动剥离。服务端已处理允许的上游重定向。 ## 开发与构建 ```sh npm ci # 修改前端依赖后重建本地资源 npm run vendor # 格式化业务代码和构建脚本 npm run format # Worker构建,不实际部署 npx wrangler deploy --dry-run ``` 前端依赖固定版本、本地分发。测试目录及Playwright配置仅在本地保留,不随仓库分发;已有实施记录中的测试结果是历史验证记录。真实GitHub联网与生产部署验收需单独进行。 规划:[开发规划](docs/development-plan.md) · [任务计划](docs/task-plan.md) · [接口调研](docs/github-api-research.md) · [实施记录](docs/implementation-status.md) ## 来源与许可证 原项目:[hunshcn/gh-proxy](https://github.com/hunshcn/gh-proxy)。保留原作者的MIT许可证;第三方前端库许可证随 `app/static/vendor/` 分发。