🍀 借助 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

相关推荐
程序猿John1 小时前
ES6 新增特性 箭头函数
前端·javascript·es6
百锦再2 小时前
五种常用的web加密算法
前端·算法·前端框架·web·加密·机密
uhakadotcom2 小时前
RunPod:AI云计算的强大助手
后端·面试·github
@大迁世界2 小时前
彻底改变我 React 开发方式的组件模式
前端·javascript·react.js·前端框架·ecmascript
uhakadotcom2 小时前
Google AlloyDB AI 与 PostgreSQL 的核心区别
后端·面试·github
uhakadotcom2 小时前
使用Go语言编写简单爬虫程序
后端·面试·github
William Dawson3 小时前
【Vue 3 + Element Plus 实现产品标签的动态添加、删除与回显】
前端·javascript·vue.js
拉不动的猪3 小时前
项目基础搭建时的一些基本注意点
前端·javascript·面试
蕉君桑3 小时前
vue2使用vue-echarts
前端·vue.js·echarts
runnerdancer3 小时前
React+Vite+Typescript项目脚手架模版
前端