阅读视图

发现新文章,点击刷新页面。
🔲 ☆

Cusdis - 轻量、保护隐私、开源的 Disqus 评论系统替代方案

由于之前将博客全静态化了导致评论无法使用,原本是不打算做的,但是还是又挺多朋友通过各种各样的渠道联系我交流问题,故打算解决一下这个问题,方便后续交流。

我的解决方案是能自建就自建,无法自建的基本上就不考虑了。Disqus 不能自建,加之实际使用起来效果并不理想,隐私问题,还有界面不太喜欢就直接被我 Pass 掉了。

相交于 Disqus,Commento++也是不错的解决方案,但是界面不太喜欢,以及不够轻量,故没有选择,综合来考虑来看,Cusdis是非常不错的解决方案,足够轻量、支持自建、UI简洁,致使我最终选择了 Cusdis。

此处介绍两种方式 Docker、手工部署 Cusdis,均基于宝塔面板。


项目介绍

项目地址:Cusdis

Cusdis是Disqus的开源、轻量级(约5kb gzip)、隐私友好的绝佳替代品,主要用于纯静态化网站。

Cusdis 并非旨在成为 Disqus 的完整替代品。它的目的是为小型网站(例如您的静态博客)实现一个极简主义和可嵌入的评论系统。

官方文档:Cusdis Docs

特性

  • Cusdis 是开源的并且可以自我托管。因此,您拥有自己的数据。
  • SDK 是轻量级的(~5kb gzipped)。
  • Cusdis 不需要您的用户登录即可发表评论。
  • Cusdis 根本不使用 cookie。

缺点:

  • Cusdis 正处于其开发的早期阶段。
  • 没有垃圾邮件过滤器,因此,您必须手动审核您的评论部分,并且在您批准之前不会显示评论。

其UI简洁、支持自托管、支持邮件推送,在邮件内即可进行批准以及回复是我比较看重的功能。


环境配置

由于 Cusdis 基于Node.js 开发,采用 SQLite 或 MySQL 或 Postgresql 数据库存储数据,所以配置要求如下:

  • 系统上需要安装 Node.js 和 yarn
  • 服务器上安装了 MySQL 或 Postgresql

本文基于宝塔面板,使用 SQLite 进行安装

安装配置 Node.js

如您已安装 Node.js 和yarn 并且配置成功,则此步可以跳过。

安装 Node.js 命令如下

1
2
3
4
5
6
cd /www/server/nodejs
#国外服务器选择
wget https://nodejs.org/dist/v14.15.0/node-v14.15.0-linux-x64.tar.gz
#国内服务器选择
wget https://registry.npmmirror.com/-/binary/node/v14.15.0/node-v14.15.0-linux-x64.tar.gz
tar -zvxf node-v14.15.0-linux-x64.tar.gz

设置 Node.js 全局变量:

在宝塔面板打开 /etc/profile 文件,将以下配置输入文件最后面,并保存

1
2
export NODE_HOME=/www/server/nodejs/node-v14.15.0-linux-x64
export PATH=$NODE_HOME/bin:$PATH

输入以下命令用于重载全局配置。

1
source /etc/profile

输入 node -v 和 npm -v 返回以下信息即配置完成

img配置成功

安装 yarn

1
npm install -g yarn

查看版本信息,如遇 yarn:未找到命令,请看:《NodeJS 和 npm 配置全局变量

国内服务器此步骤由于 Node.js 没有大陆节点,速度较慢。请耐心等待

千万不要使用淘宝的 registry 镜像源!!!!!!!!

否则安装依赖会出错!!!!!!!!

部署 Cusdis

此处介绍两种方式部署,手动部署与使用Dokcer

手动部署

一、克隆仓库

1
2
cd /www/wwwroot
git clone https://github.com/djyde/cusdis.git

img

二、安装 Cusdis 所需依赖

国内服务器此步骤由于 Node.js 没有大陆节点,速度较慢。请耐心等待

千万不要使用淘宝的 registry 镜像源!!!!!!!!

否则安装依赖会出错!!!!!!!!

1
2
cd cusdis
yarn install

img

三、配置 .env 文件

在 cusdis 文件夹中新建一个名为 .env 的文件

img

文件具体配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
USERNAME=admin
PASSWORD=password
JWT_SECRET=ofcourseistillloveyou
NEXTAUTH_URL=http://IP_ADDRESS_OR_DOMAIN
HOST=http://IP_ADDRESS_OR_DOMAIN
DB_TYPE=sqlite
DB_URL=file:./data.db
#以下配置为 EMAIL 配置 可选
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_SECURE=true
SMTP_USER=your gmail email
SMTP_PASSWORD=<app password>
SMTP_SENDER=your gmail email

其中

为用户名
1
2
3
4
5
6
7
8
9
10
PASSWORD 为密码
JWT_SECRET 为 JWT 令牌
NEXTAUTH_URL 与 HOST 需要填写项目所用的域名/IP
DB_TYPE、DB_URL 为 数据库类型、数据地址
SMTP_HOST 为 SMTP 主机
SMTP_USER 为 SMTP 用户名
SMTP_PASSWORD 为 SMTP 密码
SMTP_SENDER 为发件人电子邮件地址
SMTP_PORT 为 SMTP 端口 默认为 587
SMTP_SECURE 为是否启用 SMTP 安全,默认值为true

img

四、构建 Cusdis

1
yarn run build:without-migrate

img

这一步可能会出现错误,错误代码如下:

1
2
3
4
5
6
7
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! cusdis@ db:generate: `prisma generate --schema ./prisma/$DB_TYPE/schema.prisma`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the cusdis@ db:generate script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

这一步需要到 ./cusdis/prisma 选择需要设置的数据库类型,然后将该文件夹内的 schema.prisma 文件 复制到 ./cusdis/prisma 构建即可解决。

五、运行 Cusdis

1
yarn run start:with-migrate

img

设置程序守护,此处以systemd为例

打开目录 /usr/lib/systemd/system/

新建文件:cusdis.service

文件配置如下(以下配置仅供参考):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=CusdisServer

[Unit]
Description=CusdisServer

[Service]
ExecStart=/www/server/nodejs/node-v14.15.0-linux-x64/bin/npm start
Restart=always
Environment=PATH=/usr/bin:/usr/local/bin:/www/server/nodejs/node-v14.15.0-linux-x64/bin
Environment=NODE_ENV=production
WorkingDirectory=/www/wwwroot/cusdis/

[Install]
WantedBy=multi-user.target

此时保存即可,运行:

1
2
3
4
5
6
# 更新配置
systemctl daemon-reload
# 启动服务
systemctl start cusdis
# 设置开机启动
systemctl enable cusdis

详细的管理命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
# 启动服务
systemctl start cusdis
# 设置开机启动
systemctl enable cusdis
# 停止服务
systemctl stop cusdis
# 重启服务
systemctl restart cusdis
# 查看状态
systemctl status cusdis
# 更新配置
systemctl daemon-reload

Docker部署

一、获取镜像

镜像名如下:

1
djyde/cusdis

img

国内服务器获取镜像会极慢,请耐心等待。

二、创建容器

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
配置如下:
容器端口:3000
容器目录:/data
环境变量:
-e USERNAME=admin \
-e PASSWORD=password \
-e JWT_SECRET=ofcourseistillloveyou \
-e DB_URL=file:/data/db.sqlite \
-e NEXTAUTH_URL=http://IP_ADDRESS_OR_DOMAIN \
其中
USERNAME 为用户名
PASSWORD 为密码
JWT_SECRET 为 JWT 令牌
NEXTAUTH_URL 需要填写项目所用的域名/IP
DB_TYPE、DB_URL 为 数据库类型、数据地址

#以下配置为 EMAIL 配置 可选
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_SECURE=true
SMTP_USER=your gmail email
SMTP_PASSWORD=<app password>
SMTP_SENDER=your gmail email

img

启动完成。

后语

设置反向代理

宝塔新建站点 -> 打开SSL - > 反向代理 ->添加反向代理

目标 URL 填写:http://127.0.0.1:3000

img

img

配置站点

进入页面登陆,然后创建一个默认的网站,选择 Embed Code ,复制代码到网站的合适位置即可。

img

WordPress 配置

以下配置仅供参考,主要包括 data-page-id、data-page-url、data-page-title

1
2
3
data-page-id="<?php the_ID(); ?>"
data-page-url="<?php $id =get_the_ID();echo get_permalink($id); ?>"
data-page-title="<?php the_title(); ?>"

跨域问题

最开始使用的时候可能会出现跨域问题。

在反向代理的配置文件中添加:

1
add_header 'Access-Control-Allow-Origin' 'yousitedomain';

两种方法,更推荐 DOCKER 如选择手工安装,可能会遇到各种各样的问题。

🔲 ☆

CloudFlare 解决 CORS 跨域问题

目前博客的 CDN 方案是通过DNS识别境内境外IP,进行不同的解析的,但是使用 CloudFlare 会导致一部分跨域问题,使某些样式无法正常加载,不过最终还是找到了解决方案,记录一下。

img


配置

#2022-11-6更新一位MJJ大佬提供的更好的方法

在域名左侧选择规则->转换规则

img

选择修改响应头

img

具体配置如下图所示:

img

以下为旧方法,不太推荐使用:

百度出的方法,基本上都是从服务器配置 NGINX 取消跨域限制来解决,但是这样也会伴随着许许多多的问题。CloudFlare也发布了文章,通过 CloudFlare Worker 稍微配置一下即可解决这个问题。

一、创建 CloudFlare Worker 服务

img

设置服务名称,然后选择 HTTP 处理程序

二、点击快速编辑,将以下代码复制到其中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// Reference: https://developers.cloudflare.com/workers/examples/cors-header-proxy
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,HEAD,POST,OPTIONS",
"Access-Control-Max-Age": "86400",
}
function handleOptions (request) {
// Make sure the necessary headers are present
// for this to be a valid pre-flight request
let headers = request.headers
if (
headers.get("Origin") !== null &&
headers.get("Access-Control-Request-Method") !== null &&
headers.get("Access-Control-Request-Headers") !== null
) {
// Handle CORS pre-flight request.
// If you want to check or reject the requested method + headers
// you can do that here.
let respHeaders = {
...corsHeaders,
// Allow all future content Request headers to go back to browser
// such as Authorization (Bearer) or X-Client-Name-Version
"Access-Control-Allow-Headers": request.headers.get("Access-Control-Request-Headers"),
}
return new Response(null, {
headers: respHeaders,
})
}
else {
// Handle standard OPTIONS request.
// If you want to allow other HTTP Methods, you can do that here.
return new Response(null, {
headers: {
Allow: "GET, HEAD, POST, OPTIONS",
},
})
}
}
async function handleRequest (request) {
let response
if (request.method === "OPTIONS") {
response = handleOptions(request)
}
else {
response = await fetch(request)
response = new Response(response.body, response)
response.headers.set("Access-Control-Allow-Origin", "*")
response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
}
return response
}
addEventListener("fetch", (event) => {
event.respondWith(
handleRequest(event.request).catch(
(err) => new Response(err.stack, { status: 500 })
)

点击保存并部署

img

三、点击触发器,然后添加路由

img

填写需要解决跨域问题的域名,如多个文件在同一问题下,可直接通过 * 替代

之后即可解决 CloudFlare CORS 跨域问题。

img

出于安全原因,请只选择真正需要解决 CORS 错误的路径

可添加多个路由解决多个站点的问题

🔲 ☆

腾讯云 CDN 加速静态资源所产生的 CORS 错误

给站点的静态资源使用了腾讯云CDN加速,文件镜像到腾讯的对象存储里,结果配置完成后产生了CORS错误,即跨域错误


错误

img

CORS - 跨域

抽象的解释下为什么会导致跨域错误

当你拥有 A、B 两台服务器时,当 A 与 B 分别建设了一个网站,两个网站使用的域名不相同,分别为 网站A 和 网站B 。在网站A中调用了 网站B 的资源,此时由于 网站A 的头部参数与 网站B 后端程序所绑定的头部参数的不同,很大概率会导致调用B的资源虽然请求成功,但在浏览器中不会加载,这就是跨域错误。

一台服务器中建设两个或多个网站,也是同理。除此之外,除域名之外,端口、协议头不同均会导致跨域错误。

解决方法

错误报告:

1
Access to font at 'https://ras.its.he.cn/wp-content/themes/typology/assets/fonts/fontawesome-webfont.woff?v=4.7.0' from origin 'https://bcon.roywang.cn' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

发生此类错误主要是因为在请求资源时,资源头中没有 ‘Access-Control-Allow-Origin’,只需添加上即可解决

在腾讯云CDN控制台->域名管理->CDN域名管理

img

在高级配置中配置 HTTP 响应头即可

img

点击新增规格,配置如下:

1
2
3
头部操作:设置
头部参数:Access-Control-Allow-Origin
头部取值:此处为你所需访问资源的域名或IP,可为‘*’,多个域名或IP需用逗号隔开

img

保存并打开配置状态即可解决该问题。

img

🔲 ⭐

一种新型蠕虫:花瓣CORSBOT蠕虫

新年新气象,这个蠕虫我做了小范围测试,也提交了官方修复,小圈子里做了分享,这里正式对外公布下,出于研究而非破坏为目的,供大家参考。

IAMANEWBOTNAMEDCORSBOT
——-BOT PoC——-
http://evilcos.me/lab/IAMANEWBOTNAMEDCORSBOT.TXT

完整代码直接见上面这个链接即可。

里面需要特别注意的两个点:

  1. Conten-Type是JSON
  2. Origin是:huaban.com.al3rt.io,这个小技巧直接绕过花瓣的Origin判断

所以,蠕虫得以传播。

本质是:CORS(Cross-Origin Resource Sharing)的滥用导致,效果图:

最后,友情提示下:这个问题还是比较普遍的。脑洞怎么开,玩起来才会知道,不玩永远想不到:-)

🔲 ☆

[PRE]CSRF攻击-进击的巨人

计划准备出一个PPT专门讲解CSRF里的各种奇技淫巧,除了那些老套的手法之外:

https://github.com/evilcos/papers
我公布的Papers里有个PPT是《CSRF攻击-苏醒的巨人》,可以参考。

还包括以前提的Flash CSRF/XSF等方式,细节可以温习去年我的Paper(隐蔽的战场—Flash Web攻击),希望Flash是日不落帝国,虽然现在快日落了,但是不影响我们的最后挣扎。

除了这些,当然会有新的玩意,比如JSON Hijacking就一直在进化。还有去年很火的WormHole,这是JSON Hijacking本地攻击的一种延伸,点击下这个试试:

http://evilcos.me/lab/pac.html

探测你本地是否用Shadowsocks,当然你即使用了也不一定会弹,毕竟我测试的端口仅仅是默认的8788(如果你不是这个端口,你可以改为这个端口试试)。

以前我说过:玩CSRF,最爽的是结合了Flash,无声无息…

最近在做路由器安全研究,以及昨晚做了个新型蠕虫的测试:

1

给我带来的结论是:Flash,你可以安息了,感谢HTML5,以后玩CSRF同样可以很优雅。

我为什么Demo这只蠕虫?因为这确实是个影响会很深远的安全问题。

在我过去两年做的《程序员与黑客》第一季与第二季的演讲,里面有个核心点就是:程序员与黑客思维的差异,导致一些类型的安全问题可以成为经久不衰的存在,甚至会随着程序员的进化而不断演变。比如HTML5/ES6这些前端玩意的风靡,必然会带来许多“超能力”的滥用,毕竟能成为黑客的程序员少之又少,对抗博弈一直微妙地存在。

按照这种思维以及我最近的一些实战,CSP的存在(以及HTTP那些安全的X-扩展协议头)不会是前端黑的噩梦。我们最大的敌人是我们自己,伟大领袖也说过这句话:-)

❌