BIND結合NGINX+PHP實現DNS服務器URL轉發

https://zhuanlan.zhihu.com/p/21785319 php


前幾天在公司分享會偶爾提及DNS,忽然提到域名運營商提供的URL轉發功能,即將指定的域名轉發到相關域名,且能夠在地址欄顯示或隱藏目標URL。爭論了好久,不少同窗都認爲是DNS服務器自身提供了這個功能。衆所周知,DNS服務器只提供域名的解析功能,而URL轉發是HTTP範疇,如下詳細說明下我本身的實現原理及過程。html

原理

大多數域名運營商都會提供URL轉發(國內此功能須要備案和審覈)功能,分顯示和隱藏兩種。咱們在實現的過程當中分兩個環節,即DNS和HTTP。一個URL轉發記錄對應DNS服務器兩條記錄,分別爲A或CNAME記錄和TXT記錄。A或CNAME記錄解析到本身的HTTP服務器,以用於後面處理URL轉發,這條記錄對用戶隱藏。TXT記錄是用戶在操做界面填寫的URL轉發目標地址和類型。DNS解析完成以後交由HTTP服務器,能夠用任何服務端語言編寫。nginx

實現過程

環境說明

  • 操做系統:CentOS 6(Vagrant)瀏覽器

  • DNS服務器:BIND-9.8.2 (yum)服務器

  • HTTP服務端:NGINX+PHP-FPM-5.3 (yum)app

  • 測試域名:ninjacn.comcurl

DNS服務器

DNS服務器由BIND搭建,經過yum直接安裝便可。下面截取主要的配置以供你們理解:ide

截取/etc/named.conf

options {
        listen-on port 53 { 127.0.0.1; };
        directory       "/var/named";
};
zone "ninjacn.com" IN {
        type master;
        file "ninjacn.com.zone";
};

截取/var/named/ninjacn.com.zone

$TTL 3H
@	IN SOA	ninjacn.com. root.ninjacn.com. (
					0	; serial
					1D	; refresh
					1H	; retry
					1W	; expire
					3H )	; minimum
	NS	@
	A	127.0.0.1
u0	A	127.0.0.1
u1	A	127.0.0.1
u0	TXT	0|http://www.baidu.com/0.html
u1	TXT	1|http://www.baidu.com/1.html

共解析2條URL轉發(u0和u1),它們的A記錄都對應本身的HTTP服務器,TXT記錄對應真實的URL轉發目標地址信息,TXT記錄由2部分組成,由|分隔,左邊部分爲URL類型(顯示或隱藏),右邊部分爲真正的目標地址。測試

HTTP服務端

瀏覽器發起相關域名的請求以後,咱們本身的服務器(DNS服務器A記錄)會處理這個請求。服務端接受請求後會根據主機頭向DNS服務器查詢相應的TXT記錄,獲取到DNS記錄以後根據類型(0表明顯示URL,1表明隱藏URL)返回HTTP響應信息。url

  • 當類型爲0時,HTTP服務端返回301或302狀態碼,響應頭的Location是具體的URL目標地址。

  • 當類型爲1時,HTTP服務端返回包含iframe的HTML信息。iframe的src屬性爲具體的URL目標地址。

具體實現看如下PHP代碼。

Nginx配置文件

泛域名配置,全部請求都會由此server塊處理。

server {
    listen       80;
    server_name  _;

    location / {
        root   /usr/share/nginx/html;
        index  index.php;
    }
    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /usr/share/nginx/html$fastcgi_script_name;
        include        fastcgi_params;
    }
}

PHP實現轉發

<?php
/**
 * @author ninjacn <x@ninjacn.com>
 * 根據獲取到的主機名獲取相應TXT記錄,並返回相應信息
 */

define('TARGET_SHOW', 0); //顯示url
define('TARGET_HIDE', 1); //隱藏url

$hostname = $_SERVER['HTTP_HOST'];
$record = dns_get_record($hostname, DNS_TXT);

list($type, $url) = array('', '');
if($record) {
    if(isset($record[0]['txt'])) {
	list($type, $url) = explode('|', $record[0]['txt']);
    }
}

if(empty($type) && empty($url)) {
    exit(110);
}

if($type == TARGET_HIDE) {
    header('Location: '.$url);
} elseif ($type == TARGET_SHOW) {
    $html = "<iframe src='".$url."'></iframe>";
    echo $html;
}

測試

顯示url - u0.ninjacn.com

HTTP狀態碼爲200,不作轉發處理,真正的網頁地址在iframe的src屬性指定。

[root@localhost ~]# curl -i u0.ninjacn.com
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Thu, 28 Jul 2016 19:31:40 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.3.3

<iframe src='http://www.baidu.com/0.html'></iframe>

隱藏URL - u1.ninjacn.com

HTTP狀態碼爲302,目標地址在響應頭的Location屬性。

[root@localhost ~]# curl -i u1.ninjacn.com
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.10.1
Date: Thu, 28 Jul 2016 19:36:59 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.3.3
Location: http://www.baidu.com/1.html
相關文章
相關標籤/搜索