玩一玩泛域名解析

玩一玩泛域名解析

先看看作品的最终效果。访问 http://XXX.我喜欢你.top:521/ 会返回字符串 一直都很喜欢 XXX 呢
其中 “XXX” 可以改为任意字符(中文也可以)。

实现原理其实很简单。首先是泛域名解析。泛域名解析就是把某一级子域名全部解析到同一IP(A记录)。
比如将 *.test.uint128.com 解析到 127.0.0.1
这样访问 任意字符.test.uint128.com 都会指向 127.0.0.1

那么, 服务器怎么知道用户是从哪个域名访问过来的呢?
这里利用了 HTTP 协议头部的 Host 字段。
Host 字段记录了域名, 使得服务器可以分辨用户访问服务器时使用的域名。
这个字段就是用来实现一台服务器部署多个网站的效果。
比如把 baidu.comjd.com 都部署到 1.1.1.1 这台服务器上。
为了区分两个网站, 浏览器在发出请求时, 要在 Host 字段上记录域名。
服务器在分析 HTTP 协议头部的时候, 就能正确地把请求转发给不同网站的程序。
所以只要分析 HTTP 请求的头部, 读取 Host 字段的值, 就能知道请求是通过哪个域名发来的了。

最后一个技术点, 就是让 URL 支持中文。请求参数部分如果要支持中文, 一般使用 百分号编码 (Percent-encoding, 有时候也叫 URL 编码)。这种编码就是把 GBK 编码或者 UTF-8 编码的字符串, 用 16 进制表示, 再加上百分号。比如 %C4%E3%BA%C3%CA%C0%BD

但是域名部分要支持中文, 可就不能用百分号编码了, DNS 服务器不认识。域名部分要支持非 ASCII 字符, 一般用 Punycode (国际化域名编码)。
它长得像这样 xn--rhq34a65tw32a, 一般以 “xn—“ 开头, 中间是ASCII 字符。

虽然上面说了很多, 但是实现这个小作品非常简单: 买个域名、泛域名解析、写个程序。
这个程序的工作也很简单: 读取 HTTP 请求头部的 Host 字段, 返回相应的欢迎文本。
我这个程序用 C# 来实现, 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[HttpGet]
public IActionResult Home()
{
// idnMapping 用于将 Punycode 转化为 Unicode 字符串
IdnMapping idn = new IdnMapping();
// 读取 HTTP请求头部的 Host 字段
string rawHost = Request.Headers["host"];
// 将 Punycode 转化为 Unicode 字符串
string host = idn.GetUnicode(rawHost);
// 使用正则表达式匹配域名中的姓名
Regex regex = new Regex(@"([^.]+)(.*?)");
Match match = regex.Match(host);
string info_name = match.Groups[1].Value;
// 返回对应的欢迎文本
string text = $"一直都很喜欢 {info_name} 呢!";
return Ok(text);
}

枯燥。

作者

uint128.com

发布于

2020-04-06

更新于

2022-08-22

许可协议

评论