优雅地管理SSL证书及其关联服务
我的服务器上开着一堆服务,其中有一些需要用到SSL证书,例如Nginx及前面刚刚部署的邮件服务。我的SSL证书是通过certbot向Let’s Encrypt申请的,证书有效期为90天,也就是说每隔80多天就得更新一下证书。
动机在证书更新后,自然需要将所有用到证书的服务reload一下,以加载新的证书,通常我会写一条crontab作业来干这件事。之前我只有一台服务器A跑Nginx服务的时候,这样感觉还比较舒服,而现在情况变得更加复杂了:
这两年我都在维护我们实验室主办的学术会议的官网(规模不大,因此把官网部署在我的服务器上完全没问题),所以需要同时维护两个域名的证书。另外,我现在还同时维护着另一台B服务器——两台服务器上的服务共享着同一个域名证书,所以需要在A服务器上的证书更新时同步到B服务器上,并在B服务器上reload所有用到证书的服务。
于是原先的方法感觉就不太优雅了。正巧这两天iBug大佬发布了一篇文章,介绍了一种通过systemd来reload一些服务的方法:
引用站外地址,不保证站点的可用性和安全性
...
使用Nginx反向代理DoH服务
DoH(DNS over Https)是一种通过HTTPS来进行DNS解析的协议,它使用HTTPS协议加密DoH客户端和基于DoH的DNS解析程序之间的数据,防止中间人对DNS数据的窃听和操纵,从而提高客户端隐私和安全性。
国内外都有一些服务商提供公共的DoH服务,不过由于一些众所周知的原因,我会更倾向于使用国外服务商的DoH,随便列举几条比较知名的:
OpenDNS: https://doh.opendns.com/dns-query
CloudFlare: https://cloudflare-dns.com/dns-query
dns.sb: https://doh.dns.sb/dns-query
Google: https://dns.google/resolve
IBM Quad9: https://dns.quad9.net:5053/dns-query
同样的,由于一些原因,我们访问这些服务会有些困难。考虑到我有一台位于海外的云服务器,因此可以考虑通过Nginx做一个反向代理,来间接访问这些服务。下面是我配置的反向代理:
upstream google{
...
自部署邮箱接收不到某些邮件的原因排查
用上自部署邮箱后,我就将一些社交平台的绑定邮箱换成了自己的新邮箱。然而某些平台的验证邮件却始终无法收到——即使在垃圾邮件箱。
Twitter
查看日志后发现以下内容:
Mar 24 03:13:07 mail postfix/smtpd[27111]: connect from spruce-goose-al.twitter.com[199.59.150.81]
Mar 24 03:13:07 mail postfix/smtpd[27111]: Anonymous TLS connection established from spruce-goose-al.twitter.com[199.59.150.81]: TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)
Mar 24 03:13:08 mail postfix/smtpd[27111]: CD556EB3A9: client=spruce-goose-al.twitter.com[199.59 ...
自建docker-mailserver邮件服务器
大约两年前我就想过整一个自己域名的邮件服务,这样就可以随意注册邮箱账号了,而且看上去很帅。然而这件事却一拖再拖,到今天总算是整上了,于是就在这里记录一下整的过程。
我所使用的服务器是腾讯云的轻量应用服务器,地域在新加坡,配置是最low的2核2G入门型,由于配置比较低还跑了一些其他的服务,我只能放弃一些诸如mailcow这样的选项,最后选择的是比较轻量的docker-mailserver,不开启反病毒功能的前提下内存占用比较少。
一些约定为了方便描述,本文中出现的下面内容均为示例,需要替换为实际值。
一级域名:example.com
邮件服务器域名:mail.example.com
主机IP地址:1.2.3.4
邮件用户名:admin
邮件用户密码:password
涉及到的所有DNS解析,均只写主机名,而省略一级域名example.com。
开启端口邮件服务器需要用到的端口非常多,首先需要确保没有其他进程占用这些端口,并将它们打开:
25:SMTP(显式TLS端口,不可用于身份认证)
143:IMAP4(显式TLS端口)
465:ESMTP(隐式TLS端口)
587:ESMTP( ...
Gitalk发起Oauth时无法完成跨域请求的问题
我的博客接入Gitalk之后,经常会遇到Gitalk登录失败的问题,表现为Gitalk组件长时间转圈加载不出来,一段时间后渲染出Network Error等字样。
经过研究,发现是因为Gitalk在发起跨域请求时,其默认的代理出了问题,详情可见此issue。
https://cors-anywhere.azm.workers.dev/https://github.com/login/oauth/access_token
上面这个跨域代理的域名已经被墙了,在没有科学上网环境或网络环境差的时候就会寄。
于是我们可以自己整一个代理,方案有几种,如果没有云服务器,可以找一些免费的托管平台来搞一个代理,例如Vercel,可参考这篇文章
不过实际体验了一下,我发现vercel的域名好像也被墙了(DNS污染)。。。
考虑到我的网站是用Nginx部署在自己的云服务器上的,并且我的云服务器在境外,可以直连GitHub,因此我采用了另一种更加方便的方案,即用Nginx来转发跨域请求(参考自这篇文章)。
在网站的Nginx配置下 ...
博客接入Gitalk评论系统
2024-04-21 更新: 基于GitHub Issue的评论系统在嵌套评论时叠金字塔的行为太丑了,于是我已经将评论系统换成了基于GitHub Dissussion的Giscus。
自从开始写这个博客以来,我就嫌博客主题自带的评论系统太丑,又懒得大改CSS,于是我的博客一直没有开启评论功能。
但忽然觉得不开评论区好像过于冷清(虽然开了也不怎么会有人评论),然而我又不是很希望访客的评论占用数据库,因此我打算看看能不能整一个Serverless的评论系统。
最近接触了下GitHub REST API,于是想了一下,觉得既然GitHub的API那么方便,那为什么不试试把GitHub的Issue系统渲染到自己的网页上当评论系统用呢?(之前听说过有人拿GitHub当云存储的,简直就是人才)
考虑到受众群体应该不会有人没有GitHub账号,感觉这个想法很不错,然而当我研究的如火如荼之时,突然在网上搜到了别人已经造好的轮子:Gitalk。草,果然。
那何不拿来主义?毕竟我也比较讨厌写前端代码。于是我啪就整起来了,很快啊!就把Gittalk接入了一下,说实话这个评论系统的前端还挺不错的,基本契合我 ...
一个随Star数动态变化的GitHub仓库
几年前曾看到过@iBug大佬的一个GitHub仓库,这个仓库的名字以及描述会实时显示当前的Star数量,令当时的我觉得非常有意思,不过那会我并没有去研究原理。几年过去了,却不知昨天为啥突然想到,于是读了一下大佬的文章,试着复现了一下。
我复现的仓库链接如下:
引用站外地址,不保证站点的可用性和安全性
This Repo Has 0 Stars
GitHub
朋友们可以进去点个star看看效果~(没想到我第一次骗star竟是为这)
项目很简单,但其背后的原理覆盖了一些我之前没有接触过的东西,例如GitHub REST API、Webhook(这个倒是在做telegram bot的时候接触过)、AWS Lambda等。如果能熟练利用,感觉会是个很高效、很方便的辅助工具。由于iBug大佬的文章省略了好多「有手就行」但我不会的内容,所以在过程中踩了一些坑,因此我来水篇文章,更详细地记录一下 ...
使用Cloudflare为网站部署免费的防御措施
我决定给我的博客套一层Cloudflare。
“不是,你网站那点访问量套个der的cf啊?”
“我之前也觉得没必要,但为什么我这么小的站都有人来搞事啊。。。看来还是有必要上一下防了。反正Cloudflare有free plan,那个够好用了,不用白不用。”
发生肾磨石了?朋友们好啊,我是本博客的博主。
刚才有个朋友问我,你的个人博客为肾磨访问不了了,我说怎么回事?给我发了几张服务器无响应的截图,我一看Nginx日志,哦!源赖氏港才,有两个IP地址,非常可疑,一个请求90多万次,一个请求80多万次。
我一看这请求量!啊…我的服务器CPU占用率直线上升,到了100%,诶…服务器扛不住了,我说这是怎么回事。我说你这个请求来得太频繁了,不能这么搞,他不理我。我说小朋友你看这个CPU负载,他看都不看。他说你这也没什么办法。我说我这个有办法,得用防火墙拦截全部流量,传统运维是讲防御的,四两拨千斤,二百多万的每分钟请求数都敌不过我这一条防火墙规则啊…哈!他非得继续攻击,我说可以。
诶…我一说他脚本啪就跑起来了,很快啊!然后上来就是,一个拒绝服务,一个CC攻击,一个API滥用!
我全部防出去了,防 ...
重塑密码管理体系——Bitwarden服务端自部署
经常问我借账号的朋友都知道,我这个人记性不好,也因此,我所有平台的密码都长的大同小异(基本都是由同一个字符串通过变换字母大小写、截取子串,或者添加一两个特殊符号得来的)。
使用相似密码的坏处像我这样在各平台用相似度极高的密码,虽然方便了记忆,但后果也很严重:某些不负责任的平台会用明文存储用户密码,然后还tm泄漏了。。。这就造成了我们的常用密码被添加到了字典里,黑客便可通过这些字典来轻松破解我们其他平台的密码(虽然并没有什么值得被黑客盯上的东西)。
因此,将各种平台的密码设成互相毫无关联的随机字符串才是妥当的方案,这种安全的密码设置画风应该是下面这样的:
QQ:Tx8RYq%*fStp3r
微信:D6MuyvxS!6e$Zc
Apple账号:&Nm4PvAdL*cH#v
科大邮箱:vSP6nC$QZrh3z%
…
然而如果把各平台的密码都设成这种鸟样,安全性虽然能保证了,但毕竟我的脑子不是硬盘,肯定是记不住的,所以很自然地就需要一款能为我们管理各平台的密码的软件。拥有过目不忘能力的同学到了这就已经可以不用往下看了。
这种软件需要至少满足下面的条件:
安全可靠:能够为我生成强 ...
“The Password Game”攻略
这两天偶然发现了一个有点意思的“小游戏”,名为“The Password Game”,传送门如下:
引用站外地址,不保证站点的可用性和安全性
The Password Game
大概是给你一堆层层递进又互相强耦合的规则,让你设置一个符合所有规则的密码。我第一次通关花了几个小时,而通关两次以后,已经摸透了通关的方法,因此来记录一下。
由于其中包含Google Map和Youtube等内容,故科学上网是通关的必要条件。
本文所有的代码已集成到Greasyfork:
引用站外地址,不保证站点的可用性和安全性
Password Game Assistant
Greasyfork
小游戏共有 ...
Hackergame 2023题解(三)
本文是Hackergame 2023题解的第三部分。
🪐 流式星球查看题面茫茫星系间,文明被分为不同的等级。每一个文明中都蕴藏了一种古老的力量 —— flag,被认为是其智慧的象征。
你在探索的过程中意外进入了一个封闭空间。这是一个由神秘的流式星人控制着的星球。星球的中心竖立着一个巨大的三角形任务牌,上面刻着密文和挑战。
流式星人用流式数据交流,比如对于视频来说,他们不需要同时纵览整个画面,而是直接使用像素流。为了方便理解,你把这个过程写成了一个 Python 脚本(见附件),flag 就藏在这个视频(见附件)中。尽管最后丢掉了一部分数据,你能把 flag 还原出来吗?
Python脚本
视频文件
这题的附件给出了将一个mp4文件转换为video.bin的过程。其逻辑是将视频的每一帧抽取出来存入一个array,最后对array做了一个flattern操作并去掉了末尾随机0-99个字符,相当于按顺序存放了视频的每一个像素(仅仅删掉了最后的不到100个)。
用numpy读取video.bin,得到它的长度是135146688,然后我遍历了0-99,加上长度以后送去质因数分解,选出3的倍 ...
Hackergame 2023题解(二)
本文是Hackergame 2023题解的第二部分。
JSON ⊂ YAML?查看题面你知道吗?Hackergame 出题时,每道题都需要出题人用 YAML 格式写下题目的关键信息。然而,每年总有一些出题人在编写 YAML 文件时被复杂的语法规则弄得头疼不已。
这天小 Z 又找到小 W 说:「我昨天写 YAML 时,又花了半天研究 YAML 的规范,YAML 好难啊!」
小 W 惊讶道:「怎么会有人不会写 YAML 呢?只要你会写 JSON 就会写 YAML 呀,因为任何合法的 JSON 本身就是合法的 YAML。」
小 Z 听闻这番言论后当场表示怀疑,立刻说出了一个字符串,JSON 和 YAML 解析出的含义存在差异。小 W 研究了一番才发现,这是因为很多主流的 YAML 库仍然是 YAML 1.1 的,它没有这个性质。他不得不承认:「好吧,这个性质只适用于 YAML 1.2。」
小 Z 笑了:「别提 YAML 1.2 了,它遇到合法的 JSON 都有可能报错。」
本题附件
JSON ⊄ YAML 1.1第一问需要找到一个JSON字符串,使其被json解析的结果与被yaml1.1解 ...
Hackergame 2023题解(一)
本文是Hackergame 2023题解的第一部分。
Hackergame 启动查看题面大声喊出 Hackergame 启动,开始今年的冒险!
解法1:直接点击提交,发现URL多出参数?similarity=,手动补成?similarity=114514再访问即可。
解法2:多喊几遍Hackergame 启动!让相似度达到100%。
flag{We1ComE-70-hACkEr9aME-4nD-enjoY-h4Ck!nG-z0Z3}
虽然不玩原神,但还是被洗脑了。。。
猫咪小测查看题面
想要借阅世界图书出版公司出版的《A Classical Introduction To Modern Number Theory 2nd ed.》,应当前往中国科学技术大学西区图书馆的哪一层?(30 分)
提示:是一个非负整数。
今年 arXiv 网站的天体物理版块上有人发表了一篇关于「可观测宇宙中的鸡的密度上限」的论文,请问论文中作者计算出的鸡密度函数的上限为 10 的多少次方每立方秒差距?(30 分)
提示:是一个非负整数。
为了支持 TCP BBR 拥塞控制算法,在编译 Linu ...
Hackergame 2023题解(零)
又是一届快乐的Hackergame,今年神仙附体,拿到校内rank2,总排名rank13,是自19年开始玩Hackergame以来的最好成绩,可喜可贺可喜可贺!
引用站外地址,不保证站点的可用性和安全性
本次比赛的官方存档
GitHub
题解下面是本次比赛解出题目的题解:
Hackergame 2023题解(一)
Hackergame 启动、猫咪小测、更深更暗、旅行照片 3.0、赛博井字棋、奶奶的睡前 flag 故事、组委会模拟器、虫
Hackergame 2023题解(二)
JSON ⊂ YAML?、Git? Git!、HTTP 集邮册、Docker for Everyone、惜字如金 2.0、🪐 高频率星球、🪐 小型大语言模型星球
Hackergame 2023题解(三)
🪐 流式星球、🪐 低带宽星球(小试牛刀)、Komm, süsser Flag ...
PKU GeekGame 3rd题解(二)
本文是本次PKU GeekGame题解的第二部分。
简单的打字稿查看题面
尊敬的用户,您好!
我们深刻认识到,大力推广使用TypeScript这门优秀的编程语言,将对我国社会主义现代化建设产生深远的正面影响。我们梳理了TypeScript与现代化建设的结合点,并进行了详细阐述,请您评价。
…
我们呼吁北大等高校里富有社会责任感的青年学子,在学习TypeScript技能的同时,将之用于服务国家发展大局。让我们继续在信息技术进步的道路上阔步前行,以TypeScript为工具,建设一个我们夢想中的社会主义现代化强国,以人民为中心,实现中华民族伟大复兴!
显然,题面要是让 Claude 生成,就会变成上面那个鬼样。
不过前人说,TypeScript 确实很安全,至少对于类型来说更是如此。那么若我把 Flag 放在类型里,阁下又将如何应对?
type flag1 = 'flag{...}'
type flag2 = object | { new (): { v: () => (a: (a: unknown, b: { 'flag{.. ...
PKU GeekGame 3rd题解(一)
本文是本次PKU GeekGame题解的第一部分。
一眼盯帧本题附件从没见过如此简单直接的签到题,只要眼睛够快,看一遍动图就能算出flag。
拿到题,搜个在线GIF逐帧查看器,然后把字符抄一下,发现前四个字母是synt,就搜了一个在线rot13解码网站,解出flag。但动作慢了,只抢了8血。
小北问答!!!!!这次的问答题属实有点难顶,提交居然有一小时冷却时间。。。就算防爆破,冷却时间设个一分钟也差不多了,一小时的话就,真的很急急急!
题目如下:查看题面
在北京大学(校级)高性能计算平台中,什么命令可以提交一个非交互式任务?答案格式:^[a-z]+$
根据 GPL 许可证的要求,基于 Linux 二次开发的操作系统内核必须开源。例如小米公司开源了 Redmi K60 Ultra 手机的内核。其内核版本号是?答案格式: ^\d+.\d+.\d+$
每款苹果产品都有一个内部的识别名称(Identifier),例如初代 iPhone 是 iPhone1,1。那么 Apple Watch Series 8(蜂窝版本,41mm 尺寸)是什么?答案格式: ^[a-zA-Z]+\d+,\d+$
本 ...
PKU GeekGame 3rd题解(零)
在科研的压力下,一年一度的GeekGame成了一个消遣放松的绝好借口不过为什么感觉打这个比赛比搞科研更累?。
今年的比赛顺利取得总排名36/1012(通过签到题的人数),并且在一周的比赛时间内又学到了不少一年前可能学过但又忘了的东西,算是非常有收获。按老规矩,继续写篇题解记录一下本菜狗的解题过程。
引用站外地址,不保证站点的可用性和安全性
本次比赛的官方存档
GitHub
题解
PKU GeekGame 3rd题解(一)
一眼盯帧、小北问答!!!!!、Z 公司的服务器、基本功、Emoji Wordle、第三新XSS
PKU GeekGame 3rd题解(二)
简单的打字稿(Super Easy)、汉化绿色版免费下载、初学 C 语言(Flag 1)、绝妙的多项式、关键词过滤喵,谢谢喵(字数统计喵)、小章鱼的曲奇、华维码(华维码 · 特难)
总结本次比赛比去年学到了更多的内 ...
从零开始的麻将AI论文复现(二)
本来想省略掉所有麻将游戏的实现细节的,但后来发现强化学习算法需要一个游戏环境,因此完整实现一整套麻将游戏的流程也属于论文复现的一部分,还是有必要对游戏实现时遇到的一些技术细节进行解释。
如何判定和牌立直麻将共有三种和牌形,分别是:
面子手:m * AAA + (4-m) * ABC + DD
七对:7个互不相同的对子
国士无双:所有幺九牌各一张,并且其中之一成对子
七对和国士无双比较容易判定,但面子手的和牌形涉及到刻子、顺子、雀头的不同拆分,判定方法会比较麻烦。最容易想到的方法就是用dfs遍历所有的拆分可能性,如果能拆分完全,则满足面子手形状。曾经我也实现过这个算法,但dfs的问题在于时间复杂度不是很能接受。
考虑一个用程序实现的麻将游戏,这个程序在什么时候会需要进行和牌的判定?实际上,在每一个玩家摸完牌之后,程序都需要为该玩家判定一次和牌;另外,当玩家切出一张牌时,程序都需要为其他三位玩家各判定一次和牌。因此,在一局20巡目左右的麻将游戏中,程序大约共需要进行至少20 * 4=80次和牌判定。另外,程序还需要为玩家判定一手牌是否听牌、是否可以立直等,显然这两者比和牌判定更为复杂。 ...
从零开始的麻将AI论文复现(一)
这篇文章,我来介绍一下我对麻将局面信息的特征编码方法。
首先,通过阅读论文,我们了解到Suphx在「弃牌模型」和「立直模型」中使用了通道多达838的特征,而「鸣牌模型」用到的特征更是多了120个通道。文中给出了一些比较基本的特征的编码方法,但对于这多达838个通道都是如何编码来的并未详细说明(其实是直接没说),不过,我们完全可以先做一个简化版的出来,日后再慢慢增加特征。
手牌编码论文的图片已经很形象地说明了手牌的编码方法。该方法将手牌编码为4通道的34维向量,即形状为(4,34)的矩阵。首先将34种牌编码为0-33,当玩家手牌中拥有X张Y(0≤Y≤33)的时候,就将该矩阵第Y列的前X个元素置为1。
为了编码的方便,我们可以为每个Agent维护一个手牌计数器,然后通过下面的函数即可生成编码:
def get_hand_tile_feature(self, counter):
"""
自家手牌
:param counter: Counter
:return: (4, 34)
"""
feature = np.zeros(shape=(4, ...
从零开始的麻将AI论文复现(零)
前段时间,博主突然开始沉迷偶尔玩玩立直麻将,受自己“职业病”的影响,遂想着能不能搞个AI出来帮我上段。
先找找有没有现成的算法。上网一搜,发现果然早有不少麻将AI的算法诞生了,比如东京大学开发的「爆打」、由Dwango发布的「NAGA25」、由MSRA开发的「Suphx」等。看了一圈,决定试着复现一下「Suphx」。
论文简介论文传送门如下:
引用站外地址,不保证站点的可用性和安全性
Suphx: Mastering Mahjong with Deep Reinforcement Learning
arXiv
如论文所说,该算法仅在监督学习下就能达到人类顶级水平,而在self-play以及reinforcement learning算法的加持下,Suphx能够达到特上房的最高段位十段,其稳定段位更是能达到8.7段,远超人类高手的稳定段位:7.4段。
Suphx并没有开源代码,因此唯一 ...