之前为了穿墙和正常访问校园网两不误而在90上架了个DNS。昨天facebook hackercup里穿墙的90代理也是给力的,不过facebook就不怎么给力了 ╮(╯▽╰)╭ 扯远了,虽然不是最初的动机,不过即然架设好了DNS Server就会自然而然的想折腾一下,提供一些内部用的短域名。比如直接将zoj, nhd, icpc, printer解析成ZOJ, NexusHD, ZJU ICPC-HOST和218打印机的IP。不过为了省事,最后是改用了一个自己yy的.acm的根域名,只要简单修改bind9的配置文件,在/etc/named.conf.local中新加一个zone:

zone "acm." {
	type master;
	file "/etc/bind/acm.zone";
};

并且新建一个文件/etc/bind/acm.zone内容如下:

$TTL	604800
@	IN	SOA	acm. root.acm. (
			      1		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			 604800 )	; Negative Cache TTL
;
@	IN	NS	acm.
@	IN	A	10.71.101.90
9	IN	A	10.71.101.9
;; ...
70	IN	A	10.71.101.70
90	IN	A	10.71.101.90
90	IN	AAAA	2001:da8:e000:90:0:5efe:10.71.101.90
192	IN	A	10.71.101.192
zoj	IN	CNAME	acm.zju.edu.cn.
watashi	IN	CNAME	watashi.ws.

A记录对应ipv4,AAAA记录对应ipv6,CNAME记录对应别名。于是都可以如法炮制,其中特殊符号@代表current origin,也就是没有任何.的acm,而zoj对应的是zoj.acm,并会转到acm.zju.edu.cn上。注意最后有一个点,和url中的/类似,如果以.结尾表示是绝对的,而不以.结尾的则是相对的。

当然也可以邪恶一把,比如修改并加入两个zone,并加入下面的zone file:

$TTL	604800
$ORIGIN	shouji.360.cn.
@	IN	SOA	shouji.360.cn. root.shouji.360.cn. (
			      1		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			 604800 )	; Negative Cache TTL
;
@	IN	NS	shouji.360.cn.
shouji.360.cn.	IN	A	250.250.250.250

$TTL	604800
$ORIGIN	mail.139.com.
@	IN	SOA	mail.139.com. root.mail.139.com. (
			      1		; Serial
			 604800		; Refresh
			  86400		; Retry
			2419200		; Expire
			 604800 )	; Negative Cache TTL

@	IN	NS	mail.139.com.
mail.139.com.	IN	A	209.85.227.17	; mail.google.com
mail.139.com.	IN	A	119.147.15.56	; mail.qq;com

前面做的事情就是流氓了一把360,把shouji.360.cn解析到了不存在的IP 250.250.250.250,于是访问将会得到诸如Connection Timeout(连接超时)的错误。不知道生活在天朝的同学们是不是对此似曾相识呢 (  ̄ー ̄) 第二个就要更流氓了,如果你访问mail.139.com,那么实际可能随机访问到gmail或者qq邮箱,这也是个做负载均衡的例子,嘛,我只是建议别用139邮箱啦 >▽< 你懂的。

然后猛犸同学给了个不错的建议,就是利用这个DNS,能不能做到在地址栏里输入zoj2011之类的题号的时候就直接跳转对应题目的页面上去。当然DNS直接是做不了这个事的,DNS联系的是domain和ip address这两样东西,和http都八杆子打不着,而题目页面还是一个具体的url的http请求。不过仔细想一想其实分两步做就很简单了,简单来说就是泛域名+根据HOST重定向。所谓泛域名其实就是给一个origin下面所有未定义的域名一个默认结果,只需要在之前的acm.zone文件最后加上一行:

*	IN	CNAME	90

这样诸如对a-very-very-long-long-name.acm这样为定义的域名就会转为90.acm的访问了。然后我们在90上重定向这些请求。然后在说明一下HOST,在HTTP/1.1中HOST是唯一一个必须的header,服务器可以利用指向统一ip的不同域名架设不同的virtual host。比如说http://watashi.ws/, http://zjuicpc.watashi.wshttp://cc98.watashi.ws/指向的是同一个IP,但访问的确是不同的网站。当然不可能在apache的配置文件里写上成千上万个virtual host,这种时候就要请程序出马了。

其实只要用下面这段简单的php代码替换掉原本90上原本的主页就可以了:

<?php
$url = array(
	'zoj' => 'http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=',
	'cli' => 'http://acmicpc-live-archive.uva.es/nuevoportal/data/problem.php?p=',
	'sgu' => 'http://acm.sgu.ru/problem.php?contest=0&problem=',
	);

$host = strtolower($_SERVER['HTTP_HOST']);
if (preg_match('/^([a-z]+)(\d+)\.acm$/', $host, $ret)) {
	$oj = $ret[1];
	$id = $ret[2];
	if ($url[$oj]) {
		header("HTTP/1.1 301 Moved Permanently");
		header("Location: $url[$oj]$id");
		exit();
	}
}
echo file_get_contents('./index.html');

index.php获得HOST,并判断这是不是一个OJ的题号,如果是,那么301重定向,否则返回原本的主页index.html。然后还要稍微修改apache的配置

DirectoryIndex index.php index.html

让index.php的优先级比index.html更高,成为默认主页。最后测试一下,诸如zoj2011.acm, cli5000.acm, sgu400.acm都被重定向到了正确的题目页面,而90原本的主页也能正常访问,大功告成 φ(゜▽゜*)♪

4 Responses to “再折腾一下DNS,定制内部用域名解析”
  1. fookwood says:

    shi哥可不可以在zoj上添加一个新功能,主页有个输入框,输入题号提交之后,就可以直接跳转到相应的题目.有时候网通访问zoj速度实在令人汗颜,而且直接改网址的话不能跳到正确的题目上……

    • watashi says:

      直接改网址应该没问题吧,注意要用problemCode=,而不是problemId=
      需求会考虑的,不过现在的ZOJ暂时不想动它,会和开发者说或者想其它办法的

  2. Navi says:

    mm是题霸

  3.  
Leave a Reply