🍀 借助 Github Actions 解决 Github DNS 污染问题

前言

Github 国内问题

国内网络访问 Github 速度过慢的原因有许多,但其中最直接的原因是其 CDN 域名遭到 DNS 污染,导致我们无法连接使用 GitHub 的加速服务,因此访问速度缓慢或访问不了。

什么是 DNS 污染

DNS 污染,是指一些刻意或无意制造出来的数据包,把域名指向不正确的 IP 地址阻碍了网络访问。我们默认从目标网址的最近 CDN 节点获取内容,但当节点过远或 DNS 指向错误时,就会造成访问速度过慢或无法访问等问题。

有哪些解决方案?

  1. 使用 VPN 进行科学上网,当然大部分的 VPN 并不是免费的。
  2. 查找 Github 正确的 DNS IP,然后借助于 SwitchHosts 配置 Host。

方案

在之前的章节中,我们简单介绍了国内 Github DNS 问题以及解决方案。毫无疑问第一种方案是能有效解决大部分国内资源被墙的问题。但作为IT技术爱好者,我更喜欢尝试用第二种方案来解决 Github 问题。

初步验证

  1. 在一台已经科学上网的电脑上,通过 nslookup github.com 找出正确的 Github IP。

    bash 复制代码
      nslookup github.com
    
    
      Server:    192.168.1.1
      Address:   192.168.1.1#53
    
      Non-authoritative answer:
      Name:  github.com
      Address: 20.205.243.166
  2. 在另一台无法访问 Github 电脑上,通过 SwitchHosts 如下配置,终于可以正常访问。

相关问题

虽然我们已经通过实践验证了第二种方案的可行性,但仍然有不少的问题有待解决:

  1. 上述验证阶段,我们通过 nslookup github.com 获取的 DNS IP,但 Github 域名所解析的 DNS 是随着时间而不断变化的,那怎么解决呢?

    关于这一点,我们想到了 Github Actions, 借助于它,我们不仅可以正确解析 Github DNS IP, 我们还可以设置 cron 定期自动查询 (比如每2小时查询一次)。Perfect!

  2. 解决了 Github DNS IP 定期自动更新问题,那我们如何在自己的电脑上配置 Github Host, 难道每一次 DNS IP 的变更,都需要手动重新配置吗?

    其实并不需要这么麻烦,我可以借助于 SwitchHosts 这款软件的远程 Host 的配置来实现,同时它还可以帮我们定期同步远程的 Host。

  3. 还有一个比较棘手的问题,当我们借助于 Github Actions 定期生成 Github 正确的 Host 文件供 SwitchHosts 配置远程的 Host 时。如果当时 Github 本身相关域名不可访问,那本机的 SwitchHosts 又如何访问该域名下远程的 Host 文件呢?

    确实这一点,有点像鸡生蛋还是蛋生鸡的问题。怎么解决呢,我们打算借助大神提供的 Github Actions, 将 Github 生成 Host 的整个仓库,同步到 Gitee 上, 同时生成 Gitee Pages,以便 SwitchHosts 获取和配置远程的 Gitee 的 Github DNS Host 文件。

梳理思路

  1. 编写 ZX nslookup 查询 Github DNS,生成 host 文件 的脚本
  2. 编写 Github Workflow 定时执行,并创建 Github Pages 的配置
  3. 编写 Github Workflow 同步 Github git 仓库部署到 Gitee 的配置
  4. 编写 Github Workflow 创建 Gitee git 仓库 Gitee Pages 的配置
  5. 使用 本机 SwitchHost 配置远程 Github/Gitee DNS host,并设置定时刷新

实施

编写 ZX 脚本

  • 执行 nslookup 查询 Github DNS,并将其生成 host 文件

    javascript 复制代码
    #!/usr/bin/env zx
    
    const writer = async arr => {
      let temp = {}
      const list = []
    
      for (const url of arr) {
        if (/^\.*\//.test(url)) {
          list.push(temp = {
            file: path.resolve(url),
            contents: [],
            content: '',
          })
          continue
        }
    
        if (temp.contents) {
          temp.contents.push(url)
        }
      }
    
      for (const temp of list) {
        temp.content = await updater(temp.contents)
      }
    
      for (const temp of list) {
        fs.ensureFileSync(temp.file)
        fs.writeFile(temp.file, temp.content)
      }
    }
    
    const updater = async arr => {
      const templates = []
      const datetime = new Date().toUTCString()
    
      templates.push(`# Update: ${datetime}\n`)
    
      for (const url of arr) {
        if (url) {
          const ip = await nslookup(url)
          const dns = `${ip}\t\t${url}`
    
          if (ip) {
            templates.push(dns)
          }
        }
      }
    
      templates.sort((next, prev) => {
        const nexts = next.split(/\s/)
        const prevs = prev.split(/\s/)
        return nexts[0].length < prevs[0].length ? -1 : 1
      })
    
      return templates.join('\n')
    }
    
    const nslookup = async url => {
      try {
        const regex = new RegExp(`.*Name:\\s*[\\S]+\\s*Address:\\s*([0-9.]+)\\s*.*`, 'ims')
        const dns = (await $`nslookup ${url}`).stdout
        const ip = dns.replace(regex, '$1')
    
        if (!/\d+\.\d+\.\d+\.\d+/.test(ip)) {
          return ''
        }
    
        if (ip === '127.0.0.1') {
          return ''
        }
    
        if (ip === '0.0.0.0') {
          return ''
        }
    
        if (ip) {
          return ip
        }
      } catch {}
    
      return ''
    }
    
    // Github 相关域名,仅摘录部分
    writer([
      './public/host.txt',
      'github.blog',
      'github.com',
      'github.io',
       ...
    ])
  • host 文件范例

    bash 复制代码
      # Update: Sat, 18 May 2024 00:00:38 GMT
    
      192.0.66.2          github.blog 
      140.82.116.4        github.com
      185.199.111.153     github.io

配置 Workflow

  • 编写 Github Workflow 定时执行,并创建 Github Pages 的配置

    yml 复制代码
        name: update github dns ip
    
        on:
          schedule:
            - cron: '0 */2 * * *' # 每隔两小时自动执行
    
        jobs:
          github-host:
            runs-on: ubuntu-latest # ubuntu 运行环境
            steps:
              - name: Checkout
                uses: actions/checkout@v4 # 检出仓库 main 主分支
    
              - name: Set pnpm
                uses: pnpm/action-setup@v3 # 安装 pnpm,版本 8
                with:
                  version: 8
                  
              - name: Set nodejs
                uses: actions/setup-node@v4 # 安装 node,版本 20
                with:
                  node-version: 20
                  registry-url: https://registry.npmjs.org/
                  cache: 'pnpm'
    
              - name: Install dependencies # 安装依赖
                run: pnpm install
    
              - name: Building scripts # 运行构建,创建 public/host 文件
                run: pnpm build
    
              - name: Deploy to GitHub Pages
                uses: peaceiris/actions-gh-pages@v4 # 创建 Github Pages
                with:
                  publish_dir: ./public
                  user_name: ${{ secrets.MY_USER_NAME }}
                  user_email: ${{ secrets.MY_USER_EMAIL }}
                  github_token: ${{ secrets.GITHUB_TOKEN }}
                  
  • 编写 Github Workflow 同步 Github git 仓库部署到 Gitee 的配置,主要借助于大神的 Yikun/hub-mirror-action@master 实现的

    yml 复制代码
        name: update github dns ip
    
        on:
          schedule:
            - cron: '0 */2 * * *' # 每隔两小时自动执行
    
        jobs:
           push-gitee-repo:
            runs-on: ubuntu-latest
            needs: github-host
            steps:
              - name: Add And Push Gitee
                uses: Yikun/hub-mirror-action@master
                with:
                  src: github/dns-host
                  dst: gitee/dns-host
                  dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
                  dst_token: ${{ secrets.GITEE_PERSONAL_TOKEN }}
                  static_list: 'github'
                  force_update: true
                  account_type: org
                  
  • 编写 Github Workflow 创建 Gitee git 仓库 Gitee Pages 的配置,主要借助于大神的 yanglbme/gitee-pages-action@main 实现的

    yml 复制代码
        name: update github dns ip
    
        on:
          schedule:
            - cron: '0 */2 * * *' # 每隔两小时自动执行
    
        jobs:
          deploy-gitee-repo:
            runs-on: ubuntu-latest
            needs: push-gitee-repo
            steps:
              - name: Deploy Gitee Pages
                uses: yanglbme/gitee-pages-action@main
                with:
                  gitee-username: ${{ secrets.GITEE_USERNAME }}
                  gitee-password: ${{ secrets.GITEE_PASSWORD }}
                  gitee-repo: dns-host/github
                  branch: gh-pages
                  

配置 SwitchHost

  • https://dns-host.github.io/github/host.txt
  • https://dns-host.gitee.io/github/host.txt (目前 Gitee 已暂停 Pages 服务)
  • https://gitee.com/dns-host/github/raw/gh-pages/host.txt (推荐)

资源

Git repo

https://github.com/dns-host/github
https://gitee.com/dns-host/github

Git host

https://github.com/dns-host/github/blob/gh-pages/host.txt
https://gitee.com/dns-host/github/blob/gh-pages/host.txt

Git io

https://dns-host.github.io/github/host.txt
https://dns-host.gitee.io/github/host.txt

相关推荐
好奇的菜鸟11 分钟前
typeof 和 as 关键字
javascript·typescript
nbsaas-boot13 分钟前
消息队列场景下的前端设计:如何优化用户体验
前端·ux
sususugaa15 分钟前
前端框架Vue3——响应式数据,v-on,v-show和v-if,v-for,v-bind
开发语言·前端·vue.js·前端框架
珹洺1 小时前
从 HTML 到 CSS:开启网页样式之旅(三)—— CSS 三大特性与 CSS 常用属性
前端·javascript·css·网络·html·tensorflow·html5
T^T尚6 小时前
uniapp H5上传图片前压缩
前端·javascript·uni-app
出逃日志6 小时前
JS的DOM操作和事件监听综合练习 (具备三种功能的轮播图案例)
开发语言·前端·javascript
XIE3927 小时前
如何开发一个脚手架
前端·javascript·git·npm·node.js·github
GISer_Jing7 小时前
React渲染相关内容——渲染流程API、Fragment、渲染相关底层API
javascript·react.js·ecmascript
山猪打不过家猪7 小时前
React(五)——useContecxt/Reducer/useCallback/useRef/React.memo/useMemo
前端·javascript·react.js
前端青山7 小时前
React事件处理机制详解
开发语言·前端·javascript·react.js