网络代理学习笔记
下面的内容完全是 AI 大模型生成的,与本人毫无关系,本人不对内容负任何责任。
代理的基本概念
代理的核心作用是:将应用发起的网络请求交给中间服务器,由该服务器代替本机访问目标地址。
理解代理需要从三个问题入手:
- 流量如何进入代理(接管方式)
- 应用如何决定是否使用代理
- 代理使用什么协议进行转发
系统如何支持代理
操作系统本身并不会自动代理所有流量,而是提供若干机制,使应用可以选择使用代理。
环境变量
常见形式:
1 | http_proxy=... |
各个变量的含义如下表
| 变量 | 含义 |
|---|---|
| http_proxy | HTTP 请求所使用的代理 |
| https_proxy | HTTPS 请求所使用的代理 |
| all_proxy | 通用使用的代理(兜底) |
| no_proxy | 指定不走代理,直接连接的地址(通常是本地地址) |
Linux 设置相关环境变量
1 | export http_proxy=http://127.0.0.1:7890 |
撤销相关环境变量
1 | unset http_proxy https_proxy all_proxy no_proxy |
Windows 设置相关环境变量
1 | $env:http_proxy="http://127.0.0.1:7890" |
撤销相关环境变量
1 | $env:http_proxy="" |
特点:
- 应用主动读取这些变量
- 应用决定是否使用代理
- 不属于系统强制行为
注:
- 这里的
http_proxy等指的是 http 请求希望走的代理 URL,并没有要求代理类型,实际上代理类型可以是 http 代理,也可以是 socks5 代理。 - 不同应用支持的变量也不一样(例如 curl 通常支持
all_proxy;wget 更常用http_proxy和https_proxy,对all_proxy的支持并不统一。),有的系统和应用会区分环境变量大小写,虽然大部分使用小写版本的,但是最好都提供 - Windows 通常不区分环境变量的大小写
系统代理(System Proxy)
有的操作系统提供了统一代理配置接口,可以在系统设置中找到,例如:
- Windows 系统代理(控制面板 → 代理设置)
- macOS 网络代理
特点:
- 提供全局代理配置
- 应用可以选择是否使用
- 对图形界面程序友好
- 很多命令行工具都不会系统代理(例如
curl,wget,git等),它们更倾向于通过环境变量设置代理。 - 系统代理通常主要服务于 HTTP/HTTPS 流量;部分系统或应用也支持 SOCKS 代理,但是否生效取决于应用是否读取系统代理配置。
注意:Linux 并没有准备统一的系统代理,而且即使桌面环境准备了系统代理,绝大部分 CLI 工具也通常不会使用。
透明代理(网络层接管)
通过网络层机制拦截流量,例如:
- 路由表修改
- 防火墙规则(如 NAT / 重定向)
- 虚拟网卡(TUN)
特点:
- 应用无感知
- 可接管绝大部分经过系统网络栈的流量
- 不依赖应用支持
- 配置复杂,调试困难
代理协议
代理不仅是“一个端口”,还涉及通信协议,常见代理协议包括 HTTP 代理和 SOCKS5 代理。
HTTP 代理
形式:
1 | http://host:port |
原理:
- 工作在应用层
- 理解 HTTP 请求结构,支持 HTTP 请求,以及通过 CONNECT 方法为 HTTPS 建立隧道
特点
- 广泛支持,配置简单
- 主要用于 HTTP/HTTPS 请求
注意:通常写 http:// 而不是 https://,写成 http:// 并不影响代理访问的安全性,而且大多数代理软件不支持写成 https:// 的形式。
SOCKS5 代理
形式:
1 | socks5://host:port |
原理:
- 工作在传输层
- 不解析协议内容
- 转发任意 TCP 连接,并在协议层支持 UDP 转发(需客户端配合)
- 支持 SSH(HTTP 代理也可以通过 CONNECT 支持 SSH,但通常需要额外配置 ProxyCommand)
特点:
- 支持任意协议
- 更通用
- 可避免本地 DNS 解析问题
- 需要客户端支持
注意:socks5:// 和 socks5h:// 的区别在于哪一方负责解析域名:socks5:// 是本地解析,socks5h:// 是代理端解析。
代理端口
代理服务通常通过不同的端口提供不同协议入口。
典型划分如下:
1 | 端口 A → HTTP 代理 |
例如
1 | # HTTP 代理端口 |
HTTP 和 SOCKS 代理对应的 URL 分别为
1 | http://127.0.0.1:7890 |
这里不能把端口和协议错位使用。
某些代理服务会选择使用混合端口(Mixed Port):
1 | 单一端口 → 同时支持 HTTP 和 SOCKS |
例如
1 | # HTTP 和 SOCKS5 混合代理端口 |
特点:
- 自动识别协议
- 使用简单
关于混合端口的补充:
- 对于客户端来说,使用代理的方式由 URL 前缀直接确定;
- 对于代理端来说,它只是在监听一个端口,需要根据实际内容进一步判断应该使用 http 还是 socks5 代理。
- 混合端口的自动识别依赖实现细节,在一般场景下简单方便,但是在复杂场景下可能不如端口分离的方案稳定可靠。
小结
代理可以抽象为三层:
1 | [应用层] |
命令行工具使用代理
下面假设本地代理监听的端口为
1 | # HTTP 代理端口 |
如果使用 mixed-port,那么 HTTP 代理端口和 SOCKS5 代理端口一致。
curl
curl 支持多种代理协议,可以通过命令行参数或环境变量进行设置。
命令行参数指定 HTTP 代理或 SOCKS5 代理
1 | curl -x http://127.0.0.1:7890 https://example.com |
通过环境变量设置代理例如
1 | http_proxy=http://127.0.0.1:7890 \ |
wget
wget 主要支持 HTTP / HTTPS 代理。
命令行参数指定 HTTP 代理
1 | wget -e http_proxy=http://127.0.0.1:7890 https://example.com |
通过环境变量设置代理例如
1 | http_proxy=http://127.0.0.1:7890 \ |
ProxyChains
proxychains-ng 是一个代理辅助工具,用于强制让一些不支持代理的程序走代理。
原理是通过 hook 系统调用(如 connect),拦截网络连接并重定向到代理
安装后修改配置文件:
1 | /etc/proxychains4.conf |
或用户级配置文件
1 | ~/.proxychains/proxychains.conf |
配置文件中需要修改内容例如:指定 SOCKS5 代理
1 | [ProxyList] |
使用例如
1 | proxychains4 curl https://example.com |
加上 -q 开启静默模式,避免对 stdout 造成干扰。
1 | proxychains4 -q curl https://example.com |
注意:
- 不要和环境变量
http_proxy等混用,可能导致代理叠加或行为不确定 - 不适用于所有程序,因为采用 hook 机制,对部分程序(静态链接 / 特殊网络实现)可能无法生效
关于 Github 的访问 & git 使用代理
现在关注在 git 命令中如何使用代理,实际需求就是如何稳定访问 Github 的问题。由于 git 远程仓库的链接包括 http(s) 和 ssh 两类,因此也需要考虑对应情景下如何使用代理。
在大部分情况下直连 Github 是可以的,但是偶尔会出现连接超时,无法推送和拉取 Github 仓库,有很多种解决办法,原理各不相同,而且都无法保证奏效。
解决方案可以分为两类:
- 第一类方案不需要本地代理;
- 第二类方案则依赖本地代理。
不依赖本地代理
SSH 跳板机 / ProxyCommand 转发
可以基于 SSH 跳板机 / ProxyCommand 转发功能,用一个网络状态更好的,可以访问 Github 的服务器作为中转站,配置例如
1 | Host B |
这段配置有很多等价或有细微差异的现代写法,但是这里没有采用。
可以用下面的方式进行临时使用
1 | GIT_SSH_COMMAND='ssh -o ProxyCommand="ssh -q -W %h:%p B"' git clone git@github.com:OWNER/REPO.git |
ssh.github.com
Github 官方支持使用 ssh.github.com 代替 github.com,这会把 ssh 连接端口从 22 改到 443,在某些情况下会好很多(参考官方文档)。
可以修改 git 远程仓库的 URL,但是更建议在 .ssh/config 中直接覆盖修改
1 | Host github.com |
可以用下面的方式进行临时使用
1 | GIT_SSH_COMMAND='ssh -o HostName=ssh.github.com -p 443' git clone git@github.com:OWNER/REPO.git |
可以将代理转发和 ssh.github.com 结合,得到如下的配置方案
1 | Host B |
依赖本地代理
假设本地代理监听的端口为
1 | # HTTP 代理端口 |
如果使用 mixed-port,那么 HTTP 代理端口和 SOCKS5 代理端口一致。
下面不按照代理协议进行区分,而是按照使用 http(s) 链接或 ssh 链接的远程仓库,分别进行代理配置。
http(s) 链接
对于使用 http(s) 链接的远程仓库,Git 提供了 http.proxy 配置项,用于 http(s) 请求的代理配置。
添加 http 代理(默认仓库级配置,加上 --global 则全局生效)
1 | git config http.proxy http://127.0.0.1:7890 |
还可以添加 socks5 代理
1 | git config http.proxy socks5h://127.0.0.1:7891 |
这看起来有点奇怪,http.proxy 为什么可以指定 socks5 代理?因为 http.proxy 的语义是用于 HTTP 请求的代理配置,并不是 HTTP 类型的代理。
可以用下面的方式进行临时使用
1 | git -c http.proxy=http://127.0.0.1:7890 \ |
或者通过环境变量进行设置
1 | http_proxy=http://127.0.0.1:7890 \ |
可以用下面的命令撤销(加上 --global 撤销全局配置)
1 | git config --unset http.proxy |
ssh 链接
对于使用 ssh 链接的远程仓库,代理配置需要针对 ssh 自身进行。
使用 http 代理例如
1 | # windows |
使用 socks5 代理例如
1 | # windows |
对应的一次性命令例如
1 | GIT_SSH_COMMAND='ssh -o ProxyCommand="nc -X 5 -x 127.0.0.1:7891 %h %p"' \ |
