ansible 全局代理模式下载依赖 PySocks 库

46 阅读2分钟

pip install PySocks

这里可以详细解释一下原理:


1️⃣ 默认情况

get_url 在 Ansible 中底层调用的是 Python 的 urllibrequests 模块:

import urllib.request

它们原生只支持 HTTP、HTTPS 和 FTP 代理,例如:

http_proxy=http://1.2.3.4:8080 https_proxy=http://1.2.3.4:8080

当你写:

environment:
  ALL_PROXY: socks5://120.240.166.145:10080

普通的 urllib 并不能识别 socks5:// 这个协议,所以不会生效,也就是你下载一直失败。


2️⃣ PySocks 的作用

PySocks 是 Python 的一个库,它提供了 SOCKS 协议支持,同时能挂钩到 Python 的 socket 层

import socks
import socket

socks.set_default_proxy(socks.SOCKS5, "120.240.166.145", 10080)
socket.socket = socks.socksocket
  • 它会重写 Python 的标准 socket 类,让所有通过 socket 发出的连接都走 SOCKS 代理。
  • 因为 urllibrequests 等都是基于标准 socket 发起 TCP 连接的,所以重写 socket 后,它们就能通过 SOCKS5 代理访问网络了。

这就是为什么“安装 PySocks 并配置 ALL_PROXY 后,get_url 就能用 SOCKS5 代理”——底层 socket 被劫持了。


3️⃣ 总结

  • 没有 PySocks:Python 的网络模块识别不了 socks5://,代理无效。
  • 安装 PySocks:它会 hook socket,实现 SOCKS5 支持,所有 Python 代码(包括 Ansible 的 get_url)都能使用 SOCKS5 代理。
  • 注意:这种方式是Python 层面劫持 socket,所以全局有效,适用于 urllib、requests,但不适用于系统级 curl/wget,除非它们也支持 SOCKS5。

如果你需要,我可以帮你画一个图,直观显示 Python + PySocks 处理 SOCKS5 请求的流程。

你希望我画吗?

========================== Python 请求流程对比

1️⃣ 没有 PySocks

Python urllib/requests | | 代理 URL = socks5://... V socket.connect() | X 无法识别 socks5 协议 | 连接失败 / 无法通过代理

2️⃣ 安装 PySocks

Python urllib/requests | | 代理 URL = socks5://... V PySocks hook | V socket.connect() -> PySocks socket | | 通过 SOCKS5 代理服务器转发请求 V 目标服务器

说明:

  • PySocks 通过替换 / hook Python 标准库的 socket.connect 方法, 在 Python 层面实现 SOCKS5 协议解析和数据转发。
  • 对系统命令 (curl/wget) 无效,除非它们本身支持 SOCKS5。