Hello World

Github Page 与个人域名绑定

一个问题

在将sjtume的域名与Github Page 绑定时产生了一点困惑:
在 github 官方文档的 Setting up a custom subdomain 中有这样的警告:

Danger: Do not use wildcard DNS records (e.g. *.example.com) with GitHub Pages! A wildcard DNS record will allow anyone to host a GitHub Pages site at one of your subdomains.

这让我感到很奇怪:域名解析的 CNAME 明明指向的是我个人的 github page,为什么别人可以从我的域名跳转到别的 github page?

一种解答

背景知识 - DNS中的CNAME

A Canonical Name record (abbreviated as CNAME record) is a type of resource record in the Domain Name System (DNS) used to specify that a domain name is an alias for another domain, which is the “canonical” domain.
CNAME records must always point to another domain name, never directly to an IP address.

简单地看,CNAME 记录就是将对一个网址的访问转到另一个指定的主机上。在github page与个人域名绑定的过程中,对个人域名DNS解析增加一项指向username.github.io的解析,那么实际上对个人域名的请求最后到了github的服务器上。

这将产生一个问题:github的服务器上有无数用户的github page,如何判断应该返回哪个page?
这个问题有一种解释(实际上是错的):个人域名的DNS解析中的主机记录是确定的github page 例如访问 username.example.com 的个人域名,个人域名的CNAME主机记录设为 username.github.io 那么github的服务器根据得到的请求中的 username.github.io 中的 username来判断返回哪个用户的github page. 这是一个很容易理解的过程,然而这并不是真实的故事。
为什么这种解释是错误的: 事实上,CNAME中的主机记录并不是顶级域名,也就是说 username.github.io也有一个CNAME记录。可以用 dig username.github.io 验证:
"CNAME"
可以看到对某个用户的github page的访问最终解析到了github.map.fastly.net,而这个网址的A记录指向了最终处理请求的服务器地址(151.101.100.133)
这样看,对个人域名的解析过程就比较清晰了:

  1. 访问 username.example.com , example.com的CNAME解析主机记录为 username.github.io
  2. 请求这时指向了 username.github.io , 又被导到了 github.map.fastly.net
  3. github.map.fastly.net 的A记录的服务器处理请求

回到最开始的问题:

A wildcard DNS record will allow anyone to host a GitHub Pages site at one of your subdomains.

上文中错误解释错在:最终处理请求的服务器不是根据个人域名的CNAME中的username.github.io来返回page的,因为如果是这样,那对*.example.com的请求都将被解析到example.com的CNAME记录中那个固定的username.github.io ,例如bob.github.io,最终服务器将永远返回 bob 的 github page. 也就不存在上面那个任何人都可以将自己的page与 example.com 绑定了。

实际上,最终处理请求的服务器是根据最初的请求信息来判断应返回什么page的,所以将个人域名与github page绑定的过程中有一步是在 repository 中添加 CNAME 文件,指定绑定的域名。

完整的过程是这样的:

  1. 用户访问 username.example.com
  2. 该请求最终被github服务器处理,该服务器在所有github page repository 中寻找匹配的 CNAME 文件。如果某个 CNAME文件的内容正是 username.example.com,则返回该page

显然,如果用通配符*指定example.com的CNMAE记录,那么对 joe.example.com 的请求即便被解析到了 bob.github.io, 最终还是会由 github.map.fastly.net 处理请求,而这时服务器只关心哪个repository的CNAME文件是 joe.example.com,不在乎这个请求是从 bob.github.io那里转来的
因此一旦一个域名的CNAME记录是有通配符的,如*.example.com, 那么任意用户anyone(举个例子)只要将他的github page repository中的CNAME文件设为anyone.example.com,他就实现了自己的github page与example.com的绑定