DNS被抢答

问题发现

最近在研究 DNS 解析,学习了 nslookup 命令和 dig 命令。在我尝试查询 DNS 解析结果时,发现了一个问题:当我查询未被墙的域名时,每次查询到的结果都是一样的(无论有几个 A 记录);但是当我查询已被墙的域名时,每次的结果都不一样,且都是错误的 IP。

最开始,我对这个结果并不意外,因为当我输入 nslookup twitter.com 时,默认使用的是墙内的 DNS 服务器,它自然会给我一个错误的 IP,毕竟这是 G/F/W 的手段之一。但是当我在命令中加上特定的 DNS 服务器时,比如 nslookup twitter.com 8.8.8.8,被墙域名的查询结果依然是每次不一样的错误 IP,如图所示:

这就让我陷入了困惑,难道命令中的 8.8.8.8(Google DNS)不起作用?又或者是 Google DNS 仍然返回给我错误的 IP?更加奇怪的是,我输入一个不存在的 DNS 服务器,我依然会得到查询结果?????

抓包分析

于是我用 Wireshark 抓包分析,果然发现了问题。我的一次 DNS 查询,竟然会得到 3 个返回结果!前两个经过验证均为错误的,只有最后一个是正确的:

如果是向不存在的 DNS 服务器(5.5.5.5)查询,那么得到的全是错误的结果:

这说明我得到的 DNS 查询结果被做了手脚,网络上搜索一番后,我知道了这叫作 DNS 抢答(可以参考 这篇文章),我的 DNS 查询被抢答了错误的答案!

在云服务器上测试

我在一台香港的 VPS 上做了同样的测试,结果查询结果均为正确的(以 facebook.com 为例),不会出现被抢答的情况。G/F/W,可真有你的!关于具体细节见 维基百科


使用 Maven 时遇到的一个小问题

之前在 MacOS 的命令行中使用 Maven 时,遇到 mvn compile 报错,说我的 $JAVA_HOME 环境变量没有正确设置:

1
2
3
The JAVA_HOME environment variable is not defined correctly
This environment variable is needed to run this program
NB: JAVA_HOME should point to a JDK not a JRE

于是我打开了 .zshrc 文件,我的 $JAVA_HOME 是这样写的;

1
2
3
export JAVA_HOME=$(/usr/libexec/java_home)
export PATH=$JAVA_HOME/bin:$PATH
export CLASS_PATH=$JAVA_HOME/lib

之所以写成 export JAVA_HOME=$(/usr/libexec/java_home),是因为我之前在网上查找如何设置 MacOS 的 $JAVA_HOME,看到了这么一段话:

Many Java applications need to know the location of a $JAVA_HOME directory. The $JAVA_HOME on Mac OS X should be found using the /usr/libexec/java_home command line tool on Mac OS X 10.5 or later. On older Mac OS X versions where the tool does not exist, use the fixed path “/Library/Java/Home”. The /usr/libexec/java_home tool dynamically finds the top Java version specified in Java Preferences for the current user. This path allows access to the bin subdirectory where command line tools such as java, javac, etc. exist as on other platforms. The tool /usr/libexec/java_home allows you to specify a particular CPU architecture and Java platform version when locating a $JAVA_HOME.

Another advantage of dynamically finding this path, as opposed to hardcoding the fixed endpoint, is that it is updated when a new version of Java is downloaded via Software Update or installed with a newer version of Mac OS X. For this reason, it is important that developers do not install files in the JDKs inside of /System, since the changes will be lost with subsequent updates by newer versions of Java.

To obtain the path to the currently executing $JAVA_HOME, use the java.home System property.

大意就是说,/usr/libexec/java_home 这个命令会直接找到本机上版本最新的 Java 的 $JAVA_HOME,所以我就直接写成了上面 .zshrc 文件的样子,结果 Maven 却报错,说我写得不对。于是我直接输入命令:

1
$ /usr/libexec/java_home

得到的结果却是:

1
/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home

问题在于,这个/Library/Internet Plug-Ins/目录的 Internet Plug-Ins 中间有一个空格,所以如果直接把这一串写进 .zshrc 文件的话,没有转义,就会导致路径不对。

至于为什么 Java 会安装在这个目录下呢,原来这是 MacOS 使用 .dmg 方式安装的 Java。我找到我另一个 Java 版本的 Home 目录,在 /Library/Java/JavaVirtualMachines/jdk1.8.0_271.jdk/Contents/Home 下,于是我把 $JAVA_HOME 改成该路径,问题就解决了。


记笔记的历程

为什么记笔记

大学之前,我没有记笔记的习惯。一方面,在应试教育的影响下,所有学过的知识都会被老师重复再重复,不断加深印象,年少的我记忆力还足以应付记住这些知识;另一方面,我没有自己的电脑,再加上书本太多,用来记笔记的本子时常被我弄丢,丢了几次之后,索性就不记了,最多只有课本上稀稀拉拉的一些小笔记。

后来读大学了,学的东西越来越多,也越来越复杂。迫于常常遗忘,我在自己的电脑上,开始了记录笔记和整理笔记的历程。更重要的是,由于以前的教训,我的一个核心需求是:寻找一种永远不会让笔记丢失的方案。

初期

最开始不会什么高大上的技巧,直接用微软的 Word 记笔记(相信有很多人和我一样吧),后来接触了 Github 才知道了 Markdown,契机是我曾有一次搜索:「README.md 是什么文件?」。

发现了 Markdown 的我就像发现了新大陆一样,快速把它学会了,因为它太好用了,语法简单上手快,功能也多,代码行、图片、表格…… 可以直接渲染成网页,十分纯粹又十分漂亮,看着就舒坦,于是我的笔记一律都改为使用 Markdown 来写了。

然后我开始寻找写 Markdown 的工具,就又发现了一个神器:Typora。常规的 Markdown 编辑器一般是分两个屏,左边是 Markdown 源码,右边是渲染后的界面,或者干脆只能写源代码,要用浏览器打开才能看到渲染后的样子。而 Typora 与众不同的地方在于:当我写下 Markdown 源码时,显示出来的直接就是渲染后的页面,所写即所见,干净利落。

为了实现永不丢失的目的,我采取了一种多地备份策略:先在 GitHub 上建立一个笔记仓库,clone 到本地,然后在本地的仓库中记笔记,再定期 push 到远端。当时的我,每次都隔一段时间手动 push,然后还手动上传到 Google Drive 和 OneDrive,当时的我连写脚本自动上传都不会(菜+懒)。这个策略持续了一段时间。

Notion 时期

后来,我买了一台 MacBook,一次偶然的机会在 少数派 上看到了关于 Notion 的推荐,于是我就去尝试了这个软件,发现很有特色!贴近原生的 Markdown 语法,基于“方块”的新颖编辑模式,还有其他功能,例如嵌入视频、ToDo 列表,Database 等,也都非常好用。最重点的是,学生凭借 edu 邮箱可以免费使用 professional 版本,真的十分良心。于是我把所有的笔记迁移到了 Notion。

然而,在与 Notion 度过了一段“蜜月期”之后,我逐渐发现了 Notion 的缺点:它是完全基于 Web 的,也就是我所写的东西,全部被上传至云端,并没有本地保存一份,当我查看时,需要请求服务器获取页面。虽然这样方便了个人跨平台访问内容以及多人跨平台协作,但是也造成了问题:如果某篇笔记内容偏多,打开时就会加载很长时间,这个体验确实不太舒服。后来我又了解到,Notion 开发团队目前还在成长阶段中,而且服务器也时不时发生故障,造成很多人无法打开笔记,以及丢失笔记更新等诸多问题,具体见 Notion 官方推特。我不否认 Notion 是个很棒的产品,但由于我用不上 Notion 关于多人协作的功能(也许这才是精髓),发挥不了它的全部实力,再加上上述缺点,我最终还是放弃了它。

继续试错以及目前方案

再之后,我又尝试了几个其他的笔记应用,如 印象笔记logseq,都没有达到我的预期,兜兜转转,我又回到了 Typora。后来我学习了 rclone 这个命令行工具,它让我很方便地将本地内容与云端同步,于是我制定了一个更好的策略:在本地写 Markdown 笔记,然后编写脚本,每隔 2 小时,就自动使用 rclone 将笔记上传至 Google Drive 和 OneDrive,当然,我的 iCloud 是自动上传的。这样,不需要我手动操作,就轻松达到了多地备份的目的。这个策略是我直到目前还在使用的,算是一个简单又能满足我需求的方案。如果我之后想到或发现了更好的策略,也许我还会有所改变。

看到这篇文章的朋友,如果你也有记笔记的习惯,欢迎所有交流。关于 rclone 的使用可以参考我的另一篇文章:「rclone 使用说明


rclone 使用说明

为什么使用 rclone

我们使用网盘,一般是打开客户端,然后上传我们的文件或者文件夹,但是当我们的数据在本地更新了,网盘上却不会更新(据我所知 Dropbox 和 iCloud 可以做到同步更新),需要我们再次打开客户端上传一遍。能不能让本地文件实时(或者每间隔一段时间)同步上传到网盘呢?rclone 可以做到这一点。不仅如此,rclone 还可以让你使用命令行在不同网盘之间同步数据。

rclone 是一个命令行程序,支持 Windows、Linux、macOS 平台,用来与网盘进行数据同步,目前已支持的网盘种类非常多,包括 Google Drive、Dropbox、Microsoft One Drive 等等。

在 GitHub 上查看rclone 官网

关于 rclone 的安装请查看 安装教程

与 Google Drive 同步

首先是设置 Google API:

  1. 访问 Google API 控制台,并且使用 Google 账号登录;

  2. 选择一个项目 (project) 或新建一个项目;

  3. 在上方的 API 搜索框中键入 Google Drive 然后回车,找到搜索结果中的 Google Drive API:

    进入后,点击启用;

  4. 如果此前没有配置过“同意屏幕”,那么点击左侧菜单中的“配置同意屏幕”,选择目标用户类型为外部,应用名称可以填入“rclone”,然后填入自己的邮箱,gmail 即可,点击保存创建,最后在创建好的同意屏幕中,把“发布状态”从“测试”切换为“发布”;

  5. 点击左侧菜单的“凭据”,点击屏幕上方的“+创建凭据”,选择“OAuth 客户端 ID”,应用类型选择“桌面应用”,点击创建,然后就会显示 OAuth 客户端的 clinet_id 以及 client_secret,这两样东西后面会用到。

然后是添加网盘配置:

使用rclone config命令配置网盘,键入 n 来创建第一个网盘,取名叫 GD:

1
2
3
4
5
6
7
8
9
$ rclone config
No remotes found - make a new one
n) New remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
n/r/c/s/q> n
name> GD

然后选择网盘类型 (Storage),键入 drive,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Type of storage to configure.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
1 / 1Fichier
\ "fichier"
2 / Alias for an existing remote
\ "alias"
3 / Amazon Drive
\ "amazon cloud drive"
......
15 / Google Drive
\ "drive"
......
Storage> drive

键入之前获取的 clinet_id 以及 client_secret:

1
2
3
4
Google Application Client Id - leave blank normally.
client_id>
Google Application Client Secret - leave blank normally.
client_secret>

scope 键入 1,root_folder_id 回车默认,service_account_file 回车默认,Edit advanced config 键入 n,Use auto config 键入 y。

然后在自动打开的网页中登录 Google 账号,给予 rclone 修改 Google Drive 的权限。至此,创建网盘配置就完成了!

现在,我们就可以使用命令行来同步我们的数据了,比如我们可以将本地目录 ~/Documents/MyData/ 中的内容推送到 GD 网盘的 MyData/ 中:

1
$rclone sync ~/Documents/MyData/ GD:MyData/

自动化上传文件

我们可以编写脚本,每间隔一段时间就上传文件,这样就实现了网盘与本地的实时同步。

比如我的自动上传脚本:

1
2
3
4
5
6
7
#!/bin/bash
while true
do
sleep 3600
DATE=$(date +%Y%m%d)
rclone sync /Users/kyle/Documents/MyData/ GD:MyData_Backup/MyData_${DATE}
done

这个脚本每间隔 1 个小时将本地文件同步到网盘中,文件夹的命名为“名字+日期”的形式,这样的话,网盘中每天会新增一个文件夹,用于保留历史备份。


回忆症

“念旧“一般是指“怀念过去,觉得过去比现在好“。我就是一个极其念旧的人。例如,我觉得初中比大学和高中好,而小学又比初中好,至于小学之前,那是最快乐的时光了。(至于我为什么没有觉得高中比大学好,这是因为高中实在是太累太枯燥了,我实在不愿回忆起)。我知道这么想非常幼稚,毕竟人总是要长大,何况我马上都要参加工作了,总要面对更复杂的事情,让自己快乐也会变得越来越难。但我总是走不出来,每隔一段时间,就会想:“要是能够回到过去该有多好啊,那时的我没有这么多不快乐和烦恼”。不知从哪听来的一句话,说:“只有两种人会非常念旧,一是老人,二是对当下不满意的人”,那我自然是属于后者了,毕竟自从高中以来,我就对自己的生活不满意了。刚上大学时,想着大学能让我的生活有很大改观,可以有更多快乐,然而现在都快毕业了,也并没有快乐很多,关于这些,我想用之后的更多文章去说。

我的念旧,不仅仅在于上面写的,而更在于:“我恨不得能记住经历过的每一件事”。比如,如果我看了一部电影,我就会想记住电影的所有情节,如果在之后的某一天,我偶尔回忆起这部电影,但无法回忆起电影中的每一个情节,我就会有一种莫名的懊恼感和失落感,会感觉到过去的我,花在观看这部电影上的时间,全都被“偷走”、或“挖走”了一样。即便我能记得看完电影后的感受,但只要我无法记得电影中的每一个情节,我就是会不舒服。相反,如果我能够回忆起来的话,我会十分满足。同样的感觉还会出现在很多其他事情上,我偶尔会写便签,记录当时生活的一些事情和小小感受,但当我某天回看自己以前写过的便签,看到某一条内容,我就会拼命回想我自己当时写这条便签的近期,都发生了一些什么事情,同样是恨不得回忆起所有的细节,如果无法回忆到,我也会十分失落。

我不知道我的这种心理从何而来,说不清道不明。我不知道这个“症状”要怎么才能好,我试过在无法回忆具体细节时告诉自己不要失落,开心一些,但没什么效果,过了一段时间,另一件过去的事我无法回忆起来,我依然会失落。也许都不能称之为“念旧”了,姑且称之为“回忆症”吧。