2022年9月11日星期日

clash

 https://lancellc.gitbook.io/clash/

深入理解Clash配置文件

 本文转载自:https://v2raytech.com/deep-in-clash-config-file/,如文中内容有错误请到原文查看原始版(最新版)

Clash是一个跨平台、支持SS/V2ray/Trojan协议、基于规则的网络代理软件,功能强大、界面美观、支持订阅,尤其适合机场和付费服务使用。Clash功能全加颜值好看,使得Clash深受喜爱,有一大批死忠粉。

本站之前已经简单介绍过Clash的基本配置和使用方法,参考:

V2ray:

trojan:

Just My Socks:

上述配置教程应付基本使用已经足够,但是如果你想进行更多个性化配置,那么需要对Clash配置文件有更深入的理解,才能更好的玩转Clash。

本文带你深入理解Clash配置文件,揭开Clash功能强大的面纱。

Clash特点

开始之前,先介绍一下Clash和其他代理软件的差别。

Clash和其他SS/SSR/V2ray/trojan等客户端的第一个不同点是:不能在界面上配置代理节点信息,只能通过编辑配置文件或者URL导入。对于机场用户,导入订阅URL就好了,然而对于只有原始信息的自建用户或普通用户,要么变成链接形式通过第三方API转换成URL导入,要么只能编辑配置添加节点。这种半手工编辑和半GUI的操作,不少人也觉得Clash有点蛋疼。

Clash和其他客户端另外一点重要差别是:代理(proxies)信息是根据配置文件生成的,不同的写法就有不同的界面。虽然用的同一个软件,如果别人的界面和你的不一样,请不要惊讶。

clash代理界面

clash代理界面

最后Clash的一个重要特点是:Clash配置文件只要按照指定语法写就可以了,可以自由发挥,不需要遵守什么特定格式。默认安装的官方配置文件非常简单,实际中使用的配置文件比官方带的复杂多了,功能也强大许多。

幸运的是,不少大佬维护了Clash配置文件的模板,一般情况下根据模板改改就能用。其中最著名的当属 神机规则 模板,本站教程中的配置文件也都基于该配置模板。

接下来以本站教程中出现的模板配置文件为例,深入介绍Clash配置文件。

深入理解Clash配置文件

Clash使用YAML文件作为规则配置文件,首先简要介绍一下YAML。

YAML简介

YAML是”YAML Ain’t markup language”(YAML不是一种标记语言)的缩写,是一种方便读写的数据序列化语言。

YAML有如下特点/优点:

  1. 文件名以 .yaml 结尾;
  2. 大小写敏感;
  3. 类似Python,以缩进指示层级关系;
  4. 不允许使用Tab键,缩进只能用空格;
  5. 支持数字、字符串、List、Map等数据类型;
  6. 支持注释,#号后面的内容是注释,会被忽略

更多YAML的介绍请参考:YAML,另一种标记语言?不止是标记语言!

SS/SSR/V2ray/trojan等配置文件使用json格式,相对于YAML,json最大不足是不支持注释。

因为YAML支持注释,因此YAML配置文件可以加入字段的详细解释,方便人们理解。本站教程使用的配置文件也都有详细注释。

接下来介绍本站用到的Clash配置文件。

Clash配置文件详解

下面以SS、V2ray、trojan的模板配置文件 https://v2xtls.org/clash_template2.yaml 为例,详细讲解Clash配置文件。

1. 首先下载 https://v2xtls.org/clash_template2.yaml 文件,用记事本、VS Code、Notepad++等打开;

2. 从第一行到第75行(proxies那一行)定义了一些Clash客户端运行时的设置,这些设置基本上都能在客户端界面里直接更改,不必通过配置文件修改:

Clash基础配置

Clash基础配置

3. 接下来proxies定义了代理节点配置信息,这一项非常重要。Clash支持SS、V2ray和trojan协议,本站的配置模板分别给出了这些类型的代理模板:

Clash配置代理节点信息

Clash配置代理节点信息

代理节点的主要操作和方法为:

  • 如果只有单个代理节点,找到对应类型修改成你服务端的信息就行了
  • 如果想删除多余的节点,把 -name 开头的整个节点配置删除,然后继续参考第4步的操作;
  • 如果想修改节点名称,比如把”ss”改成“香港-ss节点”,改name后面的值,然后继续参考第4步操作;
  • 如果想增加节点,根据节点类型(ss/vmess/trojan)复制节点模板,粘贴到节点列表下面,修改name和server等配置信息的值,然后继续参考第4步操作。

需要注意的是,V2ray节点的type是vmess,不是v2ray!

4. 拖动配置文件继续往下,proxy-groups定义代理组,这一项同样非常重要:

Clash配置节点代理组策略

Clash配置节点代理组策略

模板中的第一个代理组类型是url-test,表示通过测试url的响应时间来确定最快的代理节点。这个代理组中的proxies字段下面列出了代理节点的名称,表示参与测试的节点。所以,如果上一步修改了节点名称、增加或者删除了节点,请在这里更新节点信息。

接着配置文件定义了其他五个代理组,分别是PROXY、Final、Apple、GlobalMedia和HKMTMedia。对于不看流媒体视频的人来说,只有前两个代理组有用,剩下三个代理组对于看国外视频且有IP限制的网友才有用(当然同上一步提到的代理节点一样,不想用的话不能简单删除,还需要继续修改配置文件中其他用到的地方):

Clash配置其他代理组

Clash配置其他代理组

可以看到,PROXY组中的proxies用到了上一步定义的代理节点名称。所以,如果上一步修改了节点的名字、增加或者删除了节点,记得在这里更新节点名称。

聪明的你,看到这里应该明白了:Clash配置文件中name后面的值可以改成自己的,比如把name:"Apple" 改成 name: "苹果"。但不能简单的修改,而是要把所有用到这个名字的地方也都改成新的名字,否则导入到客户端后就会出错。这也是为什么之前的教程让你看不懂不要乱改name的原因。现在你懂了,那就可以尝试修改(记得先备份原来的配置文件)。

同代理节点一样,根据不同的需求,可以定义许多个代理组。客户端的代理界面就是根据代理节点和代理组的配置生成的。

5. 继续拖动配置文件,进入到规则配置界面(Rule)。我们常说Clash是一个基于规则的代理软件,这一步便是定义Clash使用的规则:

Clash配置代理规则

Clash配置代理规则

新版clash中,Rule指令已经被弃用,使用rules代替

一个代理规则主要由三部分组成:

  1. 应用对象,包括完整域名(DOMAIN)、域名后缀(DOMAIN-SUFFIX)、域名关键字(DOMAIN-KEYWORD)、IP地址/段(IP-CIDR)以及GEOIP;
  2. 作用的IP或者域名;
  3. 采取的规则,包括直连(DIRECT)、屏蔽(REJECT),走某个代理组(上一步定义的PROXY、Apple等代理组)

配置文件中给出了许多域名和IP的代理规则,如果你想删除和修改某个域名/IP走代理还是直连,请在这些规则里修改。

规则最后一行是MATCH,Final,表示如果客户端运行在基于规则模式,如果匹配到上面的规则,就按照规则定义的路由走,否则走Final这个规则组。

同上文所述,代理组的name可以修改,但是要把规则中出现的名称也一起改了,否则软件无法运行

6. 最后是Clash for Windows需要绕过的IP和域名设置,一般无需更改:

Clash绕过列表

Clash绕过列表

到此一个完成的Clash配置文件结束,通过上面的说明,你应该对Clash配置文件不再感到神奇和害怕了吧?

总结

本文介绍了Clash和其他代理客户端的区别,并给出了配置文件的完整说明。通过对Clash配置文件的理解,能让你更好的使用这个功能强大的代理软件。

2022年8月22日星期一

hexo使用Artalk评论系统

  前些日子逛 GitHub 时发现一个比较满足强迫症要求的评论系统 Artalk,功能完善且带有支持自托管的后台,恰逢 LeanCloud 政策变更, 忍受了 LeanCloud 好几年的资源与其他限制, 终于这次,我准备休掉它换 Artalk 了, 毕竟自建博客本就是为了不受到各种平台的限制。

  从关于页面可以看出, Alliot’s blog 已经有很长很长一段时间没有折腾过博客了, 本站所用的 NexT 主题也是多年以前自己魔改过很多的 5.1.0 版本,早已偏离了上游仓库十万百千里, 同时因为魔改了挺多,又懒得折腾升级新的版本, 因此无法直接使用 Artalk 文档中提到的插件方式安装。这里只能直接进行修改,在这过程中踩了一些坑, 这里稍微记录一遇到同样问题的朋友参考(或许没我这么懒而强迫症的)。

后端配置

  后端安装跟着官方文档 docker-compose 一把梭基本是没有什么部署上的问题的,只是在配置上需要注意一些地方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 可信域名, 必须匹配,否则会报CSRF
trusted_domains:
- "https://artalk.iots.vip" # artalk 后端地址
- "https://www.iots.vip" # 博客地址
- "http://www.iots.vip"
- "http://localhost:4000" # 供本地调试地址
- "http://127.0.0.1:4000"


# 默认站点名
site_default: "blog"

# 管理员账户
admin_users:
- name: "xxx"
email: "xxx@xxx.com"

# 密码支持 bcrypt 或 md5 加密
# 如admin加密后的32位md5为: 21232f297a57a5a743894a0e4a801fc3,则如下字段因添加(md5)前缀:
password: "(md5)21232f297a57a5a743894a0e4a801fc"

  如果需要 Nginx 反向代理, 这里提供一份 Nginx 配置参考:

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
server {
listen 443 ssl http2;
server_name artalk.xxx.com;
access_log access_artalk.log;

#新增ssl配置---开始:
ssl_certificate xxx.crt; #证书公钥文件路径
ssl_certificate_key xxx.key; #证书私钥文件路径
ssl_session_timeout 5m; #5分钟session会话保持
ssl_session_cache shared:MozSSL:10m;
ssl_dhparam cert_file/dhparam;
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_stapling on;
ssl_stapling_verify on;
#新增ssl配置---结束:

proxy_max_temp_file_size 0;
client_max_body_size 128M;


location / {
proxy_pass http://localhost:23366;

# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}

location =/robots.txt {
default_type text/html;
add_header Content-Type "text/plain; charset=UTF-8";
return 200 "User-Agent: *\nDisallow: /*";
}
}

# http 301 -> https
server {
listen 80;
server_name artalk.xxx.com;
return 301 https://artalk.xxx.com$request_uri;
}

前端配置

  这里只是提供适用于适用于 Alliot’s blog 当前版本 NexT 主题的配置, 其他主题未经官方适配的主题或许可以参考一下(我前端超烂…见笑了):

  首先是资源引用,以及实例化 artalk。 themes/next/layout/_scripts/third-party/comments.swig 实例化的时候需要注意,如果你有评论是从 valine 导入的话, page_key 这里需要改一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{% if theme.artalk.enable and theme.artalk.server %}

<link href="https://unpkg.com/artalk@2.3.4/dist/Artalk.css" rel="stylesheet">
<script src="https://unpkg.com/artalk@2.3.4/dist/Artalk.js"></script>

<script>
// 获取相对路径, 如果直接用官方文档说的不指定 pageKey,则会出现 about 等页面评论无法正常加载的情况
// 因为page_key的缺省值location.pathname 会在 /about/ 后添加 index.html 后缀
// 而hexo的about等页面实际上的 URL 是不包含这个后缀的,所以会导致 key 无法对应上,评论导入后为空。
const url = '/' + "{{ page.permalink }}".split('/').slice(3).join('/');

var artalk = new Artalk({
el: '#artalkComments',
server: '{{ theme.artalk.server }}',
pageKey: url,
site: '{{ theme.artalk.site }}'
})

</script>

{% endif %}

  然后我们在评论位置添加这个元素, themes/next/layout/_partials/comments.swig:

1
2
3
{% elseif theme.artalk.enable and theme.artalk.server %}
<div id="artalkComments"></div>
{% include '../_scripts/third-party/comments.swig' %}

  再然后,为了添加首页文章评论数的效果,我采用了比较笨的一个方法去请求后端获取评论数量(粗略的看了一下文档好像并没有提供,因此构造请求来拿一下…), themes/next/layout/_macro/post.swig header 标签内添加:

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
{% if theme.artalk.enable and theme.artalk.server %}
<span class="post-comments-count">
<span class="post-meta-divider">|</span>
<span class="post-meta-item-icon">
<i class="fa fa-comment-o"></i>
</span>
<a href="{{ url_for(post.path) }}#artalkComments" itemprop="discussionUrl">
<span id="{{ post.path }}" class="post-comments-count" data-xid="{{ url_for(post.path) }}" itemprop="commentCount">loading..</span>
</a>
</span>
<script>
var formdata = new FormData();
formdata.append("site_name", "{{ theme.artalk.site }}");
formdata.append("page_key", "{{ url_for(post.path) }}");
formdata.append("limit", "1");

var requestOptions = {
method: 'POST',
body: formdata,
};
//console.log("{{ url_for(post.path) }}")

fetch("{{ theme.artalk.server }}/api/get", requestOptions)
.then(response => response.text())
.then(result => {
const count = JSON.parse(result).data.total
document.getElementById('{{ post.path }}').innerText = count
})
.catch(error => console.log('error', error));
</script>
{% endif %}

最后,主题配置文件 themes/next/_config.yml 添加:

1
2
3
4
artalk:
enable: true
site: 'blog'
server: 'https://artalk.xxx.com' # 记住不要加 / 结束

导入valine评论到Artalk

  跟随 Artalk 官方文档从 LeanCloud 导出 Comment Class 后,邮件收到的是 jsonl 格式,我们需要将其转为 json 格式:

1
2
# 首先打开 jsonl 文件删除首行的注释后,执行如下shell命令,注意valine.jsonl替换为实际的文件名 
sed '1s/^/[/; $!s/$/,/; $s/$/]/' valine.jsonl > artalk.json

这样再通过数据行囊 将其格式转换,并导入到 Artalk。
  导入的时候,需要提供 “目标站点名”, “目标站点 URL”,我这里目标站点为 “blog”, URL 为 “https://www.iots.vip", 导入后会发现一个问题,由于我们前面前端使用的 page_key 为相对路径, 但是 Artalk 的导入功能在写入数据的时候又默认会拼接 “目标站点 URL” 进 page_key 字段,这样就会导致旧的评论无法在文章页面中展示,我们需要手动将数据库中的 comments 表中的 page_key 改成相对路径。这样导入的评论就能正常展示了(感觉应该算是一个 BUG,已经跟作者提了)。
  连接数据库执行如下 SQL(如果你用的是 sqlite,那么直接用 navicat 打开它就行啦):

1
update `comments` set page_key=REPLACE(page_key, 'https://www.iots.vip/', '/');

结语

  工作后已经很少有心情去折腾博客了,比较双手抱着砖头,失去了太多的热情。这次改评论系统过程中的处理的方法又丑又笨,但就如罗老师说的————又不是不能用(逃

https://www.iots.vip/post/hexo-artalk-comment.html

2022年8月20日星期六

hugo github action|vecel 部署后文章更新时间异常修复

hugo 博客搭建好后,陆陆续续发现一些问题。大都成功进行了处理。

其中一个最头大的问题就是:文章更新时间异常。

文章更新时间异常
文章更新时间,本地和远程部署的不同,远程通过 github action|vecel 部署,远程部署后的时间不对,会把所有文章时间都更为最新。

每次更新文章后,本地显示所有文章更新时间正常,没有修改的还是保留旧的更新日期,而通过 github action|vecel 自动部署后,所有文章更新时间都会改为最新此次更新时间,那些此次没有做修改的文章也一并全部更新。

注意,不是发表时间,发表时间没有问题。

https://s2.loli.net/2022/08/16/Mt2EKIVY5ai8zmv.png
本地端
https://s2.loli.net/2022/08/16/jgeDwLyHtzUpFY4.png
远程部署后

这个 bug,花费了我很多时间精力才找到原因,终于解决了这个问题。

解决这个问题,我们先说 hugo 博客的几个时间字段说起。

hugo 全局配置文件为 config.toml/yaml/json

在 hugo 中日期(时间)是非常重要的字段,hugo 的官方配置文档 configuration(https://gohugo.io/getting-started/configuration/#configure-dates) 提供一个配置日期的 section [frontmatter]

1
2
3
4
5
6
7
[frontmatter]

  # 左边意为,变量 .Date 将会被赋值为右边数组中最先找到的的日期值
  date = ['date', 'publishDate', 'lastmod'] 
  expiryDate = ['expiryDate']
  lastmod = [':git', 'lastmod', 'date', 'publishDate']
  publishDate = ['publishDate', 'date']
  • publishDate: 变量,发表日期
  • expiryDate:变量,有效期
  • lastmod:变量,最后修改日期
  • :git:git 文件提交修改时间

这是官方列举的字段和基本配置,不过说明不是很详细。

这里说明一下,= 左边的是变量,右边中括号的是变量值,需要在对应模板里添加后才生效。

这里我们只探讨最后更新时间 lastmod

一般主题里的配置方式是这样:

1
2
[frontmatter]
  lastmod = [":git", ":fileModTime", "lastmod", ":defalut"]
  • :git:git 文件提交修改时间
  • :fileModTime:文件修改时间
  • lastmod:文章里 lastmod 字段
  • :defalut:默认时间

这里 lastmod 变量获取,以 git 文件提交修改时间,文件修改时间这样排,文章里 "lastmod“字段可不加,这样是没问题的。

我的博客就是以此配置为准,本地运行时,更新时间显示正常


  1. 如果要加”lastmod“字段,在创建文章模板里添加以下一行。添加”lastmod",有个好处就是可自由修改这个字段的时间。

hugo 默认位置为 archetypes/default.md 或者主题下目录下 xx主题/archetypes/posts.md,主题目录下如果有增加模板,创建时会以主题目录下的模板来创建。

1
lastmod: {{ .Date }}
  1. 然后再去 config.toml/yaml/json

调整这里顺序即可:

1
2
[frontmatter]
  lastmod = [":git", "lastmod", ":fileModTime", ":defalut"]

好了,按以上配置,本地运行时,更新时间显示正常,这没有任何问题。

问题来了,通过 GitHub action 部署后(我的 verccel 从 GitHub 直接同步过去),就出现问题了,每次一提交更新,会把所有文章时间都更为最新。

本地端没问题,说明问题就出在 GitHub action 部署过程了。

补充提示一下,有一个坑 : GitHub action 的 Schedule 运行不准时

GitHub action 上的默认配置时间有个坑,设定的 schedule 是 UCT 时间的 08:00,比北京时间快 8 个小时。因此运行环境要改为北京时间。

解决方法:

.github/workflows/xx.yml

yml 文件中添加 2 行设置当前环境时区

1
2
3
4
5
6
name: Hugo build and deploy
on:
	push:

env:
	TZ: Asia/Shanghai # 设置当前环境时区

config.toml/yaml/json

1
2
#获取git信息
enableGitInfo = true  #设为true

建构前新增以下配置,主要是 quotePath,默认情况下,文件名包含中文时,git 会使用引号吧文件名括起来,这会导致 action 中无法读取:GitInfo 变量,所以要设置 Disable quotePath[^1]

1
2
3
4
5
6
- name: Git Configuration
        run: |
          git config --global core.quotePath false
          git config --global core.autocrlf false
          git config --global core.safecrlf true
          git config --global core.ignorecase false

使用 checkout 的话 fetch-depth 需要设为 0,depth 默认是为 1,默认只拉取分支最近一次 commit,可能会导致一些文章的 GitInfo 变量无法获取,设为 0 代表拉去所有分支所有提交。

1
2
	uses: actions/checkout@v2
		  fetch-depth: 0   #设为0

以下是我最终的 yml 配置文件

参考:

# Github Action 自动修改文章的更新日期

# [BUG] 目录所有文章 - 最近更新,本地与远程打包不同,数据不对