文章851
标签121
分类10

加密通信的流行工具

工具特点适用场景
Stunnel简单易用,支持 SSL/TLS 加密快速实现加密通信
OpenVPN功能强大,支持完整 VPN 解决方案企业级 VPN 部署
SSH 隧道无需额外工具,支持动态端口转发临时加密通信
WireGuard高性能,轻量级,适合现代 VPN 需求高性能 VPN,移动设备
IPSec网络层加密,适合大规模部署企业级网络加密
HAProxy支持负载均衡和 SSL/TLS 终止高并发 Web 服务
Nginx高性能反向代理,支持 HTTPSWeb 服务加密
Socat多功能网络工具,支持多种协议临时测试或调试
Tailscale基于 WireGuard,简单易用团队协作,远程办公
Let's Encrypt (Certbot)免费 SSL/TLS 证书,自动化管理低成本 HTTPS 部署
Cloudflare Argo Tunnel无需开放端口,集成 Cloudflare 功能安全暴露本地服务

PHP 接入 OneZore

2025-02-27T01:15:44.png

在现代应用开发中,数据的安全性至关重要。OneZore 是一个强大的服务,但为了确保数据传输的安全性,我们通常需要使用加密通道。本文将介绍如何通过 Stunnel 建立加密通道,并使用 PHP 安全地连接 OneZore。

什么是 Stunnel

Stunnel 是一个开源的多平台代理工具,用于在不支持加密的客户端和服务端之间提供 SSL/TLS 加密。它通过将未加密的流量封装在加密通道中,确保数据在传输过程中的安全性。

为什么使用 Stunnel

  • 加密通信:确保数据在传输过程中不被窃听或篡改。
  • 兼容性:支持多种协议,适用于不同系统或应用之间的安全通信。
  • 灵活性:可以在不修改现有应用代码的情况下实现加密通信。

实现步骤

1. 安装 Stunnel

首先,我们需要在服务器上安装 Stunnel。

在 Linux 上安装 Stunnel

sudo apt-get update
sudo apt-get install stunnel4

在 Windows 上安装 Stunnel

Stunnel 官网 下载并安装。

2. 配置 Stunnel

编辑 Stunnel 的配置文件(通常位于 /etc/stunnel/stunnel.confstunnel.conf),添加以下内容:

[onezore]
client = yes
accept = 127.0.0.1:8080
connect = onezore-server-address:port
  • accept:Stunnel 监听的本地地址和端口。
  • connect:OneZore 服务端的地址和端口。

3. 启动 Stunnel

在 Linux 上启动 Stunnel

sudo service stunnel4 start

在 Windows 上启动 Stunnel

通过服务管理器启动 Stunnel。

4. 使用 PHP 连接 Stunnel

在 PHP 中,我们可以通过连接到 Stunnel 监听的本地地址和端口来建立加密通信。

<?php
// 连接到 Stunnel 监听的本地端口
$host = "127.0.0.1";
$port = 8080;

// 创建 socket 连接
$socket = fsockopen($host, $port, $errno, $errstr, 30);

if (!$socket) {
    echo "连接失败: $errstr ($errno)";
} else {
    // 发送请求
    $request = "GET /endpoint HTTP/1.1\r\nHost: onezore-server\r\nConnection: Close\r\n\r\n";
    fwrite($socket, $request);

    // 读取响应
    $response = "";
    while (!feof($socket)) {
        $response .= fgets($socket, 128);
    }
    fclose($socket);

    echo "响应: " . $response;
}

5. 验证连接

运行 PHP 脚本,如果一切正常,你应该能够看到 OneZore 服务端的响应。通过 Stunnel,所有的通信都已经过加密,确保了数据的安全性。

总结

通过 Stunnel,我们可以轻松地在 PHP 应用中实现与 OneZore 的安全通信。这种方法不仅简单易行,而且无需修改现有代码,非常适合需要快速实现加密通信的场景。

通过端口和进程ID定位进程运行地址

在实际的系统管理和故障排查中,我们经常需要根据端口或进程ID(PID)来定位进程的运行地址。本文将详细介绍如何通过端口找到进程ID,再通过进程ID找到进程的运行地址。

场景描述

假设我们有一条Redis命令日志:

1739755907.286905 [0 172.31.0.12:47294] "ZADD" "test_hash" "2" "1" 

从日志中我们可以看到,Redis客户端连接的IP地址是172.0.0.1,端口是47294。我们的目标是通过这个端口找到进程ID,再通过进程ID找到进程的运行地址。

步骤详解

1. 登录到目标服务器

首先,我们需要登录到IP地址为172.0.0.1的服务器。可以使用SSH命令登录:

ssh user@172.0.0.1

2. 通过端口找到进程ID

登录到服务器后,我们可以使用lsof命令来查找哪个进程正在使用端口47294

lsof -i :47294

输出可能类似于:

COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
redis-ser 14202 redis    6u  IPv4 123456      0t0  TCP *:47294 (LISTEN)

从输出中我们可以看到,进程ID(PID)是14202,进程名称是redis-server

3. 通过进程ID找到进程的运行地址

接下来,我们可以使用ps命令来查看该进程的详细信息,包括命令行参数:

ps -p 14202 -o args=

输出可能类似于:

/usr/bin/redis-server *:6379

4. 查找进程的工作目录

为了找到进程的运行地址,我们可以使用pwdx命令来查看进程的工作目录:

pwdx 14202

输出可能类似于:

14202: /var/lib/redis

5. 使用/proc文件系统进一步确认

我们还可以通过/proc文件系统来查看进程的当前工作目录:

ls -l /proc/14202/cwd

输出可能类似于:

lrwxrwxrwx 1 redis redis 0 Oct  1 12:34 /proc/14202/cwd -> /var/lib/redis

通过以上步骤,我们成功地通过端口47294找到了进程ID14202,并通过进程ID找到了进程的运行地址/var/lib/redis。这一过程在系统管理和故障排查中非常有用,尤其是在需要定位特定服务的运行环境时。

关键命令总结

  1. 通过端口查找进程ID

    lsof -i :47294
  2. 通过进程ID查看命令行参数

    ps -p 14202 -o args=
  3. 通过进程ID查找工作目录

    pwdx 14202
  4. 通过/proc文件系统确认工作目录

    ls -l /proc/14202/cwd

SSE 协议详解:使用场景与 Swoole 实现

1. 什么是 SSE?

SSE(Server-Sent Events)是一种允许服务器向客户端推送实时更新的技术。与 WebSocket 不同,SSE 是单向的,即服务器可以向客户端发送数据,但客户端不能向服务器发送数据。SSE 基于 HTTP 协议,使用简单的文本格式进行数据传输。

2025-02-15T12:45:41.png

2. SSE 与 WebSocket 的区别

2.1 通信方式

  • SSE: 单向通信,服务器向客户端推送数据。
  • WebSocket: 双向通信,服务器和客户端可以互相发送数据。

2.2 协议

  • SSE: 基于 HTTP 协议,使用简单的文本格式。
  • WebSocket: 基于独立的 WebSocket 协议,支持二进制和文本数据。

2.3 连接管理

  • SSE: 客户端通过 HTTP 请求建立连接,服务器保持连接并推送数据。
  • WebSocket: 客户端和服务器通过 WebSocket 握手建立连接,之后可以双向通信。

2.4 适用场景

  • SSE: 适用于服务器向客户端推送实时更新的场景,如股票行情、新闻推送等。
  • WebSocket: 适用于需要双向通信的场景,如聊天应用、在线游戏等。

图解 SSE 和 WebSocket 的区别

+-------------------+               +-------------------+
|                   |               |                   |
|    Client         |               |    Client         |
|                   |               |                   |
+--------+----------+               +--------+----------+
         |                                    |
         | HTTP Request                       | WebSocket Handshake
         |                                    |
         v                                    v
+--------+----------+               +--------+----------+
|                   |               |                   |
|    Server         |               |    Server         |
|                   |               |                   |
+-------------------+               +-------------------+
         |                                    |
         | SSE (Server Push)                  | WebSocket (Bi-directional)
         |                                    |
         v                                    v
+--------+----------+               +--------+----------+
|                   |               |                   |
|    Client         |               |    Client         |
|                   |               |                   |
+-------------------+               +-------------------+

3. SSE 协议格式

SSE 数据格式非常简单,每条消息由若干行文本组成,每行以换行符 \n 结尾。消息可以包含以下字段:

  • data: 消息的内容,可以有多行。
  • event: 事件类型,可选。
  • id: 消息的唯一标识符,可选。
  • retry: 客户端重连的时间间隔,单位为毫秒,可选。

图解 SSE 协议格式

event: message\n
id: 123\n
retry: 5000\n
data: {\n
data:   "message": "Hello, World!"\n
data: }\n
\n

4. SSE 的使用场景

SSE 适用于以下场景:

  • 实时通知: 如新闻推送、系统通知等。
  • 实时数据更新: 如股票行情、天气预报等。
  • 日志监控: 实时查看服务器日志。
  • 进度更新: 如文件上传进度、任务处理进度等。

5. Swoole 实现 SSE 示例

5.1 服务端代码

<?php

use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\Http\Server;

$server = new Server("0.0.0.0", 9501);

$server->on("request", function (Request $request, Response $response) {
    // 设置响应头
    $response->header("Content-Type", "text/event-stream");
    $response->header("Cache-Control", "no-cache");
    $response->header("Connection", "keep-alive");

    // 发送初始数据
    $response->write("event: connect\n");
    $response->write("data: " . json_encode(["message" => "Connected"]) . "\n\n");

    // 模拟实时数据推送
    $i = 0;
    while (true) {
        $i++;
        $response->write("data: " . json_encode(["message" => "Message $i"]) . "\n\n");
        sleep(1);
    }
});

$server->start();

5.2 客户端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SSE Client</title>
</head>
<body>
    <div id="messages"></div>

    <script>
        const eventSource = new EventSource("http://127.0.0.1:9501");

        eventSource.onmessage = function(event) {
            const data = JSON.parse(event.data);
            document.getElementById("messages").innerHTML += `<p>${data.message}</p>`;
        };

        eventSource.onerror = function(event) {
            console.error("EventSource failed:", event);
        };
    </script>
</body>
</html>

6. 总结

SSE 是一种简单且高效的服务器推送技术,适用于需要服务器向客户端实时推送数据的场景。与 WebSocket 相比,SSE 更加轻量级且易于实现。通过 Swoole,我们可以轻松实现 SSE 服务端,并结合前端技术实现实时数据推送功能。

[踩坑] Mysql 主从延迟排故过程分析

昨天帮朋友 看一个问题, 服务器间接主从延迟问题, 延迟时间不固定, 偶现1到2小时随机出现, 每次延迟最高30秒,维持1分钟左右.

主库CPU长期50% 负载不严重, 从库了解到更是没流量没负载.

2025-02-12T00:20:52.png

2025-02-12T00:21:58.png

常见出现主从延迟的场景如下:

  1. 主从配置不同, 从库配置查同步慢
  2. 从库负载过高, 导致延迟
  3. 大事务操作, insert select 最为经典, 还有 就是 for update / delete / update 语句中的 where 使用区间索引.

了解到 可以排除前两样 1 和 2, 排除法定位 查询是否存在慢日志.

使用谷歌的GCP云服务, 内部提供了个查询工具, 通过平均执行时间倒序 找出问题的

2025-02-12T00:27:37.png

1) 逐一SQL排查 发现 发现 存在 insert select 语句 是个大问题
2) 又发现两个 delete 语句 where 条件是 id <= $id and type=1 and status=1, id 是主键 type不是1就是2 虽然 type status 存在索引,但这个delete 语句 用到的还是 主键索引! 索引导致区间锁的问题.

解决方案:

修改 1) 2) 的SQL语句, 改为

1. 查询出需要删除的表 500条
2. 事务开启
3. 批量插入500条到新表
4. 使用 主键ID, delete from where id in () 批量删除500条 
5. 事务提交
">