前面写了一篇文章介绍Mosdns安装和配置使用,本文来优化一下文中的配置,然后介绍一下搭配Cloudflare优选IP的使用技巧。

配置优化

下面这些优化并非必须的,并且都是mosdns的实验性功能,所以请务必了解清楚再应用到自己的配置中。

缓存写入文件

上一篇文中设置了乐观缓存,我设置的时间是3天,但是同时又配置了每天更新域名列表,所以其实缓存时间只有一天。为了解决这个问题,可以将缓存写入文件,mosdns会定时自动写入缓存,启动时则自动从文件中加载缓存。同时,为了方便随时清理缓存或写入文件,还可以开启API,具体的配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
api:
  http: "0.0.0.0:53535"

plugins:
  - tag: cache
    type: cache
    args:
      size: 10240
      lazy_cache_ttl: 259200
      dump_file: /etc/mosdns/cache.dump

然后就可以通过curl your.mosdns.ip:53535/plugins/cache/flush来清理缓存了,dump和load_dump的操作一般无需手动进行。

另外,说一下自动重启mosdns这个事情,因为配置了定时任务,加上mosdns v5不支持自动重载配置,所以每次拉取域名列表以及每次优选完IP之后都得重启(下文会配置),具体每天重启几次取决于你的定时任务。以我自己为例,我配置的是每天要重启三次(两次优选、一次列表),根据我观察mosdns的日志,从准备关闭到完全启动大概在130ms左右,以我的家庭局域网条件而言,这个重启操作可以说完全没有影响。但是每个人情况不同,接受程度不同,加上重启也是有风险的,有可能关了就起不来了,所以在配置过程中,请根据自己的实际情况来选择如何重启。

增加fallback容错

上一篇的配置中,main sequence中最后的操作是- exec: $proxy_forward,这其实有一点问题,如果代理挂了就完蛋了,不在直连名单内的域名将无法解析。为了解决这个问题,需要引入fallback插件,配置很简单:

1
2
3
4
5
6
- tag: proxy_fallback
  type: fallback
  args:
    primary: proxy_forward
    secondary: cn_forward
    always_standby: false

这样一来,代理挂了之后不至于影响DNS解析。这里需要注意的是always_standby设置为了false,有两个原因,一是这本来就是个保险,如果设置为true的话,两个forward都会执行,没必要;二是为了避免DNS泄露。

Cloudflare优选IP

有关优选IP这个项目如何使用我就不啰嗦了,看README或者网上的教程都可以,需要注意的是,优选IP并不适合所有人,有些网络下用了还不如不用。因此,继续看之前最好先搞明白到底适不适合自己。

配置起来有两种思路,一是白名单,二是黑名单,各有利弊,看完之后需要自己权衡使用哪种。不过二者有一个共同的好处,就是改了之后整个局域网都生效,所有的设备都可以享受优选IP。

假设现在获取到的优选IP是104.19.5.44 104.19.68.1 104.19.25.61这三个。

白名单

白名单利用的机制是mosdns的hosts文件,很简单,就是把需要优选的域名和优选之后的IP写入hosts文件即可。这样的好处是:

  1. DNS查询快!类似主机hosts,域名匹配之后连DNS请求都不用发,直接就返回了。
  2. 自己清楚哪些网站是被优选的,意外出现的概率几乎为0(下面黑名单再介绍意外的情况)。

坏处是手动配置域名太麻烦了,不可能对所有Cloudflare的网站优选,如果某个网站不用Cloudflare了,还得手动移除。

这种方式不需要修改config.yaml配置文件,下面是hosts.txt的示例:

1
2
blog.eyebrowkang.com 104.19.5.44 104.19.68.1 104.19.25.61
xxxx.com 104.19.5.44 104.19.68.1 104.19.25.61

黑名单

黑名单利用的是mosdns内置的black_hole操作,其原理就是先按流程走拿到响应,然后如果不在黑名单内,就进入对比流程,对比响应是否在CF公布的IP段内,在范围内就证明用的CF的服务器,可以优选,利用black_hole篡改响应为优选的IP即可;不在的话就原样返回。而如果域名在黑名单内,则略过对比流程,直接返回。

这种方式的好处是:

  1. 不需要手动一个一个配置,省心省事
  2. 覆盖全面,绝大部分(可能有网站不在公布的IP段内)的CF网站都可以被优选

坏处有两个:

  1. 比白名单慢,但是和正常网站应该是一样的,这个可能不算坏处。
  2. 会有意外发生。这里解释一下,CF的企业用户可以让任意端口走CDN,这样的企业用户使用的IP是特殊的,可以转发特殊端口,而优选IP不能转发这些特殊端口。举个例子,gitlab就是Cloudflare的企业用户,CF给gitlab.com分配的IP是172.65.251.78,这个IP可以转发22端口给gitlab,但我们优选的IP是没办法转发22端口给gitlab的,结果就是优选完可以看gitlab的网页但不能用SSH。我们并不能预知这些网站,所以碰到之后就需要加到黑名单里,禁用优选,这种就属于意外情况。

这种方式需要修改配置文件,这里只展示变动的部分,完整配置在文章末尾提供:

 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
plugins:
  - tag: "cf_ip_set"
    type: "ip_set"
    args:
      files:
        - /etc/mosdns/cf-ipv4.txt
        - /etc/mosdns/cf-ipv6.txt

  - tag: cf_black_hole
    type: sequence
    args:
      - matches:
          - qname &/etc/mosdns/cf-black.txt
        exec: return
      - matches:
          - resp_ip $cf_ip_set
        exec: black_hole 104.19.5.44 104.19.68.1 104.19.25.61

  - tag: main
    type: sequence
    args:

      # 忽略了部分配置

      - exec: $cache
      - exec: jump cf_black_hole
      - matches:
          - has_resp
        exec: accept

      - matches:
          - qname &/etc/mosdns/direct-list.txt &/etc/mosdns/my-direct-list.txt
        exec: $cn_forward
      - exec: jump cf_black_hole
      - matches:
          - has_resp
        exec: accept

      # 忽略了部分配置

      - exec: $proxy_fallback
      - exec: jump cf_black_hole

简单解释一下上面的配置,cf_ip_set是从官方网站获取到的IP列表;cf_black_hole这个sequence对应前面提到的对比流程,在黑名单内的不篡改响应直接返回,否则如果是CF的IP就篡改。接下来的main sequence中,分别在三个位置(命中缓存后、直连转发后、代理转发后)进行一个对比,之所以命中缓存也要走一下对比流程,是因为优选的IP会变(下面会配置自动化)。另外,注意这里用的是jump关键字,这在执行完cf_black_hole之后会返回main sequence,如果用goto就不会返回了。

自动化优选IP过程

由于优选IP是有时效性的,可能几天甚至几小时就变了,所以肯定是需要配置自动化优选的,让我手动优选的话还不如不优选。下面的脚本是我自用的,来源于官方仓库的脚本,做了一些修改。

 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
57
58
59
60
61
62
63
64
#!/usr/bin/env bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# --------------------------------------------------------------
#       项目: CloudflareSpeedTest 自动更新 Hosts
#       版本: 1.0.4
#       作者: XIU2
#       项目: https://github.com/XIU2/CloudflareSpeedTest
# --------------------------------------------------------------

_CHECK() {
        while true
                do
                if [[ ! -e "nowip_hosts.txt" ]]; then
                        echo -e "该脚本的作用为 CloudflareST 测速后获取最快 IP 并替换 Hosts 中的 Cloudflare CDN IP。\n使用前请先阅读:https://github.com/XIU2/CloudflareSpeedTest/issues/42#issuecomment-768273848"
                        echo -e "第一次使用,请先将 Hosts 中所有 Cloudflare CDN IP 统一改为一个 IP。"
                        read -e -p "输入该 Cloudflare CDN IP 并回车(后续不再需要该步骤):" NOWIP
                        if [[ ! -z "${NOWIP}" ]]; then
                                echo ${NOWIP} > nowip_hosts.txt
                                break
                        else
                                echo "该 IP 不能是空!"
                        fi
                else
                        break
                fi
        done
}

_UPDATE() {
        echo -e "开始测速..."
        NOWIP=$(head -1 nowip_hosts.txt)

        # 这里可以自己添加、修改 CloudflareST 的运行参数
        ./CloudflareST -o "result_hosts.txt"

        [[ ! -e "result_hosts.txt" ]] && echo "CloudflareST 测速结果 IP 数量为 0,跳过下面步骤..." && exit 0

        BESTIP=$(sed -n "2,4p" result_hosts.txt | awk -F, '{print $1}' | tr '\n' ' ' | sed 's/ $//')
        if [[ -z "${BESTIP}" ]]; then
                echo "CloudflareST 测速结果 IP 数量为 0,跳过下面步骤..."
                exit 0
        fi
        echo ${BESTIP} > nowip_hosts.txt
        echo -e "\n旧 IP 为 ${NOWIP}\n新 IP 为 ${BESTIP}\n"

        # ====这是给黑名单用的====
        echo "开始备份 Config 文件..."
        \cp -f /etc/mosdns/config.yaml /etc/mosdns/config_backup.yaml
        echo -e "开始替换..."
        sed -i "s/$NOWIP/$BESTIP/g" /etc/mosdns/config.yaml

        # ====白名单用下面的配置====
        # echo "开始备份 Hosts 文件..."
        # \cp -f /etc/mosdns/hosts.txt /etc/mosdns/hosts_backup.txt
        # echo -e "开始替换..."
        # sed -i "s/$NOWIP/$BESTIP/g" /etc/mosdns/hosts.txt

        echo -e "完成..."
        systemctl restart mosdns
}

_CHECK
_UPDATE

我改动的地方有三个,

  1. BESTIP,我改成了选前三个IP出来
  2. 备份和替换的地方,我改成了config.yaml的路径,因为我自己在用黑名单模式。如果是白名单,需要改成hosts文件的路径
  3. 最后重启一下mosdns,否则不会生效。

最后需要配置一下定时任务,具体看这里,里面也有其他的细节,建议弄明白。另外,建议让AI解读一下脚本,自己先搞明白了再用,不要直接复制粘贴,容易爆炸💥。

总结

本文主要讲的依然是配置思路,并不是小白教程,不适合复制粘贴,需要按照自己的实际情况灵活修改。所有涉及到的配置文件和脚本都在这个gist,如果有更好的配置思路,欢迎留言交流 😁 。