feat: SOCKS5 代理管理系统 v1.0
Flask + SQLite + Bootstrap5 暗色主题 - 仪表盘: 在线/离线统计 + 最近代理 + 操作日志 - 代理 CRUD: 增删改 + 启用/禁用 + 单/批量健康检测(SOCKS5) - 分组管理: 创建/删除/筛选 - 操作日志: 分页查询 - RESTful API + Web 界面 - 管理员登录认证 (SM_ADMIN_PASSWORD 环境变量)
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import time
|
||||
import logging
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from models import Proxy, db
|
||||
from extensions import db as _db_ext
|
||||
|
||||
log = logging.getLogger("socks.health")
|
||||
|
||||
TEST_URL = "http://httpbin.org/get"
|
||||
|
||||
|
||||
def check_proxy(proxy):
|
||||
"""检查单个 SOCKS5 代理是否可用。返回 {status, latency_ms, error}"""
|
||||
import socks
|
||||
import socket
|
||||
|
||||
host, port = proxy.host, proxy.port
|
||||
timeout = 10
|
||||
status = "unknown"
|
||||
latency = None
|
||||
error = None
|
||||
|
||||
orig_getaddrinfo = socket.getaddrinfo
|
||||
orig_socket = socket.socket
|
||||
|
||||
try:
|
||||
# 使用 PySocks 创建 SOCKS5 隧道
|
||||
s = socks.socksocket()
|
||||
s.settimeout(timeout)
|
||||
s.set_proxy(socks.SOCKS5, host, port,
|
||||
username=proxy.username or None,
|
||||
password=proxy.password or None)
|
||||
|
||||
t0 = time.time()
|
||||
# 尝试连接到测试 URL(httpbin.org)
|
||||
s.connect(("httpbin.org", 80))
|
||||
elapsed = time.time() - t0
|
||||
latency = round(elapsed * 1000, 1)
|
||||
|
||||
# 发送一个简单 HTTP HEAD 请求验证隧道通畅
|
||||
s.sendall(b"HEAD /get HTTP/1.1\r\nHost: httpbin.org\r\nConnection: close\r\n\r\n")
|
||||
resp = s.recv(1024)
|
||||
s.close()
|
||||
|
||||
if resp and (b"200" in resp[:4] or b"301" in resp[:4] or b"302" in resp[:4]):
|
||||
status = "online"
|
||||
else:
|
||||
status = "online" # 连接成功即算在线(某些代理只允许特定目标)
|
||||
|
||||
except Exception as e:
|
||||
status = "offline"
|
||||
error = str(e)[:200]
|
||||
log.warning("Proxy %s:%d check failed: %s", host, port, e)
|
||||
finally:
|
||||
socket.getaddrinfo = orig_getaddrinfo
|
||||
socket.socket = orig_socket
|
||||
|
||||
return {"status": status, "latency_ms": latency, "error": error}
|
||||
|
||||
|
||||
def run_health_checks():
|
||||
"""对所有 enabled 的代理运行健康检测,更新数据库,返回结果摘要。"""
|
||||
proxies = Proxy.query.filter_by(enabled=True).all()
|
||||
results = []
|
||||
online_count = 0
|
||||
|
||||
for p in proxies:
|
||||
r = check_proxy(p)
|
||||
p.status = r["status"]
|
||||
p.latency_ms = r["latency_ms"]
|
||||
p.last_check = datetime.now(timezone.utc)
|
||||
if r["status"] == "online":
|
||||
online_count += 1
|
||||
results.append({
|
||||
"id": p.id, "name": p.name, "host": p.host, "port": p.port,
|
||||
**r,
|
||||
})
|
||||
|
||||
_db_ext.session.commit()
|
||||
return {
|
||||
"checked": len(results),
|
||||
"online": online_count,
|
||||
"offline": len(results) - online_count,
|
||||
"details": results,
|
||||
}
|
||||
Reference in New Issue
Block a user