樱花客栈

作者: 大嘴巴小牙齿

  • Nginx代理基础

    常用目录

    • /var/www/html/ 默认的站点目录,供外部访问
    • /etc/nginx/ 配置文件目录:

    nginx.conf
    Nginx 的核心配置文件,用于设置全局参数(如 worker 进程数、日志路径、PID 文件等)、事件处理模块(events 块)以及 HTTP 服务相关配置,包括 http、server 和 location 等模块。

    conf.d/
    该目录用于存放扩展配置文件,常用于按站点或功能划分虚拟主机配置。主配置文件中通常通过 include 指令引入该目录下的所有 .conf 文件,实现配置模块化管理。

    mime.types
    该文件用于定义文件扩展名与 MIME 类型之间的映射关系。Nginx 根据此文件确定响应头中的内容类型,例如将 .jpg 映射为 image/jpeg。

    fastcgi_params、uwsgi_params、scgi_params
    这些参数文件定义了与 FastCGI、uWSGI、SCGI 等后端通信所需的环境变量,便于 Nginx 在与 PHP、Python 等应用服务器交互时传递请求信息。

    • /usr/share/nginx/ 默认站点目录,最终为页面看到的内容。

    /usr/share/nginx/html/ 存放默认站点的index.html、404.html等文件

    • /var/log/nginx 日志目录

    代理

    正向代理与反向代理的区别:正向代理,客户端通过代理服务器向远程服务器发送请求;反向代理,客户端访问远程服务器,远程服务器将请求再转发至目标可用服务器。

    负载均衡:代理多个后端服务器时,Nginx 可按轮询、IP hash 等策略分发请求。

    工作原理

    Nginx包括基于事件驱动、异步非阻塞的高性能Web服务器架构,擅长处理高并发请求,常用于静态资源服务、反向代理、负载均衡等场景。

    Nginx启动一个Master主进程,然后根据配置文件创建一个或多个Worker子进程。Master主进程负责读取配置、管理进程(启动、重载、关闭),只负责“调度管理“。

    Nginx采用异步非阻塞的请求处理机制,使其具备高效处理海量并发请求的能力。相比之下,Apache默认采用的工作模式(尽管也提供异步非阻塞版本,但由于与部分内置模块存在兼容性问题而较少使用)会为每个请求分配独立的工作线程。当并发量达到数千级别时,就意味着需要同时维持数千个运行线程。这种设计会给系统带来显著负担:一方面,大量线程会消耗可观的内存资源;另一方面,频繁的线程上下文切换会产生巨大的CPU开销。这些额外的系统资源消耗不仅无法提升性能,反而会成为系统瓶颈。

    在 Nginx 中,阻塞式系统调用是大忌。既然不能阻塞,那就必须采用非阻塞的方式——比如某个事件还没准备好,系统调用会立即返回 EAGAIN,告诉你:“别急,数据还没到位,等会儿再来查!”于是,你可以先去做别的事情,过会儿再来检查。虽然这种方式避免了线程阻塞,但需要不断轮询事件状态,仍然存在不小的开销。

    于是,更高效的异步非阻塞事件驱动模型应运而生,其核心就是 selectpollepoll(Linux)或 kqueue(BSD)这样的系统调用。它们的共同特点是:

    • 批量监控多个事件:调用时虽然是阻塞的,但可以设置超时时间,期间只要有事件就绪,就会立即返回。
    • 高效的事件管理:以 epoll 为例,未就绪的事件会被注册到 epoll 中,待其就绪后再处理;如果读写时返回 EAGAIN,就重新放回 epoll 等待。这样,程序只需在所有事件都未就绪时才会真正等待,其余时间都在高效处理就绪事件。

    这种模式下,虽然单线程在同一时刻只能处理一个请求,但由于采用了事件循环机制,可以在多个请求间快速切换。关键在于:

    • 切换无代价:不同于多线程的上下文切换,Nginx 的切换是主动让出(因事件未就绪),本质上只是循环处理已就绪的事件。
    • 资源占用极低:无需创建线程,每个请求仅消耗少量内存,没有线程切换的开销,使得高并发时不会浪费 CPU 资源。

    master-workers的好处

    Nginx 采用多进程架构,每个 Worker 进程独立运行,这种设计带来了诸多优势:

    1. 无锁高性能
      • 由于 Worker 进程之间不共享内存,无需加锁,避免了锁竞争带来的性能损耗,同时也降低了编程复杂度和问题排查难度。
    2. 无缝热升级
      • 支持 nginx -s reload 热部署,在不中断服务的情况下更新配置或二进制文件,确保业务持续可用。
    3. 故障隔离,服务不中断
      • Worker 进程之间相互独立,即使某个进程崩溃,也不会影响其他进程,Master 进程会迅速重启新的 Worker,保证服务稳定运行。
      • 虽然异常的 Worker 会导致当前处理的请求失败,但仅影响部分请求,不会造成全局服务中断,降低了整体风险。
    4. 高效请求处理
      • 所有 Worker 进程公平竞争处理请求,即使某个 Worker 异常退出,剩余进程仍能继续处理新请求,确保服务高可用。

    这种进程隔离+Master 守护的机制,使得 Nginx 在保持高性能的同时,具备极强的稳定性和容错能力。

  • SSH加密算法(Diffie-Hellman、RSA、AES、ECDSA)


    Diffie-Hellman

    Diffie-Hellman(D-H)是一种“密钥交换协议“,主要用于安全地生成共享密钥,适用于需要在不安全网络上建立加密通信的场景,常用于 TLS、IPsec。

    D-H算法用于建立可用于秘密通信的共享密钥,同时使用椭圆曲线通过公共网络交换数据,以生成点并使用参数获取密钥,算法本身不负责“认证 ” 或“数据传输”。

    为了算法的简单性和实际实现,只考虑 4 个变量,一个大质数 P 和 G(P 的元根)和两个私钥值 a 和 b。
    P和G都是公开可用的数字。用户(比如 Alice 和 Bob)选择私有值 a 和 b,然后生成密钥并公开交换。对方收到密钥并生成一个密钥,之后他们使用相同的密钥进行加密。

    D-H算法示例代码(Go):

    // 实现 a^b mod P
    func power(a, b, p int) int {
    	if b == 1 {
    		return a
    	} else {
    		pow := int(math.Pow(float64(a), float64(b)))
    		return pow % p
    	}
    }
    
    func main() {
    	var P int // public key P (大质数):用作模运算的基数,限制计算范围,防止数值过大
    	var G int // public key G (原根):是一个生成元,它的不同指数幂可以生成不同的数,确保密钥交换的安全性
    	P, G = 21, 9
    
    	var a int // a's private key
    	var b int // b's private key
    	a, b = 4, 5
    
    	var x int
    	var y int
    
    	x = power(G, a, P)
    	y = power(G, b, P)
    	fmt.Println("x,y", x, y)
    
    	ka := power(y, a, P) // secret key for a
    	kb := power(x, b, P) // secret key for b
    	fmt.Println("ka,kb", ka, kb)
    }

    代码解释:

    第 1 步:A 和 B 获取公共号码 P = 23,G = 9
    第 2 步:A 选择了一个私钥 a = 4 和
    B 选择了一个私有密钥 b = 5
    第 3 步:A 和 B 计算公共值
    A: x =(9^4 mod 23) = (6561 mod 23) = 6
    B: y = (9^3 mod 23) = (729 mod 23) = 16
    第 4 步:A和B交换公共号码
    第 5 步:A收到公钥y =16和B收到公钥 x = 6
    步骤 6:A和B计算对称密钥
    A:ka = y^a mod p = 65536 mod 23 = 9
    B: kb = x^b mod p = 216 mod 23 = 9
    第 7 步:9 是共享密钥。


    RSA

    非对称加密算法。公钥和私钥是一对,如果用公钥加密,只有对应的私钥才能解密;如果用私钥加密,只有对应的公钥才能解密。

    由于资源消耗较大且运算效率较低,RSA 加密算法并不适合用于对整个消息或文件进行加密。因此,实际应用中通常将 RSA 与其他加密机制结合使用,例如用于加密对称密钥,或用于生成数字签名以确保消息的完整性与真实性。

    数字签名在身份认证和文件验证方面具有重要作用。通过防止数据在传输过程中被篡改或伪造,数字签名提高了敏感文档的安全性。其工作机制基于非对称加密:发送方使用私钥对哈希值进行签名,接收方则使用相应的公钥验证签名的合法性,从而确认消息来源及其未被篡改。

    在加密应用中,用户通常采用 混合加密策略:使用对称加密算法(如 AES)对实际数据加密,再使用 RSA 公钥对对称密钥进行加密。接收方只有在拥有 RSA 私钥的前提下,才能解密该对称密钥,并进一步访问原始消息内容。

    RSA 加密已被广泛集成到多个系统和加密库中,如 OpenSSL、cryptlib、wolfCrypt 等,亦广泛应用于 Web 浏览器、电子邮件通信、VPN 和其他网络协议中。

    在 VPN 场景中,RSA 尤其用于客户端与服务器之间的 安全密钥交换。以 OpenVPN 协议为例,RSA 可用于 TLS 握手阶段,确保密钥交换过程的机密性和双方身份的可信性,从而建立一个安全的数据通信通道。

    加密过程:

    1. 发送方获取接收方的公钥
    2. 将要发送的消息进行编码(转成数字形式)。
    3. 使用接收方的公钥对这个数字进行加密,得到密文。
    4. 将密文发送出去。

    解密过程:

    1. 接收方收到密文后,使用自己的私钥进行解密。
    2. 解密后的结果就是原始消息。

    AES

    AES-128加密过程:

    初始轮(预处理)

    • 将密钥与原始数据进行一次初步的异或混合(叫做轮密钥加)。

    主轮(9 轮): 每一轮包含以下 4 个步骤:

    • 字节代换(SubBytes):对每个字节做替换,使用一个固定的替换表(S盒),增加混淆。
    • 行移位(ShiftRows):将每一行的字节向左循环移动不同的位数,打乱位置,增加扩散。
    • 列混淆(MixColumns):对每一列的数据进行数学变换,进一步打乱数据结构。
    • 轮密钥加(AddRoundKey):将当前轮的密钥与数据块再次混合(异或运算)。

    最后一轮(第10轮)

    • 同样进行字节代换、行移位和轮密钥加,但不执行列混淆

    AES-128解密过程基本上是加密的反向操作,也需要使用相同的密钥,但各步骤顺序和处理方法刚好相反。


    RSA与AES区别

    特性RSAAES
    🔑 加密方式非对称加密(公钥 & 私钥)对称加密(同一个密钥)
    🧠 基本原理数学难题(大数分解)数据混淆与扩散(代数结构变换)
    📦 密钥类型一对密钥:公钥 + 私钥单一密钥
    ⏱️ 速度慢(适合加密小数据)快(适合加密大量数据)
    🧾 用途密钥交换、数字签名数据加密
    🔐 安全强度安全性取决于密钥长度(通常 ≥2048位)非常安全(128/192/256位)
    🛠 应用场景HTTPS 握手、SSH 登录、证书签名文件加密、VPN、数据库加密

    ECDSA

    (Elliptic curve digital signature algorithm)椭圆曲线数字签名算法

    ECDSA基于椭圆曲线密码学(Elliptic Curve Cryptography,简称ECC)。ECC是一种公钥密码学方法,其原理建立在有限域上的椭圆曲线代数结构之上。与传统的公钥加密方法,如RSA(Rivest-Shamir-Adleman),相比,ECC提供了多种优势,包括更小的密钥尺寸、更快的计算速度,以及在相同密钥长度下更高的安全性。

    椭圆曲线通过一个数学方程来定义,形式为:

    y^2 = x^3 + ax + b

    其中a和b是常数。所有满足该方程的点(x,y),以及一个被称为“无穷远”的特殊点,组成了椭圆曲线的一个群体。ECC的安全性依赖于离散对数问题,而在椭圆曲线上解决这个问题被认为是计算上不可行的,从而确保了其加密的安全性。

    在ECDSA中,每个用户生成一对公钥和私钥,用于数字签名的签署与验证。密钥生成的过程包括以下步骤:

    1. 选择一条合适的椭圆曲线,并指定该曲线上的一个点 GGG 作为基点,同时定义n为点G的阶,其中n是一个大质数。基点G和阶数n是公开的,并且在所有用户之间共享。
    2. 从1到n−1的范围内随机选择一个整数d。这个整数d被作为私钥。
    3. 计算公钥Q=dG,其中Q是椭圆曲线上的一个点。这个步骤使用了标量乘法,即重复将基点G与自身相加d次。标量乘法是椭圆曲线密码学中的核心运算。

  • Raspberry Pi 5开箱与供电

    参数

    • Broadcom BCM2712 2.4GHz 四核 64 位 Arm Cortex-A76 CPU,具有加密扩展、每核 512KB 二级缓存和 2MB 共享三级缓存
    • VideoCore VII GPU,支持 OpenGL ES 3.1、Vulkan 1.2
    • 双 4Kp60 HDMI® 显示输出,支持 HDR
    • 4Kp60 HEVC 解码器
    • LPDDR4X-4267 SDRAM(2GB、4GB、8GB 和 16GB)
    • 双频 802.11ac Wi-Fi®
    • 蓝牙 5.0 / 低功耗蓝牙 (BLE)
    • microSD 卡插槽,支持高速 SDR104 模式
    • 2 个 × 个 USB 3.0 端口,支持同步 5Gbps作
    • 2 × 个 USB 2.0 端口
    • 千兆以太网,支持 PoE+(需要单独的 PoE+ HAT)
    • 2 × 4 通道 MIPI 摄像头/显示器收发器
    • PCIe 2.0 x1 接口,用于快速外设(需要单独的 M.2 HAT 或其他适配器)
    • 通过 USB-C 提供 5V/5A 直流电源,支持 Power Delivery
    • Raspberry Pi 标准 40 针接头
    • 实时时钟 (RTC),由外部电池供电
    • 电源按钮

    开箱

    一次性封装盒子,开口处有粘胶
    使用128G TF内存卡(170mb/s读取,80mb/s写入)
    使用最小系统,无外设输入、无显示输出
    Ubuntu 24.04.02 TLS,开机内存使用约 320 Mib。当前为运行Nginx后
    使用fio测试,读取 88.6 Mib/s
    使用fio测试,写入 56.9 Mib/s

    供电

    测试了两个手机充电器,分别是22.5W(SCP 5V2A、9V2A、10V2.25A)和66W(SCP 5V3A、9V3A、11V6A、20V2A)充电头。两个充电头都能进入系统,系统会提示电流不足5A。
    查看电流信息:

    充电头命令输出换算(mA)
    22.5Whexdump -C /proc/device-tree/chosen/power/max_current00000000  00 00 03 84 |….|
    00000004
    20×03 84=900
    22.5Wod -An -t u4 -N 4 -j 0 /proc/device-tree/chosen/power/max_current22147891202214789120=0x84030000
    颠倒取03 84,
    得到900
    66Whexdump -C /proc/device-tree/chosen/power/max_current00000000  00 00 0b b8 |….|
    00000004
    20x0b b8 = 3000
    66Wod -An -t u4 -N 4 -j 0 /proc/device-tree/chosen/power/max_current30877286403087728640=0xb80b0000
    颠倒取0b b8,得到3000

    vcgencmd命令

    • watch -n 1 vcgencmd pmic_read_adc
      # 使用PMIC(电源管理芯片,含内置ADC)读取设备电源电压
    • vcgencmd measure_temp
      # 板载soc温度传感器数据
    • vcgencmd measure_clock arm
      # 内核时钟频率,arm还可以替换为uart hdmi isp emmc等
    • vcgencmd get_mem gpu
      # 分配的显存
    • vcgencmd get_lcd_info
      # 显示器信息
    • vcgencmd get_throttled
      # 获取欠压信息

  • SSH加密概念

    SSH = Secure Shell
    一种安全加密网络传输协议


    加密基础

    对称加密

    发送方和接收方都使用同一个密钥

    发送方:明文+密钥 -> 密文
    接收方:密文+密钥 -> 明文

    加密算法:
    AES(高级加密标准,Advanced Encryption Standard):目前最常用的加密算法(AES-128、AES-192、AES-256),SSH传输数据时会使用AES加密
    DES(数据加密标准,Data Encryption Standard):早期加密标准,密钥长度短(56位)

    非对称加密

    非对称加密使用一对密钥:公钥Public key和私钥Private Key
    公钥用于加密,私钥用于解密,公钥加密的数据只能用私钥解密

    发送方:使用接收方的公钥Pub进行加密
    接收方:使用自己的私钥Private进行解密

    加密算法:
    RSA(Rivest-Shamir-Adleman):基于大整数因子分解难题(常见密钥长度 2048、4096 位)
    ECDSA(椭圆曲线数字签名算法):基于椭圆曲线离散对数问题,密钥短但同等安全
    Ed25519:更快、更安全的椭圆曲线签名算法,SSH 默认使用

    哈希加密

    哈希是一种单向函数,用于计算固定长度的明文值,确保数据完整性。
    哈希值 = hash(明文)

    • 不可逆(无法从哈希值计算明文)
    • 抗碰撞(难以找到一种 hash(明文1)=hash(明文2))
    • 输入敏感(哪怕明文只改动1比特,哈希值也会大幅变化)

    加密算法:
    SHA-256  / SHA-3:广泛用于安全协议,如 TLS、SSH
    MD5(消息摘要算法):不安全,不用于加密传输,可用于验证传输信息完整性


    SSH认证

    固定密码📚或密钥对🔑登陆SSH服务器,弱强度的固定密码有被暴力破解的可能。

    1. 固定密码登陆方式:客户端通过ssh命令向ssh服务器发送登陆请求;服务器向客户端协商密钥用于构建加密通信通道;加密通道建立后,服务器向客户端索要登陆密码,并与服务器上存储的密码比对;密码校验通过后,服务器允许客户端访问Shell。
    服务器协商,对称密钥SHA-256
    1. 密钥对的登陆方式包括公钥和私钥概念,公钥即可以公开的密钥,私钥只有在本地存储才安全。
    密钥对方式登陆

    密钥存储

    1. 本机公钥信息存储在文件:~/.ssh/authorized_keys
      公钥通常的内容是(加密类型+公钥文+域):
    ssh-ed25519 AAAAAAAAAAC1yc2EAAAADAQABAAACAQDRxHaAqjB5LcvNGMuB/W9vL2sfbfvl8CKgkZUT9041MCtV9j== hi@ziyuan.work
    1. ~/.ssh/ 目录还会存放服务器的公钥和私钥文件,通常是.pem.pub.pem文件,文件格式为PEM(Privacy-Enhanced Mail)

    .pem私钥文件内容(私钥文):

    -----BEGIN RSA PRIVATE KEY-----
    AB3NzaC1yc2EAAAADAQABAAABgQDlZICl9XYz0yovhi4ajYlyDfHL5tNt2jmX/Js0I7c+Heqb3ExzOd+Td0aYVruMQkYsulXsQfe/wzQ145OppbeFRkZATKIOkb/DcN2YvTH+YtjO/GJPtdT5WVA6I/3a+pd2AgcXVh
    -----END OPENSSH PRIVATE KEY-----

    .pem.pub公钥文件内容(加密类型+公钥文+域):

    ssh-rsa CCxrInV8Dgij2vuufsw4iLF/05hg2L9rNHdwaQx6vSDZKgjw2VPzWxCufJeKMEZbKh9a4m7D1rMPN7Z1rS6E10/vTFD2OJgbpi8eM1TondTlxVa8BZ0roXLuYCpue/CyqOoYfm74fgmAbTKWUzg86jCVL9ngn66UQsW+AtgBX00d3XZ1oJ1lL9lvlyJwE6NXIMy3f9F5dJ0RZmqXtKLBeAR+SD+lD7sPug6O/nYpEzK5BVDFGwFYtjO/GJPtdT5 hi@ziyuan.work
    1. 密钥生成

    使用ssh-keygen命令可以生成私钥和公钥

    ssh-keygen -t rsa -b 4096 -m PEM -f mykey.pem
    
    # 运行以上命令会在文件夹中得到mykey.pemmykey.pem.pub文件,移动文件到~/.ssh目录
    
    # -t 加密算法,可以有rsa dsa ed25519 ecdsa
    # -b 密钥位数(bit),当-t 为rsa和ecdsa时有效
    # -m 密钥格式,可以有PEM OPENSSH PKCS8
    # -f 文件名,通常为xxxxx.pem
    1. 使用ssh-copy-id命令可以将公钥发送给服务器,实现密钥对登陆
    ssh-copy-id user@192.168.1.10 
    
    # user:远程主机用户
    # 192.168.1.10:远程主机IP
  • 移除内核崩溃转储(kdump)

    当Linux内核崩溃时,kdump 会利用预留的一段内存(称为 crash kernel)启动一个最小化的内核环境,从而将故障时的内存数据保存到硬盘。崩溃日志可用于后期故障排查。云主机的内存比较宝贵,如果是一台4G内存的主机,除去KVM的硬件预留,还有内核崩溃转储预留,可能实际available为3.6G左右。如果不需要捕获系统崩溃信息,可以再腾出一些空间。有些云服务器厂商的系统默认配置kdump,也就是说存在云主机运行内存不足额的情况,这边需要手动更新配置。

    查看系统当前的内存预留:

    sudo dmesg | grep -i memory

    修改 /etc/default/grub ,去除crashkernel相关字段:

    GRUB_CMDLINE_LINUX=" vga=792 console=tty0 console=ttyS0,115200n8 net.ifnames=0 noibrs nvme_core.io_timeout=4294967295 nvme_core.admin_timeout=4294967295 iommu=pt crashkernel=0M-1G:0M,1G-4G:192M,4G-128G:384M,128G-:512M crash_kexec_post_notifiers=1"

    改完grub后,需要更新配置:

    sudo grub-mkconfig -o /boot/grub/grub.cfg
    
    sudo grub-mkconfig -o /boot/efi/EFI/ubuntu/grub.cfg

    再次重启主机,内存会释放。

  • 自定义Dolphin右键新建按钮

    日常在Dolphin中会用到右键-新建Librioffice Draw,这些办公类快捷按钮会在软件安装的时候自动添加,做笔记常用到markdown.md文件,配一个入口按钮方便点开创建即用。

    1. 创建模板文件夹
    ~/.local/share/templates && cd ~/.local/share/templates
    1. 新建文件
    touch MarkDown.md
    1. 新建快捷信息,并填写
    vim create_markdown.desktop
    [Desktop Entry]
    Name=Markdown
    Comment=快速新建Markdown文件
    Type=Link
    URL=MarkDown.md
    Icon=application-vnd.oasis.opendocument.text