- 博客(77)
- 收藏
- 关注
原创 第 13 期:如何安全地修改 Smali 代码?(原理篇)
所以在只改几个字节时,如果新指令比旧指令短,必须用 nop(空操作,机器码 0x00)把剩下的空间填满,这样既改了逻辑,又不破坏文件结构。比如你把 v0 改成 v5,但 v5 里面根本就是空的,它拿个空值去比较,自然会引发空指针异常直接崩溃。如果你确信只要让它跳过失败提示就行,可以把那句 if-nez v0, :cond_1 直接删掉,或者替换成一句永远会跳转的指令:goto :cond_1。理论懂了,手就痒了。后面的判断逻辑原封不动,因为它拿到了恒为 true 的 v0,自然就顺着正常逻辑执行了。
2026-11-14 11:53:50
184
原创 第 12 期:满屏的 :cond_0 和 goto,代码到底往哪跳?
上期看的是直线代码,但只要有 if-else 或者 while 循环,smali 里就会出现一堆 :cond_0、:goto_1。你在 smali 里看到以冒号开头的,比如 :cond_0、:goto_1、:pswitch_data,它们就是代码里的坐标。你可以把它理解成路牌:goto :cond_0 的意思就是“立刻跳到贴着 :cond_0 标签的那行代码继续执行”。if-eqz v0, :cond_0:如果 v0 等于 0(或者 false),跳到 :cond_0 处。⚠️ 新手必踩的 3 个坑。
2026-11-11 22:55:08
5
原创 反编译后全是天书?带你认识 smali 语法
Dalvik 指令有两百多条,你只需要记住 const(赋值)、invoke(调用)、if(判断)、goto(跳转)、return(返回)这几大类。看到 const/4 v0, 0x0,意思就是把 0(通常代表 false)赋值给 v0。如果是非静态方法(实例方法),p0 永远是 this(当前对象自己),真正的参数从 p1 开始数。返回:return v0(返回 v0 的值),或者 return-void(无返回值)。赋值:const/4 v0, 0x1(把十六进制的 1 塞进寄存器 v0)。
2026-11-10 16:25:43
9
原创 第 10 期:只看不改非好汉:apktool 的解包与回编译
解法:找到你手机或模拟器里的 framework-res.apk(通常在 /system/framework/),把它拉出来,运行 apktool if framework-res.apk 安装框架,然后再回编译。最简单的解法:把整个文件夹删了,重新解包一次,或者加上 --use-aapt2 参数(apktool d app.apk --use-aapt2)。jadx 只能看代码(而且是伪代码),如果你想把 App 里的“文字改掉”或者“换个图标”,jadx 做不到。可以直接用记事本打开改(复习第4期)。
2026-11-09 15:56:08
7
原创 第 9 期:老牌神器 jadx 的正确打开方式
解法:找到 jadx 目录下的 bin/jadx-gui 脚本文件(Windows 是 .bat),用记事本打开,找到 DEFAULT_JVM_OPTS=“-Xmx…默认情况下,jadx 搜代码里的中文字符串可能会漏。如果你知道你要找的提示语,最好去 Resources 里找 resources.arsc 里的字符串池,或者用搜索框搜拼音或英文关键词。解压后,双击里面的 bin/jadx-gui.bat(Windows)或 bin/jadx-gui(Mac/Linux)就能启动。
2026-11-08 14:02:31
196
原创 第 8 期:Java 代码是怎么变成 classes.dex 的?
现代 App 功能太多了,一个集装箱装不下,于是就有了 classes2.dex、classes3.dex,它们本质上是多个集装箱排在一起。这就好比,.class 是一堆散装的快递盒,而 .dex 是经过物流公司重新打包、塞得严严实实的一个大集装箱。反编译工具(比如我们常听说的 jadx)干的事情,就是把机器的“0101 指令”,逆向翻译成人类能看懂的类似 Java 的代码。这就是“逆向工程”的魅力所在。不管是最初的 .java,还是中间的 .class,还是 .dex,它们本质上都是给虚拟机看的指令。
2026-11-06 18:37:14
7
原创 第 7 期:别放过 ELF 的“尾巴”,揪出加固工具的狐狸尾巴
当程序员用编译器(如 clang)把 C 代码打包成 .so 时,链接器会自动把编译器的版本信息写进 .comment 段里。如果段的数量异常少,或者出现像 [0] NULL 这种,说明它的结构被“瘦身”或“魔改”过,防御极强。Android 的 .so 文件本质上是 ELF(可执行与可链接格式),和 Linux 下的程序一模一样。它里面有严格的结构划分(段表)。如果 .comment 段是空的,不代表没加固,恰恰相反,这通常说明开发者做了“编译后清理(strip)”,或者高级混淆器把痕迹擦干净了。
2026-11-05 19:54:23
9
原创 第 6 期:strings 命令,从乱码里挖出核心情报
如果你用 Windows,可以在 Git Bash 里执行,或者装个 Python,用 pip install pefile 结合脚本去扫。如果你解压 APK,看到 lib/arm64-v8a/ 下面有 .so 文件,说明这个 App 用 C/C++ 写了核心逻辑(通常为了性能或防逆向)。这些文件用文本编辑器打开全是乱码,但它里面其实藏着海量明文,靠 strings 就能挖出来。如果跑完 strings,发现十几 MB 的文件只扫出几百行,且搜不到任何有意义的单词,说明它的字符串被加密或混淆了。
2026-11-04 20:10:36
11
原创 第 5 期:如何一眼看出 APK 被“动过手脚”?
v1 签名在 META-INF 文件夹里能直接看到,但 v2 和 v3 签名是写入在整个 ZIP 文件的特殊区块里的,解压出来根本看不到。神级操作:如果你手里有官方原版的 APK,你对比它和那个“修改版”的 SHA-256 指纹。有些开源应用(比如某些极客自己写的工具)就是用的 Debug 签名或者自签名证书发布,这本身没问题。如果只看到 v1,说明这个包可能很老,或者是用老旧工具打包的。看什么:看到 Android Debug 说明这是开发用的测试签名,绝对不可能是正规商业App的官方发布版。
2026-11-03 18:13:47
6
原创 第 4 期:AndroidManifest.xml 里藏着的三个“隐形炸弹”
怎么查:aapt2 dump xmltree --file AndroidManifest.xml app.apk | grep exported (如果看到 true,就要重点看这个组件是不是主页,不是主页的通常是隐患)。怎么查:aapt2 dump xmltree --file AndroidManifest.xml app.apk | grep allowBackup(安全要求高的金融类 App,这个值必须是 false)。本期目标:学会查看 App 的核心配置文件,识别三个最致命的配置错误。
2026-11-02 20:02:34
9
原创 第 3 期:一行命令,把 App 的底细摸得一清二楚
记得把名字换成你当前目录下真实的 APK 文件名,或者直接按住文件拖进命令行终端里,它会自动补全绝对路径。如果值是 28 以下:说明这个 App 很老,或者开发者刻意调低了这个数字,导致它依然可以使用不加密的 HTTP 协议传输数据,这就存在被中间人劫持的风险。REQUEST_INSTALL_PACKAGES:重点注意,这意味着它能偷偷给你装其他软件。看什么:这是 App 的身份证,后续你要在设备里搜索它、或者用脚本跑自动化,全靠这个名字。看什么:这行极长,但你只需重点搜几个“高敏词”。
2026-11-01 21:11:44
232
原创 第 2 期:别搞那些花里胡哨的,逆向只需这三件套
别去配全局环境变量,直接 cd 进那个 build-tools 目录里执行,或者用 ./aapt2,最省事。工具装好了,下期教你敲一行最简单的命令 aapt2 dump badging。就这一行,包名、版本、权限、支持什么 CPU 架构,全部给你列出来。很多新手一搜教程,看到要装虚拟机、装 IDA Pro、装 Frida,直接就被劝退了。怎么装:不用单独下,装了 Android Studio 就有。怎么装:有 Python 环境后,一行命令搞定:pip install androguard。
2026-10-31 17:58:45
380
原创 第 1 期:APK 到底是个啥?别被后缀名骗了
如果你用 WinRAR 解压,改了个文件,再右键“添加到压缩包”,这个 APK 绝对装不上。如果你用工具只分析 classes.dex,会发现很多核心逻辑“凭空消失”了。工欲善其事,必先利其器。你可以现在就动手试一下:把你手头任何一个合法的测试 App(比如你自己写的 Demo,或者开源软件)的 .apk 后缀改成 .zip,双击就能用解压软件打开。我们后续所有的“逆向”、“反编译”,说白了就是把这个 ZIP 里的文件抽出来,按特定的格式去解析它。想看它,必须用专门的工具解析(下期教你怎么装工具)
2026-10-30 21:06:55
18
原创 别再每次手敲 ssh user@ip 了,用 SSH Config 给服务器起个“小名”
它就像本地电脑的“通讯录”,你可以给服务器起个“小名”,把所有繁琐的参数提前存好。解法:右键你的私钥文件 -> 属性 -> 安全 -> 高级 -> 禁用继承 -> 删除所有用户,只保留你自己的账户,并赋予“完全控制”权限。如果你有几台不同的机器(比如一台测试、一台生产、一台树莓派),那要记的 IP、端口、用户名、私钥路径就更多了,简直是在考验大脑的内存。解法:如果你觉得每次输密码烦,可以开启 ssh-agent 缓存,或者干脆生成一个空密码的私钥(但私钥文件一定要保管好)。
2026-10-28 00:48:24
123
原创 2G 内存跑全栈监控,为什么你的容器总在半夜被“暗杀”?
因为你的机器只有 2GB 内存,跑 5 个服务,一旦遇到某个时间段并发稍微高一点,或者数据库做一次大的查询,内存瞬间见底。如果你在 docker-compose.yml 里给容器设了 mem_limit: 256m,但没设 memswap_limit,默认情况下容器能用的 Swap 是物理限制的两倍。有了这 2GB 的 Swap,下次内存再逼近临界点,系统会悄悄把一部分冷数据(比如 Kuma 里几个月前的心跳数据)塞进硬盘里,而不是直接拔刀杀你的容器。容器没有报错,是被系统“亲手杀”了。
2026-10-28 00:45:20
770
原创 TB335FC(MT6835) GhostLock临时Root实践(二):执行与风险控制
声明:本文仅为在本人拥有设备上进行的个人技术验证记录,旨在分享特定固件版本下的实际表现,请勿用于任何非授权设备。操作未修改系统分区,重启后权限自动失效。内核漏洞操作存在死机、重启、数据丢失等风险,请提前备份并自行承担后果。临时 Root 可用于 su -c 执行命令、加载 KernelSU 模块、App 提权、修改部分内核参数等。临时 Root 重启失效,profile 可保存在 App 已保存配置中,重跑较方便。不同固件版本差异较大,本文参数仅对应上述系统与内核版本,请自行校验后再操作。
2026-10-26 20:13:38
2270
原创 TB335FC(MT6835) GhostLock临时Root实践(一):设备与profile提取
MTK 机型按官方 MEDIATEK.md 需要补充两个物理地址参数,可从官方固件的 boot.img 和 vendor_boot.img 通过官方提取器生成。结论:BL 未解锁、数据未清、未刷分区,通过 GhostLock 内核漏洞加载自制 profile,获得临时 uid=0,KernelSU LKM 可正常加载。系统:Android 15,TB335FC_CN_OPEN_USER_M1317.3_V_ZUXOS_1.1.10.522_ST_251110。CVE-2025-21479 不适用。
2026-10-26 20:11:56
2637
原创 网页一片白?Docker 跑 Nginx 读不到文件,403 Forbidden 排查实录
SELinux:如果你的云服务器开了 SELinux(虽然 Ubuntu 默认没有,但 CentOS 有),光改 rwx 权限没用,必须加 😒 或 :Z 标签。挂载路径写错:Docker 挂载如果是空目录,Nginx 会用自己的默认欢迎页顶替,导致你看到的是 Nginx 欢迎页,而不是你的大屏。Nginx 跨过门(挂载目录)去拿文件,发现文件夹大门紧锁,连看都不让看,直接甩个 403。宿主机的文件,是我用 ubuntu 账号建的,权限是 rw-r–r–。发现目录是 700,只有创建者能进。
2026-10-25 17:42:30
267
原创 2G 内存被谁吃了?一招调优 MariaDB,拯救你的小内存监控大屏
忘了设置 max_connections:Flask 代码一旦有连接泄漏,瞬间发起几百个连接,MariaDB 会为每个连接分配内存,瞬间把机器打爆。SSH 进去一查,dashboard 和 monitor 都好好的,唯独 db 容器一口气吃了 800 多 MB 内存,直接把服务器榨干了。预期输出:db 容器的内存占用从 800MiB 降到了 150MiB 左右。但我的服务器总共才 2G,它吞了 1G,其他租客(Flask、Kuma)连站脚的地方都没了,系统自然卡死。直接在容器里改配置:容器重启后配置全丢。
2026-10-25 17:41:41
80
原创 大屏突然 502?一次 Nginx Buffer 溢出引发的血案:upstream sent too big header
现在 Flask 塞过来一堆附件(用户登录的 Cookie、很长的 JWT Token、复杂的 CORS 头),麻袋撑爆了。Nginx 兜不住,直接把快递扔地上,大喊一声“502”。Nginx 手里拿了个固定大小的麻袋(Buffer),默认是 4K 大小。F12 网络面板里,502 消失,正常的 200 响应返回,Header 里的 Token 完整传递。本地不复现:本地开发环境通常不带复杂的 Cookie 或 SSO Token,导致本地永远测不出这个错,必须上生产。调大 Nginx 的麻袋。
2026-10-24 22:26:41
94
原创 2核2G 的 Flask 该起几个 Worker?别再用公式死记硬背了!
内存泄漏(Memory Leak):如果你的 Flask 代码写得不够严谨(比如全局变量存大数组),Worker 内存会越涨越高。建议加个 --max-requests 1000 参数,处理完 1000 个请求就让 Worker 重启一下,把内存强制清空。再加上 MariaDB(另一个大厨)和 Kuma(收银员),厨房(内存)瞬间挤爆,房东(系统)直接把厨师扔了出去。小内存机器,内存才是瓶颈,不是 CPU。2G 内存,系统基础跑掉 300M,MariaDB 吃掉 400M,Kuma 吃掉 200M。
2026-10-24 22:26:07
173
原创 获取的全是 172 开头的假 IP?Nginx 反代后,Flask 怎么才能拿到真实访客 IP?
remote_addr vs $proxy_add_x_forwarded_for:X-Real-IP 适合单层代理。我用的是 Nginx 反代 Flask 容器,request.remote_addr 拿到的全是 Docker 内网 IP,根本不是访客的真实公网 IP。如果有严格的安全需求,必须配合 Nginx 的 real_ip_module 模块处理。预期输出:Your Real IP: 你的4G公网IP(不再是 172 开头)。Nginx 说:“是我给的(172.18.0.x)”。
2026-10-23 18:36:35
91
原创 报数据库连不上?Docker Compose 启动顺序假象:depends_on 不是万能的!
老版本 Compose 不认:如果你的 docker compose 版本很老(V2 以下),可能不支持 condition: service_healthy,必须升级 compose 插件。健康检查命令写错:test 里的命令如果没有指定 CMD 或者写错,容器永远 unhealthy,导致后端永远起不来。不写超时退出:如果不配合 restart: always(重启策略),一旦后端起太快报错退出,它就不会自己重试了。dashboard 跑得飞快,起跑后直接敲门,发现 db 还没弄好,立刻报错退出。
2026-10-23 18:35:19
199
原创 改了 IP 就报 502?Nginx 缓存 DNS 的隐蔽大坑,光 reload 没用!
明明容器已经起来了,curl 127.0.0.1:5000 也是通的,但 Nginx 就是连不上。原路径丢失:使用变量 set $backend 后,请求的路径如果带参数,有时会被截断,需要在 proxy_pass 后面加上 $request_uri。启动时,他看了一眼电话本(DNS),把后端地址(比如 172.18.0.5)抄在脑子里。下次再重建容器(IP 变了),最多等 10 秒,大屏自动恢复,不用再手动重启 Nginx。你把后端容器重建了,相当于换了个人,IP 变成了 172.18.0.6。
2026-10-22 19:21:25
196
原创 Nginx 报错 Too many open files?一招 ulimit 解决高并发下的文件句柄耗尽
只改 limits.conf 没用:如果你是用 systemctl restart nginx 启动的,systemd 会覆盖 limits.conf。必须改 /etc/systemd/system.conf。reload 不生效:改 ulimit 必须 restart,光 nginx -s reload 没用,因为进程 PID 没变,号牌数量不会重新分配。Nginx 既要接访客(连接),又要看日志(文件),还要连 Flask(代理),还得转发静态资源。访问大屏,502 消失,系统顶住了并发。
2026-10-22 19:20:43
151
原创 Nginx 代理非标端口 HTTPS 踩坑
用非标端口 8443。Certbot 续期:非标端口(如 8443)Certbot 默认测 80 端口。必须用 --http-01-port 8443 或改用手动 DNS 验证。小学生版:Nginx 以为是标准 443 门。Nginx 告诉浏览器“去 443 门”,浏览器敲 8443 门,死循环。根本原因:Nginx 传给后端的 Host 头没带端口。Flask 静态资源路径:重定向修复后,如果 CSS 丢失,检查前端代码是不是写死了 /static/。host 不带端口,$http_host 带端口。
2026-10-21 16:44:14
199
原创 Kuma SQLite 备份坑
直接 cp kuma.db,没带上 -wal 和 -shm 文件。起容器,Kuma 打不开。直接备份 Volume:如果停服时间允许,用 docker compose stop monitor,备份整个 /app/data 目录,再 start。忘记清理临时文件:.backup 会在容器里生成新文件,记得在容器内 rm,否则容器磁盘爆满。版本兼容:恢复时,新 Kuma 版本的 DB schema 可能升级,备份只能同级恢复。必须用 SQLite 官方备份命令,或者使用 Docker 卷停服备份。
2026-10-21 16:44:03
170
原创 2G 内存跑 5 个容器频频 OOM?一招 Swap 抢救你的 2核2G 小破服务器
这时候备份脚本(另一个租客)也想进来,仓库塞不下了,房东(Linux 系统)一看急眼了,直接把一个正在干活的租客扔出去(OOM Killer,Out of Memory),导致服务崩溃。再次跑备份脚本,系统不卡了,用 vmstat 1 看,si 和 so(Swap 换入换出率)保持在 0 或者个位数,说明物理内存稳住了。把 Swap 放在机械硬盘上:虽然我们云服务器大概率是云盘,但如果是本地机械盘,Swap 过于频繁会导致系统巨卡,Swap 只是救命药,不是健胃消食片。
2026-10-20 16:10:19
159
原创 容器日志“穿越”了?一次 Docker 时区不一致引发的监控时间错乱惨案
小学生版解释:宿主机(你的云服务器)戴的是“北京时间”的手表,但 dashboard 容器是个老外,它默认戴的是“伦敦时间”(UTC)。它去写数据库的时候,写的是伦敦时间,导致整个数据时间线全乱了。Python 代码里的时间处理:如果代码里用了 datetime.now(),建议存数据库时统一存 UTC,前端展示时再转回东八区,避免跨时区部署的麻烦。只改宿主机没改容器:很多人用 timedatectl 把宿主机改成了北京时间,就以为容器也同步了,其实容器还在自己玩。宿主机的时间是 CST(东八区)。
2026-10-20 16:09:45
216
原创 别再背那些又长又臭的 Docker 命令了,用 Makefile 一键搞定
如果你碰巧在服务器上建了一个叫 backup 的文件夹,你再敲 make backup,Make 就会告诉你:“这个文件已经是最新的了,不需要执行”。在跟 docker-compose.yml 同级的目录下,新建一个文件名就叫 Makefile 的文件(注意首字母大写,没有后缀名)。解法:永远在文件开头加上 .PHONY: 你的命令名,告诉 Make“无视同名文件,强制当成命令跑”。Makefile 的语法极其死板:命令前面必须是一个真正的 Tab 制表符,绝对不能是 4 个空格。
2026-10-19 16:40:34
156
原创 别再裸奔了!用 Nginx 安全头给你的监控大屏穿上防弹衣
Strict-Transport-Security 效果极好,但你一旦给浏览器下发了这个头,在 max-age 设定的时间内(比如一年),浏览器哪怕访问 http:// 也会自动强行转成 https://。如果你的后端返回了 4xx 或 5xx(比如接口报错了),安全头就丢了。但浏览器拿到包裹后,里面如果有恶意代码(XSS),或者被别人偷偷嵌到别的网页里(点击劫持),浏览器默认是不知道该怎么防御的。解法:第一次配 HSTS 时,max-age 先设小一点,比如 300(5分钟),确认稳定了再改大。
2026-10-19 16:38:42
100
原创 Docker Compose 多环境管理:别把开发配置带进生产环境
很多人图省事,直接复制一份 docker-compose.yml 改个名,变成 docker-compose.dev.yml 和 docker-compose.prod.yml。如果你在服务器上直接敲了 docker compose up -d,而没有加 -f 指定生产配置文件,Docker 会自动加载那个 override.yml。如果在基础文件里写了 ports: [“80:80”],在 override 里写了 ports: [“8080:80”],最终结果只有 8080:80,80 端口不会保留。
2026-10-18 19:52:25
172
原创 从裸机到全栈监控:我写了个 5 分钟一键初始化脚本
这在安装软件时很容易卡住——比如你脚本里写 docker --version 检查是否安装,如果没装,这条命令返回非 0,脚本直接崩了,后面的安装逻辑根本没执行。如果是用脚本自动跑的,一旦卡在这个界面,整个脚本就死锁了。把脑子里的“步骤列表”转化为“代码”,既能保证每次重装环境的一致性,又能省下喝杯咖啡的时间。解法:生成完立刻 chmod 600 .env,并且在使用 docker compose 前,确保你的脚本没把它拷到别的地方。重装系统后,把脚本传上去(或者用 curl 直接拉),跑一下:。
2026-10-18 19:00:59
150
原创 每次开机手动检查 6 样东西?我写了个 2 秒自检脚本
date -d “$END” +%s 在 Ubuntu 上是 GNU date 的扩展,macOS 不认。自检脚本应该挂在登录提示里,但不要在登录时自动执行。如果全都用红色,大脑会脱敏,反而忽略真正的危险。服务器上有几个容器、多个监听端口、HTTPS 入口、SSL 证书、每日备份。不是不知道要检查什么,而是没有一个统一的"体检清单"。想到什么查什么,容易遗漏,也不便于对比。这就好比去医院体检,医生不会每次临时想查什么,而是有一张固定的体检单,一项一项过。结构设计:6 个检查节,每节独立,不互相影响。
2026-10-17 11:26:30
217
原创 服务器时间错乱:一个让监控和定时任务全乱套的隐藏地雷
CST 这个缩写,在美国代表中部时间(UTC-6),在中国代表北京时间(UTC+8)。而且你之前配的“每天凌晨 3 点备份”的 cron 任务,查看日志发现它是在下午 3 点才跑的。定时任务(Crontab):你写 0 3 * * * 以为凌晨 3 点跑,其实是 UTC 的 3 点,也就是北京时间上午 11 点跑。这是 Linux 云服务器最常见的一个坑:默认时区是 UTC(协调世界时),而你人在中国,用的是 CST(北京时间,UTC+8)。如果输出是 SYSTEM,说明它跟着系统走了(这是对的)。
2026-10-17 11:26:11
956
原创 备份和服务器在同一台机器上,等于没备份
setfacl -m u:backup_reader:x 只给"穿过"权限,不给"列目录"。Windows 写密码文件时如果用 Set-Content,会多一个 \r,GPG 说"密码错误"。服务器每天 03:00 自动备份,产出业务包 + GPG 加密的 secrets 包。ACL 是精确到"某一个人"的。只设"每天 4:00",但电脑经常关机。加一个"登录后 5 分钟"触发,双保险。这是备份的经典盲点:同机备份只能防"误删文件",不能防"整机丢失"。为什么是"电脑拉"而不是"服务器推"
2026-10-16 18:38:11
106
原创 别再 chmod 777 了,用 ACL 给它开一扇窗
目录是 /home/user/backups/,但 /home/user 的权限是 drwxr-x—(只有 user 和 user 组能进)。需要一个专用备份用户 backup_reader,能读到 /home/user/backups/ 目录下的文件。如果之后执行 chmod 700 /home/user,可能会覆盖掉 ACL。user:backup_reader:–x — 只给 x(穿过),不给 r(列目录)先 apt install acl,一条命令的事,但不知道就会卡住。
2026-10-16 18:38:00
175
原创 监控跑了一个月,出事时微信一声没响
服务器上跑着 Uptime Kuma,监控 3 个服务,接了 ServerChan 微信通知。界面只能看单个监控,monitor_notification 表能一眼看出全局绑定情况。notification.active=1 只表示渠道本身开着,不代表任何监控在用它。然后在 Kuma 界面点 Test Notification,微信立刻收到测试消息。建完监控就以为完事了,是最大的错觉。通知渠道建好了,监控也建好了,但两者从来没连上。坑 3:排查监控问题,SQLite 比界面更直接。
2026-10-15 18:55:25
181
原创 密码明明一样,为什么 GPG 说“错的“?
服务器上用 GPG 加密了一个备份包,密码存在 /root/.backup_pass。记事本里两个文件长得一模一样,只有看字节才知道差一个 \r。跨平台处理密钥文件,永远用 Format-Hex / xxd 确认。Windows 的 Set-Content 默认在每行末尾加 \r\n,GPG 把那个 \r 也当成密码的一部分了。从密码管理器复制时,有的会带上末尾换行。坑 2:Linux 的 echo 也会加换行。密码是从服务器抄过来的,一个字符没差。坑 3:密码管理器里存的值可能带换行。
2026-10-15 18:54:52
159
原创 Nginx 限流实战:防 CC 攻击和爬虫的四个配置
如果前面挂了 Cloudflare / CDN,Nginx 拿到的 $remote_addr 是 CDN 的 IP,不是真实用户 IP。用 $binary_remote_addr 时,它已经是被 real_ip 替换后的真实 IP。坑 3:CDN / 反代后,$binary_remote_addr 是 CDN 的 IP。如果攻击者用大量代理 IP(比如僵尸网络),状态表满了之后,新 IP 无法被限流。调优方法:先配宽松一点,观察日志,看正常用户的峰值是多少,再往下压。
2026-10-14 18:57:22
120
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅