开启代理之后,内部 API 挂了
目标
用会记录的模拟代理,亲自测量在客户内部代理配置下 curl、Python urllib、requests 各自走哪条路径,并制作让三个工具都走同一条路径的配置、集成连接器和判定工具。
为什么重要
代理环境变量不是标准而是惯例,所以每个工具的解释不同。因此在填入客户配置之后,会出现 curl 健康检查是绿灯、而只有 Python 采集器在内部 API 上收到 403 的情况。凭推测去修改配置,很容易救活一个工具却弄坏另一个。本实验培养的是用记录来确认“那个请求有没有到达代理”的习惯。
材料:/opt/lab/p1a-proxy/ —— corpnet.py(模拟代理、内部 API)、customer.env(客户配置)、cases.tsv(18 个用例)、connector.py(有问题的集成连接器)。没有互联网。127.0.0.2、127.0.0.3 也是这个 Pod 自己(回环),corp.example、saascorp.example 这样的名称无法解析——想直连的请求会在名称解析上失败,但没有出现在代理记录里,这件事本身就是“走了直连”的证据。
预计 60 分钟。会话结束后 /root/proxy 会消失,所以需要的文件要另外保存。
步骤
- 用
python3 /opt/lab/p1a-proxy/corpnet.py up启动模拟的内部网络,在应用 customer.env 的状态下,分别用 curl、urllib、requests 请求一次http://127.0.0.2:8080/health。查看响应正文中的 served_by 和 id,在 /root/proxy/repro.tsv 中写下도구<TAB>PROXY|DIRECT<TAB>id(占位符为工具名称)三行。 - 用三个工具运行 cases.tsv 中第 2 步的用例(c01..c05,大小写和按协议区分的变量),按
case<TAB>curl<TAB>urllib<TAB>requests的格式写入 /root/proxy/matrix.tsv。 - 测量第 3 步的用例(c06..c10,后缀、前导点、带星号的域名),追加到 matrix.tsv。
- 测量第 4 步的用例(c11..c14,IP、CIDR、端口),追加到 matrix.tsv。
- 测量第 5 步的用例(c15..c18,单个星号以及小写、大写的优先级),追加到 matrix.tsv。
- 制作 /root/proxy/fixed.env,让三个工具访问内部四处(127.0.0.2:8080、127.0.0.3:8080、localhost:8081、api.corp.example:8080)时直连,访问外部三处(http、https 的 saascorp.example,updates.vendor.example)时走代理
http://127.0.0.1:3128。 - 把 connector.py 复制为 /root/proxy/connector.py 并修复。要继续使用 CONNECTOR_PROXY,但命中 NO_PROXY 的 URL 要直连,并且不能使用环境中的 HTTP_PROXY、HTTPS_PROXY。
- 制作 /root/proxy/route_probe.py。
python3 route_probe.py <env파일> URL...(占位符为 env 文件)要把配置文件中的代理地址换成本地哨兵,实际运行三个工具,为每个 URL 输出url<TAB>curl<TAB>urllib<TAB>requests,判定不一致时以退出码 3 结束,全部一致则为 0。
参考
- 只给一次环境来运行:
env -i PATH=$PATH http_proxy=http://127.0.0.1:3128 curl -s http://127.0.0.2:8080/health——用env -i清除 shell 中残留的变量。 - 查看记录:
tail -n 3 /root/proxy/logs/proxy.jsonl、tail -n 3 /root/proxy/logs/api.jsonl - urllib 会把 403 作为异常(HTTPError)抛出。正文用异常对象的
read()来读取。 - https 用例以 CONNECT 方式到达代理。没有正文,所以按记录的行数来判定。
- 评分器不会使用你启动的 corpnet。它会在自己的端口上启动同样的模拟环境,在相同条件下重新测量。
- 常见错误:在 shell 中 export 的代理变量混进了下一个用例;相信
*.corp.example会像通配符那样工作。
用客户配置重现故障并留下证据
启动 corpnet,用 customer.env 分别用三个工具发送一次请求,然后把工具、路径、id 写入 /root/proxy/repro.tsv。
响应正文中的 served_by 是 corp-proxy,就说明走了代理。id 必须与 logs 中的记录行对得上,并且通过记录中的 User-Agent 交叉确认是哪个工具发的。customer.env 要用 set -a 只在子 shell 中 export。
测量大写 HTTP_PROXY 和 ALL_PROXY
用三个工具运行 cases.tsv 的 c01..c05,以 PROXY/DIRECT 写入 /root/proxy/matrix.tsv。
每个用例都用 env -i 构造干净的环境,并查看请求前后 proxy.jsonl 的行数是否增加。请在 curl 手册的 ENVIRONMENT 一节中,找出只针对 http_proxy 的那个例外。
后缀、前导点、带星号的域名
测量 c06..c10,追加到 /root/proxy/matrix.tsv(不要删掉前面用例的行)。
想直连的请求会在名称解析上失败。要看的不是是否失败,而是是否到达了代理记录。saascorp.example 是以 corp.example 结尾的另一家公司的名称。
写了 CIDR 和端口的 NO_PROXY
测量 c11..c14,追加到 /root/proxy/matrix.tsv。
CIDR 支持在 curl 手册的 --noproxy 说明中,连同版本一起给出。urllib 文档写道 no_proxy 条目可以带端口。文档没有说明的工具,要测了才知道。
单个星号与小写优先
测量 c15..c18,追加到 /root/proxy/matrix.tsv。
请比较星号是列表中的一个条目时,与是整个列表时的区别。值为空字符串的小写变量,是被读作“未设置”还是“空列表”,各个工具也不一样。
以三个工具的公共子集重写配置
制作 /root/proxy/fixed.env,让内部四处直连,外部三处走 http://127.0.0.1:3128 指定的代理。
请只挑选在前面填好的表中、三个工具给出相同答案的写法。需要决定四件事:大小写、域名前面的点、用什么代替 CIDR、是否带端口。
修复使用 proxies 参数的集成连接器
把 /opt/lab/p1a-proxy/connector.py 复制为 /root/proxy/connector.py,并修改为遵守 NO_PROXY。
requests.utils 中有一个函数,可以根据 URL 和 no_proxy 字符串告知是否绕过代理。会话的 trust_env 决定是否使用环境变量中的代理。如果把内部 IP 写死在代码里,用其他 NO_PROXY 评分时就会不合格。
无论什么配置都能测量各工具路径的探针
制作 /root/proxy/route_probe.py。接收 env 文件和若干 URL,通过实际运行判定三个工具的路径并以 TSV 输出,不一致时以 3 结束,一致时以 0 结束。
客户的代理地址在这个 Pod 里是连不通的。判断规则(no_proxy)保持不变,只把代理值换成本地哨兵地址,就能根据哨兵是否收到连接来判定。评分器会用随机的域名和代理地址来测试。