暗网采集的部署
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.

13 KiB

暗网采集服务部署笔记

CentOS + Tor + Privoxy + Flask(python3 直接启动)

环境信息

项目
云平台 华为云
部署主机 ocai-node-05
公网 IP 124.243.188.109
内网 IP 192.168.0.131(同 VPC 内访问)
代码目录 /opt/crawl/darkweb_api
入口文件 darkweb_api_3.py
服务 端口 说明
Tor (SOCKS5) 9050 暗网隧道;动态采集直连此端口
Privoxy (HTTP) 19095 静态采集走此代理
Flask API 8000 采集接口 /crawl

端口对应关系(三处必须一致):

组件 配置文件 关键项
Tor /etc/tor/torrc SOCKSPort 127.0.0.1:9050
Privoxy /etc/privoxy/config listen-address 127.0.0.1:19095
Privoxy /etc/privoxy/config forward-socks5t / 127.0.0.1:9050 .
API 代码 darkweb_api_3.py 静态代理 / 动态代理 19095 / 9050

API 接口说明

作用:接收一个目标 URL(明网或 .onion 暗网),由服务器经 Tor 代理抓取页面内容,以 JSON 返回 HTML 源码。调用方无需在本机配置 Tor / 代理。

项目 说明
地址 POST http://<IP>:8000/crawl
Content-Type application/json
采集模式 静态(默认):requests + Privoxy;动态:Playwright + Tor,适合搜索页 / JS 渲染页

输入(JSON Body):

参数 必填 默认值 说明
url 要采集的目标地址
is_dynamic false true 启用动态采集(Playwright)
headers {} 自定义请求头
cookies {} 自定义 Cookie
referer Referer 头
static_timeout_s 60 静态采集超时(秒)
dynamic_timeout_ms 90000 动态页面加载超时(毫秒)
wait_selector 动态模式下等待的 CSS 选择器
wait_selector_timeout_ms 30000 选择器等待超时(毫秒)

输出(JSON):

成功(HTTP 200):

{
  "code": 200,
  "msg": "success",
  "mode": "静态",
  "data": {
    "status_code": 200,
    "url": "http://xxx.onion/",
    "content": "<html>...页面源码...</html>"
  }
}

失败:

HTTP 状态码 code msg 示例
400 400 请发送 JSON 格式 / url 不能为空
502 502 代理连接失败,请检查服务状态
504 504 静态请求超时 / 动态请求超时
500 500 系统异常: ...

Python 调用示例:

import requests

resp = requests.post(
    "http://124.243.188.109:8000/crawl",
    json={"url": "http://xxx.onion/", "is_dynamic": True},
    timeout=300,
)
data = resp.json()
html = data["data"]["content"]   # msg == "success" 时取用

快速上手(最常用)

关键配置(首次部署必做)

Privoxy 默认监听 8118,必须改成 19095 并转发到 Tor 9050;改完后还要处理文件权限。

1. 配置 Tor(/etc/tor/torrc

sudo vim /etc/tor/torrc

确认存在以下行(没有就加上,有重复端口配置以这条为准):

SOCKSPort 127.0.0.1:9050
sudo systemctl restart tor
sudo netstat -tlnp | grep 9050    # 应看到 tor 监听 9050

2. 配置 Privoxy(/etc/privoxy/config

sudo vim /etc/privoxy/config

① 注释掉默认监听端口(搜索 listen-address,把 8118 那行注释掉):

# listen-address  127.0.0.1:8118
# listen-address  [::1]:8118

② 新增监听端口(HTTP 代理,供 API 静态采集使用):

listen-address  127.0.0.1:19095

③ 新增转发规则(把 HTTP 代理流量转给 Tor SOCKS5,末尾 . 不能漏):

forward-socks5t / 127.0.0.1:9050 .

④ 修复权限sudo vim 改完后面属主会变成 root,Privoxy 会启动失败):

sudo chown -R privoxy:privoxy /etc/privoxy/

⑤ 若 SELinux 拦截 19095 端口(启动失败或端口未监听时):

sudo setenforce 0
sudo systemctl restart privoxy
sudo netstat -tlnp | grep 19095    # 应看到 privoxy 监听 19095

3. 确认 API 代码端口一致

darkweb_api_3.py 中应与上面配置对应(一般默认已正确,改过 Privoxy 端口时需同步修改):

STATIC_PROXY_PORT = "19095"              # 对应 Privoxy listen-address
DYNAMIC_PROXY_SERVER = "socks5://127.0.0.1:9050"   # 对应 Tor SOCKSPort

启动服务

# 1. 启动基础代理(一般已装好,重启即可)
sudo systemctl start tor
sudo systemctl start privoxy

# 2. 启动 API
cd /opt/crawl/darkweb_api
nohup python3 darkweb_api_3.py > ./logs/api_stdout.log 2>&1 &

验证命令

# 服务与端口
sudo systemctl status tor privoxy
ps -ef | grep darkweb_api_3
sudo netstat -tlnp | grep -E '9050|19095|8000'

# Tor 直连
curl --socks5-hostname 127.0.0.1:9050 --max-time 60 http://httpbin.org/ip

# Privoxy 转发
curl -x http://127.0.0.1:19095 --max-time 60 http://httpbin.org/ip

# 暗网连通
curl -x http://127.0.0.1:19095 -L --max-time 120 \
  "http://darkzqtmbdeauwq5mzcmgeeuhet42fhfjj4p5wbak3ofx2yqgecoeqyd.onion/"

# API 静态采集
curl -X POST -H "Content-Type: application/json" \
  -d '{"url": "http://darkzqtmbdeauwq5mzcmgeeuhet42fhfjj4p5wbak3ofx2yqgecoeqyd.onion/"}' \
  http://127.0.0.1:8000/crawl

# API 动态采集
curl -X POST -H "Content-Type: application/json" \
  -d '{"url": "http://darkzqtmbdeauwq5mzcmgeeuhet42fhfjj4p5wbak3ofx2yqgecoeqyd.onion/search?q=a", "is_dynamic": true}' \
  http://127.0.0.1:8000/crawl

一键体检

echo "=== Tor ===" && curl -s --socks5-hostname 127.0.0.1:9050 --max-time 30 http://httpbin.org/ip && \
echo -e "\n=== Privoxy ===" && curl -s -x http://127.0.0.1:19095 --max-time 30 http://httpbin.org/ip && \
echo -e "\n=== API ===" && curl -s -X POST -H "Content-Type: application/json" \
  -d '{"url":"http://httpbin.org/ip"}' http://127.0.0.1:8000/crawl | head -c 200

启停与排障

# 采集超时?先重启 Tor(最常见修复方式)
sudo systemctl restart tor
sudo systemctl restart privoxy

# 查看 Tor 是否正常建电路
journalctl -u tor -n 20 --no-pager | grep -iE 'bootstrap|circuit'

# API 进程管理
ps -ef | grep darkweb_api_3
kill <PID>
cd /opt/crawl/darkweb_api && nohup python3 darkweb_api_3.py > ./logs/api_stdout.log 2>&1 &

外部调用

# 其他机器通过公网 IP 调 API(推荐)
curl -X POST -H "Content-Type: application/json" \
  -d '{"url": "http://<onion-url>/"}' \
  http://124.243.188.109:8000/crawl

# 同 VPC 内网
curl -X POST -H "Content-Type: application/json" \
  -d '{"url": "http://<onion-url>/"}' \
  http://192.168.0.131:8000/crawl

详细部署说明

一、核心架构

客户端 (Python / Curl / 其他服务器)
   ↓  HTTP 请求
Flask API (:8000)  ──静态采集──→  Privoxy (:19095)
   │                                      ↓ SOCKS5
   └──动态采集 (Playwright) ──────────→  Tor (:9050)
                                              ↓ 加密隧道
                                         暗网 (.onion)
  • Tor:建立暗网加密隧道,提供 SOCKS5 接口(9050)。
  • Privoxy:将 HTTP 代理请求翻译为 SOCKS5 后转发给 Tor。
  • Flask API:对外提供 /crawl 接口;静态走 Privoxy,动态由 Playwright 直连 Tor。当前以 python3 直接启动。

二、安装与配置 Tor

Tor 不在 CentOS 默认源中,需先添加 EPEL:

sudo yum install epel-release -y
sudo yum install tor -y

编辑 /etc/tor/torrc,确认 SOCKS 监听端口:

SOCKSPort 127.0.0.1:9050
sudo systemctl start tor
sudo systemctl enable tor
sudo systemctl restart tor
sudo netstat -tlnp | grep 9050    # 确认 9050 已监听

三、安装与配置 Privoxy

sudo yum install privoxy -y

编辑 /etc/privoxy/config三项必改

步骤 操作 说明
注释默认 listen-address ... 8118 避免仍监听旧端口
新增 listen-address 127.0.0.1:19095 HTTP 代理监听端口
新增 forward-socks5t / 127.0.0.1:9050 . 转发到 Tor,末尾 . 不能漏

完整示例:

# listen-address  127.0.0.1:8118
# listen-address  [::1]:8118
listen-address  127.0.0.1:19095
forward-socks5t / 127.0.0.1:9050 .

改完权限并启动:

sudo chown -R privoxy:privoxy /etc/privoxy/
sudo systemctl start privoxy
sudo systemctl enable privoxy
sudo systemctl restart privoxy
sudo systemctl status privoxy
sudo netstat -tlnp | grep 19095

四、常见问题

权限错误(Permission Denied)

sudo vim 改配置后文件属主变为 root,Privoxy 以 privoxy 用户运行时会读不到配置:

sudo chown -R privoxy:privoxy /etc/privoxy/
ls -l /etc/privoxy/config    # 确认属主为 privoxy

SELinux 拦截自定义端口

CentOS 默认只允许 Privoxy 监听 8118,改用 19095 可能被拦截:

sudo setenforce 0    # 临时关闭,验证后可按需配置 SELinux 策略

Tor 进程在跑但采集超时

日志出现 0 circuits open 或 Privoxy 请求 127.0.0.1:19095 超时:

sudo systemctl restart tor
journalctl -u tor -f    # 观察是否出现 Bootstrapped 100%

若重启后仍卡在 Bootstrap 5%,检查系统时间(timedatectl)和华为云安全组出站规则;仍不通再考虑配置 Tor Bridge。


五、API 服务部署

接口作用

/crawl 是暗网采集服务的唯一入口。客户端传入目标 URL,服务端代为完成:

  1. 静态模式(默认):通过 Privoxy → Tor 发 HTTP 请求,返回页面 HTML。
  2. 动态模式is_dynamic: true):启动无头浏览器经 Tor 访问,支持 JS 渲染、自动滚动,返回渲染后的 HTML。

适用于:暗网页面采集、搜索结果显示、需登录 Cookie / 自定义请求头的场景。部分站点在代码内置了采集策略,会自动切换动态模式。

请求格式

POST /crawl
Host: 124.243.188.109:8000
Content-Type: application/json
{
  "url": "http://darkzqtmbdeauwq5mzcmgeeuhet42fhfjj4p5wbak3ofx2yqgecoeqyd.onion/search?q=a",
  "is_dynamic": true,
  "headers": {"User-Agent": "Mozilla/5.0 ..."},
  "cookies": {"session": "xxx"},
  "referer": "http://xxx.onion/",
  "static_timeout_s": 120,
  "dynamic_timeout_ms": 90000,
  "wait_selector": "body",
  "wait_selector_timeout_ms": 30000
}

响应格式

成功:

{
  "code": 200,
  "msg": "success",
  "mode": "动态",
  "data": {
    "status_code": 200,
    "url": "http://xxx.onion/search?q=a",
    "content": "<!DOCTYPE html>..."
  }
}
字段 说明
code 业务状态码,200 表示成功
msg success 或错误描述
mode 实际使用的采集模式:静态 / 动态
data.status_code 目标站点 HTTP 状态码
data.url 请求的原始 URL
data.content 页面 HTML 源码(主要取用字段)

失败:

{"code": 504, "msg": "静态请求超时"}

代码目录

cd /opt/crawl/darkweb_api
ls darkweb_api_3.py

代码内代理配置(一般无需修改):

  • 静态代理:127.0.0.1:19095(Privoxy)
  • 动态代理:socks5://127.0.0.1:9050(Tor)

启动方式

前台运行(调试用):

cd /opt/crawl/darkweb_api
python3 darkweb_api_3.py

后台运行(生产常用):

cd /opt/crawl/darkweb_api
nohup python3 darkweb_api_3.py > ./logs/api_stdout.log 2>&1 &

调用示例

curl:

# 静态采集
curl -X POST -H "Content-Type: application/json" \
  -d '{"url": "http://<onion-url>/"}' \
  http://127.0.0.1:8000/crawl

# 动态采集
curl -X POST -H "Content-Type: application/json" \
  -d '{"url": "http://<onion-url>/", "is_dynamic": true}' \
  http://127.0.0.1:8000/crawl

Python:

import requests

api_url = "http://124.243.188.109:8000/crawl"
payload = {
    "url": "http://<onion-url>/",
    "is_dynamic": True,
}

resp = requests.post(api_url, json=payload, timeout=300)
result = resp.json()

if result.get("msg") == "success":
    html = result["data"]["content"]
else:
    print("失败:", result.get("msg"))

其他服务器(公网):

curl -X POST -H "Content-Type: application/json" \
  -d '{"url": "http://<onion-url>/"}' \
  http://124.243.188.109:8000/crawl

六、运维速查

# 服务状态
sudo systemctl status tor privoxy
ps -ef | grep darkweb_api_3

# 端口占用
sudo netstat -tlnp | grep -E '9050|19095|8000'

# 日志
tail -f /opt/crawl/darkweb_api/logs/api_stdout.log
tail -f /opt/crawl/darkweb_api/logs/*.log
sudo journalctl -u tor -f
sudo journalctl -u privoxy -f