暗网采集的部署
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

521 lines
13 KiB

  1. # 暗网采集服务部署笔记
  2. > CentOS + Tor + Privoxy + Flask(python3 直接启动)
  3. ## 环境信息
  4. | 项目 | 值 |
  5. |------|-----|
  6. | 云平台 | 华为云 |
  7. | 部署主机 | `ocai-node-05` |
  8. | 公网 IP | `124.243.188.109` |
  9. | 内网 IP | `192.168.0.131`(同 VPC 内访问) |
  10. | 代码目录 | `/opt/crawl/darkweb_api` |
  11. | 入口文件 | `darkweb_api_3.py` |
  12. | 服务 | 端口 | 说明 |
  13. |------|------|------|
  14. | Tor (SOCKS5) | `9050` | 暗网隧道;动态采集直连此端口 |
  15. | Privoxy (HTTP) | `19095` | 静态采集走此代理 |
  16. | Flask API | `8000` | 采集接口 `/crawl` |
  17. **端口对应关系(三处必须一致):**
  18. | 组件 | 配置文件 | 关键项 | 值 |
  19. |------|----------|--------|-----|
  20. | Tor | `/etc/tor/torrc` | `SOCKSPort` | `127.0.0.1:9050` |
  21. | Privoxy | `/etc/privoxy/config` | `listen-address` | `127.0.0.1:19095` |
  22. | Privoxy | `/etc/privoxy/config` | `forward-socks5t` | `/ 127.0.0.1:9050 .` |
  23. | API 代码 | `darkweb_api_3.py` | 静态代理 / 动态代理 | `19095` / `9050` |
  24. ## API 接口说明
  25. **作用**:接收一个目标 URL(明网或 `.onion` 暗网),由服务器经 Tor 代理抓取页面内容,以 JSON 返回 HTML 源码。调用方无需在本机配置 Tor / 代理。
  26. | 项目 | 说明 |
  27. |------|------|
  28. | 地址 | `POST http://<IP>:8000/crawl` |
  29. | Content-Type | `application/json` |
  30. | 采集模式 | **静态**(默认):`requests` + Privoxy;**动态**:Playwright + Tor,适合搜索页 / JS 渲染页 |
  31. **输入(JSON Body):**
  32. | 参数 | 必填 | 默认值 | 说明 |
  33. |------|------|--------|------|
  34. | `url` | 是 | — | 要采集的目标地址 |
  35. | `is_dynamic` | 否 | `false` | `true` 启用动态采集(Playwright) |
  36. | `headers` | 否 | `{}` | 自定义请求头 |
  37. | `cookies` | 否 | `{}` | 自定义 Cookie |
  38. | `referer` | 否 | — | Referer 头 |
  39. | `static_timeout_s` | 否 | `60` | 静态采集超时(秒) |
  40. | `dynamic_timeout_ms` | 否 | `90000` | 动态页面加载超时(毫秒) |
  41. | `wait_selector` | 否 | — | 动态模式下等待的 CSS 选择器 |
  42. | `wait_selector_timeout_ms` | 否 | `30000` | 选择器等待超时(毫秒) |
  43. **输出(JSON):**
  44. 成功(HTTP 200):
  45. ```json
  46. {
  47. "code": 200,
  48. "msg": "success",
  49. "mode": "静态",
  50. "data": {
  51. "status_code": 200,
  52. "url": "http://xxx.onion/",
  53. "content": "<html>...页面源码...</html>"
  54. }
  55. }
  56. ```
  57. 失败:
  58. | HTTP 状态码 | `code` | `msg` 示例 |
  59. |-------------|--------|------------|
  60. | 400 | 400 | `请发送 JSON 格式` / `url 不能为空` |
  61. | 502 | 502 | `代理连接失败,请检查服务状态` |
  62. | 504 | 504 | `静态请求超时` / `动态请求超时` |
  63. | 500 | 500 | `系统异常: ...` |
  64. **Python 调用示例:**
  65. ```python
  66. import requests
  67. resp = requests.post(
  68. "http://124.243.188.109:8000/crawl",
  69. json={"url": "http://xxx.onion/", "is_dynamic": True},
  70. timeout=300,
  71. )
  72. data = resp.json()
  73. html = data["data"]["content"] # msg == "success" 时取用
  74. ```
  75. ---
  76. # 快速上手(最常用)
  77. ## 关键配置(首次部署必做)
  78. > Privoxy 默认监听 `8118`,必须改成 `19095` 并转发到 Tor `9050`;改完后还要处理文件权限。
  79. ### 1. 配置 Tor(`/etc/tor/torrc`)
  80. ```bash
  81. sudo vim /etc/tor/torrc
  82. ```
  83. 确认存在以下行(没有就加上,有重复端口配置以这条为准):
  84. ```
  85. SOCKSPort 127.0.0.1:9050
  86. ```
  87. ```bash
  88. sudo systemctl restart tor
  89. sudo netstat -tlnp | grep 9050 # 应看到 tor 监听 9050
  90. ```
  91. ### 2. 配置 Privoxy(`/etc/privoxy/config`)
  92. ```bash
  93. sudo vim /etc/privoxy/config
  94. ```
  95. **① 注释掉默认监听端口**(搜索 `listen-address`,把 `8118` 那行注释掉):
  96. ```
  97. # listen-address 127.0.0.1:8118
  98. # listen-address [::1]:8118
  99. ```
  100. **② 新增监听端口**(HTTP 代理,供 API 静态采集使用):
  101. ```
  102. listen-address 127.0.0.1:19095
  103. ```
  104. **③ 新增转发规则**(把 HTTP 代理流量转给 Tor SOCKS5,末尾 `.` 不能漏):
  105. ```
  106. forward-socks5t / 127.0.0.1:9050 .
  107. ```
  108. **④ 修复权限**(`sudo vim` 改完后面属主会变成 root,Privoxy 会启动失败):
  109. ```bash
  110. sudo chown -R privoxy:privoxy /etc/privoxy/
  111. ```
  112. **⑤ 若 SELinux 拦截 19095 端口**(启动失败或端口未监听时):
  113. ```bash
  114. sudo setenforce 0
  115. ```
  116. ```bash
  117. sudo systemctl restart privoxy
  118. sudo netstat -tlnp | grep 19095 # 应看到 privoxy 监听 19095
  119. ```
  120. ### 3. 确认 API 代码端口一致
  121. `darkweb_api_3.py` 中应与上面配置对应(一般默认已正确,改过 Privoxy 端口时需同步修改):
  122. ```python
  123. STATIC_PROXY_PORT = "19095" # 对应 Privoxy listen-address
  124. DYNAMIC_PROXY_SERVER = "socks5://127.0.0.1:9050" # 对应 Tor SOCKSPort
  125. ```
  126. ---
  127. ## 启动服务
  128. ```bash
  129. # 1. 启动基础代理(一般已装好,重启即可)
  130. sudo systemctl start tor
  131. sudo systemctl start privoxy
  132. # 2. 启动 API
  133. cd /opt/crawl/darkweb_api
  134. nohup python3 darkweb_api_3.py > ./logs/api_stdout.log 2>&1 &
  135. ```
  136. ## 验证命令
  137. ```bash
  138. # 服务与端口
  139. sudo systemctl status tor privoxy
  140. ps -ef | grep darkweb_api_3
  141. sudo netstat -tlnp | grep -E '9050|19095|8000'
  142. # Tor 直连
  143. curl --socks5-hostname 127.0.0.1:9050 --max-time 60 http://httpbin.org/ip
  144. # Privoxy 转发
  145. curl -x http://127.0.0.1:19095 --max-time 60 http://httpbin.org/ip
  146. # 暗网连通
  147. curl -x http://127.0.0.1:19095 -L --max-time 120 \
  148. "http://darkzqtmbdeauwq5mzcmgeeuhet42fhfjj4p5wbak3ofx2yqgecoeqyd.onion/"
  149. # API 静态采集
  150. curl -X POST -H "Content-Type: application/json" \
  151. -d '{"url": "http://darkzqtmbdeauwq5mzcmgeeuhet42fhfjj4p5wbak3ofx2yqgecoeqyd.onion/"}' \
  152. http://127.0.0.1:8000/crawl
  153. # API 动态采集
  154. curl -X POST -H "Content-Type: application/json" \
  155. -d '{"url": "http://darkzqtmbdeauwq5mzcmgeeuhet42fhfjj4p5wbak3ofx2yqgecoeqyd.onion/search?q=a", "is_dynamic": true}' \
  156. http://127.0.0.1:8000/crawl
  157. ```
  158. ## 一键体检
  159. ```bash
  160. echo "=== Tor ===" && curl -s --socks5-hostname 127.0.0.1:9050 --max-time 30 http://httpbin.org/ip && \
  161. echo -e "\n=== Privoxy ===" && curl -s -x http://127.0.0.1:19095 --max-time 30 http://httpbin.org/ip && \
  162. echo -e "\n=== API ===" && curl -s -X POST -H "Content-Type: application/json" \
  163. -d '{"url":"http://httpbin.org/ip"}' http://127.0.0.1:8000/crawl | head -c 200
  164. ```
  165. ## 启停与排障
  166. ```bash
  167. # 采集超时?先重启 Tor(最常见修复方式)
  168. sudo systemctl restart tor
  169. sudo systemctl restart privoxy
  170. # 查看 Tor 是否正常建电路
  171. journalctl -u tor -n 20 --no-pager | grep -iE 'bootstrap|circuit'
  172. # API 进程管理
  173. ps -ef | grep darkweb_api_3
  174. kill <PID>
  175. cd /opt/crawl/darkweb_api && nohup python3 darkweb_api_3.py > ./logs/api_stdout.log 2>&1 &
  176. ```
  177. ## 外部调用
  178. ```bash
  179. # 其他机器通过公网 IP 调 API(推荐)
  180. curl -X POST -H "Content-Type: application/json" \
  181. -d '{"url": "http://<onion-url>/"}' \
  182. http://124.243.188.109:8000/crawl
  183. # 同 VPC 内网
  184. curl -X POST -H "Content-Type: application/json" \
  185. -d '{"url": "http://<onion-url>/"}' \
  186. http://192.168.0.131:8000/crawl
  187. ```
  188. ---
  189. # 详细部署说明
  190. ## 一、核心架构
  191. ```
  192. 客户端 (Python / Curl / 其他服务器)
  193. ↓ HTTP 请求
  194. Flask API (:8000) ──静态采集──→ Privoxy (:19095)
  195. │ ↓ SOCKS5
  196. └──动态采集 (Playwright) ──────────→ Tor (:9050)
  197. ↓ 加密隧道
  198. 暗网 (.onion)
  199. ```
  200. - **Tor**:建立暗网加密隧道,提供 SOCKS5 接口(`9050`)。
  201. - **Privoxy**:将 HTTP 代理请求翻译为 SOCKS5 后转发给 Tor。
  202. - **Flask API**:对外提供 `/crawl` 接口;静态走 Privoxy,动态由 Playwright 直连 Tor。当前以 `python3` 直接启动。
  203. ---
  204. ## 二、安装与配置 Tor
  205. Tor 不在 CentOS 默认源中,需先添加 EPEL:
  206. ```bash
  207. sudo yum install epel-release -y
  208. sudo yum install tor -y
  209. ```
  210. 编辑 `/etc/tor/torrc`,确认 SOCKS 监听端口:
  211. ```
  212. SOCKSPort 127.0.0.1:9050
  213. ```
  214. ```bash
  215. sudo systemctl start tor
  216. sudo systemctl enable tor
  217. sudo systemctl restart tor
  218. sudo netstat -tlnp | grep 9050 # 确认 9050 已监听
  219. ```
  220. ---
  221. ## 三、安装与配置 Privoxy
  222. ```bash
  223. sudo yum install privoxy -y
  224. ```
  225. 编辑 `/etc/privoxy/config`,**三项必改**:
  226. | 步骤 | 操作 | 说明 |
  227. |------|------|------|
  228. | ① | 注释默认 `listen-address ... 8118` | 避免仍监听旧端口 |
  229. | ② | 新增 `listen-address 127.0.0.1:19095` | HTTP 代理监听端口 |
  230. | ③ | 新增 `forward-socks5t / 127.0.0.1:9050 .` | 转发到 Tor,末尾 `.` 不能漏 |
  231. 完整示例:
  232. ```
  233. # listen-address 127.0.0.1:8118
  234. # listen-address [::1]:8118
  235. listen-address 127.0.0.1:19095
  236. forward-socks5t / 127.0.0.1:9050 .
  237. ```
  238. 改完权限并启动:
  239. ```bash
  240. sudo chown -R privoxy:privoxy /etc/privoxy/
  241. sudo systemctl start privoxy
  242. sudo systemctl enable privoxy
  243. sudo systemctl restart privoxy
  244. sudo systemctl status privoxy
  245. sudo netstat -tlnp | grep 19095
  246. ```
  247. ---
  248. ## 四、常见问题
  249. ### 权限错误(Permission Denied)
  250. `sudo vim` 改配置后文件属主变为 `root`,Privoxy 以 `privoxy` 用户运行时会读不到配置:
  251. ```bash
  252. sudo chown -R privoxy:privoxy /etc/privoxy/
  253. ls -l /etc/privoxy/config # 确认属主为 privoxy
  254. ```
  255. ### SELinux 拦截自定义端口
  256. CentOS 默认只允许 Privoxy 监听 `8118`,改用 `19095` 可能被拦截:
  257. ```bash
  258. sudo setenforce 0 # 临时关闭,验证后可按需配置 SELinux 策略
  259. ```
  260. ### Tor 进程在跑但采集超时
  261. 日志出现 `0 circuits open` 或 Privoxy 请求 `127.0.0.1:19095` 超时:
  262. ```bash
  263. sudo systemctl restart tor
  264. journalctl -u tor -f # 观察是否出现 Bootstrapped 100%
  265. ```
  266. 若重启后仍卡在 Bootstrap 5%,检查系统时间(`timedatectl`)和华为云安全组出站规则;仍不通再考虑配置 Tor Bridge。
  267. ---
  268. ## 五、API 服务部署
  269. ### 接口作用
  270. `/crawl` 是暗网采集服务的唯一入口。客户端传入目标 URL,服务端代为完成:
  271. 1. **静态模式**(默认):通过 Privoxy → Tor 发 HTTP 请求,返回页面 HTML。
  272. 2. **动态模式**(`is_dynamic: true`):启动无头浏览器经 Tor 访问,支持 JS 渲染、自动滚动,返回渲染后的 HTML。
  273. 适用于:暗网页面采集、搜索结果显示、需登录 Cookie / 自定义请求头的场景。部分站点在代码内置了采集策略,会自动切换动态模式。
  274. ### 请求格式
  275. ```
  276. POST /crawl
  277. Host: 124.243.188.109:8000
  278. Content-Type: application/json
  279. ```
  280. ```json
  281. {
  282. "url": "http://darkzqtmbdeauwq5mzcmgeeuhet42fhfjj4p5wbak3ofx2yqgecoeqyd.onion/search?q=a",
  283. "is_dynamic": true,
  284. "headers": {"User-Agent": "Mozilla/5.0 ..."},
  285. "cookies": {"session": "xxx"},
  286. "referer": "http://xxx.onion/",
  287. "static_timeout_s": 120,
  288. "dynamic_timeout_ms": 90000,
  289. "wait_selector": "body",
  290. "wait_selector_timeout_ms": 30000
  291. }
  292. ```
  293. ### 响应格式
  294. **成功:**
  295. ```json
  296. {
  297. "code": 200,
  298. "msg": "success",
  299. "mode": "动态",
  300. "data": {
  301. "status_code": 200,
  302. "url": "http://xxx.onion/search?q=a",
  303. "content": "<!DOCTYPE html>..."
  304. }
  305. }
  306. ```
  307. | 字段 | 说明 |
  308. |------|------|
  309. | `code` | 业务状态码,200 表示成功 |
  310. | `msg` | `success` 或错误描述 |
  311. | `mode` | 实际使用的采集模式:`静态` / `动态` |
  312. | `data.status_code` | 目标站点 HTTP 状态码 |
  313. | `data.url` | 请求的原始 URL |
  314. | `data.content` | 页面 HTML 源码(主要取用字段) |
  315. **失败:**
  316. ```json
  317. {"code": 504, "msg": "静态请求超时"}
  318. ```
  319. ### 代码目录
  320. ```bash
  321. cd /opt/crawl/darkweb_api
  322. ls darkweb_api_3.py
  323. ```
  324. 代码内代理配置(一般无需修改):
  325. - 静态代理:`127.0.0.1:19095`(Privoxy)
  326. - 动态代理:`socks5://127.0.0.1:9050`(Tor)
  327. ### 启动方式
  328. 前台运行(调试用):
  329. ```bash
  330. cd /opt/crawl/darkweb_api
  331. python3 darkweb_api_3.py
  332. ```
  333. 后台运行(生产常用):
  334. ```bash
  335. cd /opt/crawl/darkweb_api
  336. nohup python3 darkweb_api_3.py > ./logs/api_stdout.log 2>&1 &
  337. ```
  338. ### 调用示例
  339. **curl:**
  340. ```bash
  341. # 静态采集
  342. curl -X POST -H "Content-Type: application/json" \
  343. -d '{"url": "http://<onion-url>/"}' \
  344. http://127.0.0.1:8000/crawl
  345. # 动态采集
  346. curl -X POST -H "Content-Type: application/json" \
  347. -d '{"url": "http://<onion-url>/", "is_dynamic": true}' \
  348. http://127.0.0.1:8000/crawl
  349. ```
  350. **Python:**
  351. ```python
  352. import requests
  353. api_url = "http://124.243.188.109:8000/crawl"
  354. payload = {
  355. "url": "http://<onion-url>/",
  356. "is_dynamic": True,
  357. }
  358. resp = requests.post(api_url, json=payload, timeout=300)
  359. result = resp.json()
  360. if result.get("msg") == "success":
  361. html = result["data"]["content"]
  362. else:
  363. print("失败:", result.get("msg"))
  364. ```
  365. **其他服务器(公网):**
  366. ```bash
  367. curl -X POST -H "Content-Type: application/json" \
  368. -d '{"url": "http://<onion-url>/"}' \
  369. http://124.243.188.109:8000/crawl
  370. ```
  371. ---
  372. ## 六、运维速查
  373. ```bash
  374. # 服务状态
  375. sudo systemctl status tor privoxy
  376. ps -ef | grep darkweb_api_3
  377. # 端口占用
  378. sudo netstat -tlnp | grep -E '9050|19095|8000'
  379. # 日志
  380. tail -f /opt/crawl/darkweb_api/logs/api_stdout.log
  381. tail -f /opt/crawl/darkweb_api/logs/*.log
  382. sudo journalctl -u tor -f
  383. sudo journalctl -u privoxy -f
  384. ```