PowerDNS URL records and redirector
В PowerDNS есть пара плюшек, которые я раньше не замечал. Одну из них - записи "URL" я сегодня попробовал, настроил и остался вполне доволен.
Что же такое URL-запись? Это фича PowerDNS, при помощи которой можно делать редирект домена на заданный URL.
Например, запись выглядит как
[cc lang="text"]
some.domain.com URL http://other.domain.com/some_domain_com
[/cc]
На самом деле в поле со значением записи может быть ссылка куда угодно.
В конфиге сервера нужно указать
[cc lang="ini"]
...
fancy-records=yes
urlredirector=77.120.99.180
...
[/cc]
Когда приходит запрос к DNS'у для домена some.domain.com отдается 77.120.99.180, указанный в конфиге, как если бы это была обычная "А"-запись.
Браузер отрезолвив имя идет на http://some.domain.com. На этом адресе висит http-сервер (я повесил lighttpd), у которого скрипт лезет в БД и для указанного домена ищет соответствующую ему URL-запись и редиректит браузер туда. Все просто и тривиально.
Для lighttpd у меня конфиг дополнился такими строками:
[cc lang="ini"]
$SERVER["socket"] == "77.120.99.180:80" {
$HTTP["host"] =~ "(.*)" {
magnet.attract-raw-url-to = ("/var/www/lighttpd/pdns-url-redirector.lua")
}
}
[/cc]
То есть все что приходит незамедлительно обрабатывается упомянутым lua-скриптом. Почему lua? С ним работает mod_magnet, и мне было интересно написать этот скриптик. Вот он:
[cc lang="lua"]
require "luasql.mysql"
env = assert (luasql.mysql())
con = assert (env:connect("dnsdb", "dns_user", "dns_pass_for_readonly_records_table", "localhost"))
domain = lighty.request["Host"]
mysql_replacements = {
["\0"] = "\\0",
["\n"] = "\\n",
["\r"] = "\\r",
["\'"] = "\\\'",
["\""] = "\\\"",
["\026"] = "\\Z",
["\b"] = "\\b",
["\t"] = "\\t",
}
function fixsql (s)
return (string.gsub (tostring (s), "[%z\n\r\'\"\026\b\t]",
function (str)
return mysql_replacements [str] or str
end ))
end -- fixsql
cur = assert (con:execute( string.format("SELECT content FROM records WHERE `type` = 'URL' AND `name` = '%s'", fixsql(domain) ) ) )
result = cur:fetch()
if result then
redirect_to = string.format("%s", result)
else
redirect_to = "http://daemons.org.ua/"
end
cur:close()
con:close()
env:close()
--lighty.content = { string.format("SELECT content FROM records WHERE `type` = 'URL' AND `name` = '%s'", fixsql(domain) ) }
--lighty.header["Content-Type"] = "text/plain"
--return 200
lighty.header["Location"] = redirect_to
return 301
[/cc]
Комментарий начинается с "--". Закоментарены строки для отладки скрипта.
Для соединения с мускулем из lua доставил пакет liblua5.1-sql-mysql-2.
Скрипт писал долго, но это было интересно. И небесполезно =)
UPD: во избежание DoS/DDoS атаки на мускуль возможны два варианта апгрейда метода: 1. По крону раз в 5 минут генерить sqlite-БД состоящую из одной таблицы из двух полей - domain, target 2. Раз в 5 минут генерить сам скрипт с вынесенными в него в виде хеша записями. Тогда скрипт вообще никуда подглядывать не будет.
UPD: во избежание DoS/DDoS атаки на мускуль возможны два варианта апгрейда метода: 1. По крону раз в 5 минут генерить sqlite-БД состоящую из одной таблицы из двух полей - domain, target 2. Раз в 5 минут генерить сам скрипт с вынесенными в него в виде хеша записями. Тогда скрипт вообще никуда подглядывать не будет.