mirror of
https://github.com/hotyue/IP-Sentinel.git
synced 2026-06-09 11:19:46 +08:00
feat(webhook): 架构大跃迁!引入解耦型双轨独立监听器(Dual-Socket)彻底阻断内核态兼容冲突,并上线「前置安全遥测雷达」打破历史透明盲区
This commit is contained in:
@@ -126,6 +126,18 @@ if os.path.exists('/opt/ip_sentinel/config.conf'):
|
||||
|
||||
class AgentHandler(http.server.BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
# ==========================================================
|
||||
# 【核心加固】打破遥测盲区:请求一旦触达协议栈,在任何校验前强行审计
|
||||
# ==========================================================
|
||||
try:
|
||||
log_dir = '/opt/ip_sentinel/logs'
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
ts = time.strftime('%Y-%m-%d %H:%M:%S UTC', time.gmtime())
|
||||
with open(f'{log_dir}/agent.log', 'a', encoding='utf-8') as f:
|
||||
f.write(f"[{ts}] [TELEMETRY] Connection received from {self.client_address} -> Path: {self.path}\n")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# [权限校验] 路径解析与 HMAC-SHA256 动态签名核验
|
||||
parsed = urllib.parse.urlparse(self.path)
|
||||
req_path = parsed.path
|
||||
@@ -484,55 +496,79 @@ fi
|
||||
pass
|
||||
|
||||
import socket
|
||||
import threading
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# [核心架构] 多线程非阻塞 Socket 模型 (抵抗 Slowloris 及阻塞攻击)
|
||||
# [核心架构大跃迁: v4.3.2 双轨解耦监听防线]
|
||||
# ----------------------------------------------------------
|
||||
class DualStackServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
||||
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
||||
allow_reuse_address = True
|
||||
|
||||
class ThreadedServerV6(ThreadedServer):
|
||||
"""专属 IPv6 隔离监听器,强行物理隔绝 IPv4 混杂空间,彻底阻断 EADDRINUSE 冲突"""
|
||||
address_family = socket.AF_INET6
|
||||
def server_bind(self):
|
||||
# [核心魔改] 强行解除 Linux/Unix 的 IPv6 独占锁
|
||||
# 实现一个 Socket 对象同时接管 IPv4 (0.0.0.0) 和 IPv6 (::) 的全域监听防漏接机制
|
||||
if self.address_family == socket.AF_INET6:
|
||||
try:
|
||||
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
|
||||
except Exception:
|
||||
pass
|
||||
super().server_bind()
|
||||
|
||||
# [v4.2.2 终极架构] 彻底抛弃配置文件的 IP 束缚,强行探测系统底层的双栈能力
|
||||
bind_addr = "::"
|
||||
address_family = socket.AF_INET6
|
||||
try:
|
||||
# 探针:如果机器是纯 IPv4 (连内核级的 IPv6 模块都没有被加载),强绑 :: 会引发 OSError,此时自动降维
|
||||
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||
s.close()
|
||||
except OSError:
|
||||
bind_addr = "0.0.0.0"
|
||||
address_family = socket.AF_INET
|
||||
def main():
|
||||
import ssl
|
||||
cert_path = '/opt/ip_sentinel/core/cert.pem'
|
||||
key_path = '/opt/ip_sentinel/core/key.pem'
|
||||
|
||||
context = None
|
||||
if os.path.exists(cert_path) and os.path.exists(key_path):
|
||||
try:
|
||||
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
context.load_cert_chain(certfile=cert_path, keyfile=key_path)
|
||||
except Exception as e:
|
||||
print(f"SSL Context creation failed: {e}")
|
||||
|
||||
DualStackServer.address_family = address_family
|
||||
httpd = DualStackServer((bind_addr, PORT), AgentHandler)
|
||||
servers = []
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# [加密通信] 强制全网挂载 TLS 加密隧道上下文
|
||||
# ----------------------------------------------------------
|
||||
import ssl
|
||||
cert_path = '/opt/ip_sentinel/core/cert.pem'
|
||||
key_path = '/opt/ip_sentinel/core/key.pem'
|
||||
|
||||
if os.path.exists(cert_path) and os.path.exists(key_path):
|
||||
# 1. 尝试挂载 IPv4 独立对空雷达
|
||||
try:
|
||||
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
context.load_cert_chain(certfile=cert_path, keyfile=key_path)
|
||||
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
|
||||
ThreadedServer.address_family = socket.AF_INET
|
||||
srv_v4 = ThreadedServer(("0.0.0.0", PORT), AgentHandler)
|
||||
if context:
|
||||
srv_v4.socket = context.wrap_socket(srv_v4.socket, server_side=True)
|
||||
servers.append(srv_v4)
|
||||
print(f"📡 IPv4 Vector Socket binding established on 0.0.0.0:{PORT}")
|
||||
except Exception as e:
|
||||
print(f"SSL 隧道构建失败,退化为 HTTP: {e}")
|
||||
print(f"⚠️ IPv4 Socket binding failed: {e}")
|
||||
|
||||
try:
|
||||
httpd.serve_forever()
|
||||
except Exception as e:
|
||||
sys.exit(1)
|
||||
# 2. 尝试挂载 IPv6 独立对空雷达 (强制隔离 IPv4)
|
||||
try:
|
||||
srv_v6 = ThreadedServerV6(("::", PORT), AgentHandler)
|
||||
if context:
|
||||
srv_v6.socket = context.wrap_socket(srv_v6.socket, server_side=True)
|
||||
servers.append(srv_v6)
|
||||
print(f"📡 IPv6 Vector Socket binding established on [::]:{PORT}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ IPv6 Socket binding failed: {e}")
|
||||
|
||||
if not servers:
|
||||
print("❌ [FATAL] Dual-Stack Network Radar completely localized binding failed!")
|
||||
sys.exit(1)
|
||||
|
||||
# 3. 跨线程异步并发激活所有对空信道
|
||||
for srv in servers:
|
||||
t = threading.Thread(target=srv.serve_forever, daemon=True)
|
||||
t.start()
|
||||
|
||||
# 4. 主守护线程,使用简单的时间挂起
|
||||
try:
|
||||
while True:
|
||||
time.sleep(3600)
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
EOF
|
||||
|
||||
echo "🚀 [Agent] 正在启动 Webhook 监听服务 (端口: $AGENT_PORT)..."
|
||||
echo "🚀 [Agent] 正在启动双轨独立 Webhook 监听引擎 (端口: $AGENT_PORT)..."
|
||||
exec python3 "${INSTALL_DIR}/core/webhook.py" "$AGENT_PORT"
|
||||
Reference in New Issue
Block a user