在很多公司中,IT 部门会限制内部网络向互联网的访问(各种理由,比如安全)。但是外网访问又是不可或缺的,所以通常它们会提供一个代理服务器,当你需要访问外网时,你需要配置你的程序来使用这个代理服务器。在 Windows 10 的图形界面上设置代理是非常简单的操作,但它应用范围有限(只适用于使用 WinHTTP 库的程序与部分会读取系统代理设置的程序)。许多我们在开发中使用到的命令行程序并不会读取系统代理设置。那么,有没有什么方法为这些命令行程序设置代理呢?

方法一:环境变量

这里我们常用到三个环境变量: HTTP_PROXYHTTPS_PROXYNO_PROXY
有非常多的命令行程序会读取这些环境变量作为其代理服务器配置(例如 curl 与 wget)。

HTTP_PROXY

HTTP_PROXY 指定程序以 HTTP 协议发出请求时,所需要使用的代理服务器。
取值的格式为 协议://主机:端口/ ,如果需要认证的话则可能是 协议://用户名:密码@主机:端口/ 。也就是标准的 URL。一般我们会这么设置:

  1. # 设置 HTTP 代理
  2. export HTTP_PROXY=http://127.0.0.1:23333/
  3. # 设置 SOCKS 代理
  4. export HTTP_PROXY=socks://127.0.0.1:23334/
  5. # 取消代理
  6. unset HTTP_PROXY

这里的协议是代理服务器的协议,和程序本身请求所使用的协议无关。当然,每个程序所能支持的代理服务器协议也是不同的,通常都会支持 HTTP 代理协议,支持 socks4、socks5 协议的次之。

HTTPS_PROXY

HTTPS_PROXY 指定程序以 HTTPS 协议发出请求时,所需要使用的代理服务器。其取值和 HTTP_PROXY 是一样的。
值得注意的是,如果你的代理服务器是 HTTP 代理协议(所谓“HTTP 代理”),那么 HTTPS_PROXY 的取值里还是以 http:// 开头,而不是 https:// 开头。

  1. # 设置 HTTP 代理
  2. export HTTPS_PROXY=http://127.0.0.1:23333/
  3. # 设置 SOCKS 代理
  4. export HTTPS_PROXY=socks://127.0.0.1:23334/

NO_PROXY

当我们设置了 HTTP(S)_PROXY 后,程序对于所有 HTTP(S) 请求都会使用环境变量所使用的代理服务器。这有时候会带来不便,例如当你想要访问公司内网资源时,你就不需要也不应该使用代理服务器。这时 NO_PROXY 环境变量就派上用场了。你可以在这个环境变量里指定你不想走代理的地址:

  1. # 本地地址不走代理
  2. export NO_PROXY="localhost,127.0.0.1"
  3. # 中大域名不走代理
  4. export NO_PROXY="sysu.edu.cn"

wget 的帮助文档里对于 NO_PROXY 是这么解释的:

This variable should contain a comma-separated list of domain extensions proxy should not be used for. For instance, if the value of no_proxy is ‘.mit.edu’, proxy will not be used to retrieve documents from MIT.

理论上说,它的值里只能放域名后缀。但我要是想整个局域网网段都不走代理的话,怎么办呢?有些软件(还不少)就支持在 NO_PROXY 里使用 CIDR 记号,例如:

  1. # 本地回环地址、局域网地址不走代理
  2. export NO_PROXY="127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8"

使用 net.http 的 Go 程序所能支持的 NO_PROXY 取值见 golang/go#16704。这个规则也是很多程序都支持的规则。

方法二:proxychains

Linux & macOS only

那如果我们的程序发送的请求不是以 HTTP(S) 协议发送的,又或者我们的程序压根就不支持代理服务器,那我们又要怎么让它们“走代理”呢?
这是我们就可以祭出大杀器 proxychains 了。proxychains 的功能就是让程序发出的 TCP 连接强制走代理(原理是 hack 程序所使用的相关网络函数,所以可能还是有极少一部分程序是用不了的),这样不管程序本身支不支持代理,都可以使用我们指定的代理服务器来发出请求。

安装

以 Ubuntu 20.04 为例,直接

  1. sudo apt install proxychains4

配置

编辑 /etc/proxychains4.conf 文件,找到最下方的 [ProxyList] ,把默认的 socks4 127.0.0.1 9050 改成你想要的代理,例如 http 127.0.0.1 23333 。然后保存。
image.png

使用

在原本的命令前加一个 proxychains 即可,例如 proxychains curl http://sysu.edu.cn
image.png

方法三:透明代理

Linux only

这种方法配置起来就相对复杂了。
如果说 proxychains 只是通过 hack 网络函数来实现代理,那么透明代理则是使用 Linux 内核能力,对所有 TCP/UDP 请求一网打尽。限于篇幅原因,这里不赘述透明代理的配置方法,有兴趣的朋友可以自行搜索。
附 Linux 内核相关文档:https://www.kernel.org/doc/Documentation/networking/tproxy.txt