У меня (как и у многих web-разработчиков) имеется с десяток сайтов которые необходимо где-то размещать (хостить).
Сайты практически не приносят прибыли, поскольку это какие-то старые работы (по разным причинам не пошедшие в продакшн), домашняя страница, сайт заведенный красивой почты и тому подобное. Но в то же время эти сайты жалко бросать, а потому приходится каждый месяц на них тратить вполне реальные деньги чтобы покупать хостинг. Деньги, прямо скажем небольшие, но тем не менее их жалко, поскольку отдачи от сайтов никакой нет.
В то-же время в наличии имеется:
Но не имеется ключевого — статического IP. Если бы он был, то все было-бы намного проще и данную статью я бы точно не писал. А выдавать статический IP мой МТС абсолютно не желает (если только я не подключусь как бизнес-клиент).
Разумеется есть всем известные Dynamic DNS сервисы вроде noip.com, но они успешно решают лишь задачу удаленного доступа к нашему серверу (по SSH или FTP), но для хостинга совершенно нам не подходят, поскольку в настройках домена на DNS-сервере нам нужно обязательно прописать A-запись с реальным IP-адресом (а не ссылку на наш виртуальный домен).
Я не буду останавливаться на том, как настроить linux сервер (и тем более как его выбрать), поскольку предполагаю, что он у вас уже есть. Также я не буду подробно расписывать настройки nginx и Apache, поскольку опять-таки предполагаю, что вы с этим справитесь самостоятельно.
Первое с чем у меня возникли проблемы — это как перенаправить посетителей с моих доменов (у меня есть 2 домена) на мой домашний сервер. То есть чтобы клиент который набрал domain.com попал ровно на мой домашний сервер с учетом того, что на нем каждый день меняется IP-адрес.
Для решения нам нужно настроить DNS-сервер, а именно следующие записи: SOA, NS, MX, A, CNAME. Важно чтобы мы имели возможность настройкой TTL (time to live), поскольку время жизни наших записей должно быть очень небольшим, буквально 60-120 секунд. В противном случае при смене IP-адреса сервера пользователи долго не смогут попасть на наш сервер (из-за кеширования).
Итак, нам нужен DNS сервер, варианты решения:
Рассмотрим оба варианта.
Для этого есть ряд бесплатных сервисов, из которых самым популярным является freedns.afraid.org. На таких сервисах можно добавить свой домен(ы) и получить возможность через API обновлять у них A-запись при помощи небольшого скрипта.
Выглядит вполне неплохо, но подвох в том, что эти сервисы оставляют за собой право довешивать к вашему домену поддомены третьего уровня. То есть вы зарегистрировали у них user.ru, а они спокойно довешают свои сайты вида hello.user.ru, shop.user.ru и так далее. Разумеется от этого можно отказаться, но… за деньги. Платить деньги за такие сервисы смысла я не вижу, поскольку за сравнимые деньги вы можете купить полноценный хостинг на каком-нибудь провайдере без всяких плясок вокруг DNS настроек.
Остальные сервисы рассматривать не будем, а сосредоточимся на втором варианте.
Для этого варианта у нас, во-первых, должен быть DDNS-домен (который обновляется при смене IP), например, domain.ddns.net, а во-вторых, придется установить и настроить BIND на нашем сервере.
Всего необходимо сделать ровно 5 шагов. Везде под словами «domain» или «domain.ru» подразумевается ваше имя домена (короткое или полное).
Почему 2 или 3? Потому, что ряд регистрантов не разрешит вам использовать домен только с одним NS-сервером. Самое обидно, что не все про это скажут — ваш домен просто не будет работать, но вы не будете понимать почему.
Тут все просто — идем на noip.com, там регистрируем аккаунт и добавляем 3 бесплатных поддомена (больше 3 не даст).
Устанавливаем BIND:
Создаем зоны (по одной зоне на каждый наш домен):
с содержимым:
и собственно файл с настройками зоны:
и пишем внутри:
Примечание: обращаю внимание, что TTL устанавливаем равным 60 секунд. В файле /etc/bind/named.conf.local добавляем подключение нашей зоны:
Все, рестартуем BIND:
И глянем /var/log/syslog чтобы там не было сообщений об ошибках
Идем в панель управления регистратора и там в настройках нашего домена в качестве NS-серверов указываем созданные DDNS-поддомены:
После этого возможно придется подождать несколько часов (или даже сутки) пока настройки среплицируются между всеми серверами.
Мой роутер поддерживает обновление IP-адреса на одном домене, но мне нужно это делать сразу для 3-х доменов. Плюс нам надо обновлять IP-адрес в конфиге BIND'а, поэтому напишем скрипт который будет делать:
Сам скрипт пусть будет на шелле:
Скрипт нужно запускать под рутом (чтобы ему хватило прав обновлять конфиги BIND'а и рестартовать его). Добавляем в crontab рута его запуск каждую минуту:
Пару слов про определение текущего IP-адреса. В скрипте выше это делается через резолвинг DDNS-поддомена domain.ddns.net. То есть сначала наш роутер его туда прописывает, а потом мы читаем. Это не очень хороший вариант, поскольку мы завязываемся на роутер и можем потерять несколько минут пока на DDNS-поддомене обновится IP-адрес на актуальный. Все это время наш сервер будет недоступен.
Поэтому у себя я использовал улучшенный вариант, который заодно не лазит в интернет:
В данном варианте мы загружаем главную страницу роутера (через http), дальше регэкспом находим на ней текущий IP-адрес. Разумеется, этот вариант подходит далеко не всем, но на DD-WRT прошивках работает.
Про необходимость настроить обращение к DDNS-сервису я уже писал, но еще не забывайте про необходимость настроить форвардинг портов на вашем роутере:
Итак, что я получил в итоге:
По моим замерам, когда МТС (мой провайдер) обновляет мне IP-адрес, то мои сайты начинают работать спустя где-то 2 минуты. Это вполне приемлемо для меня.
P.S. Если кому-то понравилась данная заметка, то я могу написать вторую часть, где расскажу как настроить работу с использованием DNS-хостинга Яндекса. Это позволит отказаться от собственного DNS-сервера, отказаться от DDNS-поддоменов, плюс чуть улучшит надежность работы (поскольку DNS-сервер никогда не будет менять свой IP). Именно такую схему я использую в настоящий момент.
Сайты практически не приносят прибыли, поскольку это какие-то старые работы (по разным причинам не пошедшие в продакшн), домашняя страница, сайт заведенный красивой почты и тому подобное. Но в то же время эти сайты жалко бросать, а потому приходится каждый месяц на них тратить вполне реальные деньги чтобы покупать хостинг. Деньги, прямо скажем небольшие, но тем не менее их жалко, поскольку отдачи от сайтов никакой нет.
В то-же время в наличии имеется:
- Домашний сервер на Ubuntu
- Быстрый ethernet-интернет от МТС
Но не имеется ключевого — статического IP. Если бы он был, то все было-бы намного проще и данную статью я бы точно не писал. А выдавать статический IP мой МТС абсолютно не желает (если только я не подключусь как бизнес-клиент).
Разумеется есть всем известные Dynamic DNS сервисы вроде noip.com, но они успешно решают лишь задачу удаленного доступа к нашему серверу (по SSH или FTP), но для хостинга совершенно нам не подходят, поскольку в настройках домена на DNS-сервере нам нужно обязательно прописать A-запись с реальным IP-адресом (а не ссылку на наш виртуальный домен).
Что делать?
Я не буду останавливаться на том, как настроить linux сервер (и тем более как его выбрать), поскольку предполагаю, что он у вас уже есть. Также я не буду подробно расписывать настройки nginx и Apache, поскольку опять-таки предполагаю, что вы с этим справитесь самостоятельно.
Первое с чем у меня возникли проблемы — это как перенаправить посетителей с моих доменов (у меня есть 2 домена) на мой домашний сервер. То есть чтобы клиент который набрал domain.com попал ровно на мой домашний сервер с учетом того, что на нем каждый день меняется IP-адрес.
Для решения нам нужно настроить DNS-сервер, а именно следующие записи: SOA, NS, MX, A, CNAME. Важно чтобы мы имели возможность настройкой TTL (time to live), поскольку время жизни наших записей должно быть очень небольшим, буквально 60-120 секунд. В противном случае при смене IP-адреса сервера пользователи долго не смогут попасть на наш сервер (из-за кеширования).
Итак, нам нужен DNS сервер, варианты решения:
- Используем сервисы которые предоставляют нам DNS-хостинг
- Используем собственный DNS-сервер в связке с DDNS-доменом
Рассмотрим оба варианта.
Используем сервисы которые предоставляют нам DNS-хостинг
Для этого есть ряд бесплатных сервисов, из которых самым популярным является freedns.afraid.org. На таких сервисах можно добавить свой домен(ы) и получить возможность через API обновлять у них A-запись при помощи небольшого скрипта.
Выглядит вполне неплохо, но подвох в том, что эти сервисы оставляют за собой право довешивать к вашему домену поддомены третьего уровня. То есть вы зарегистрировали у них user.ru, а они спокойно довешают свои сайты вида hello.user.ru, shop.user.ru и так далее. Разумеется от этого можно отказаться, но… за деньги. Платить деньги за такие сервисы смысла я не вижу, поскольку за сравнимые деньги вы можете купить полноценный хостинг на каком-нибудь провайдере без всяких плясок вокруг DNS настроек.
Остальные сервисы рассматривать не будем, а сосредоточимся на втором варианте.
Используем собственный DNS-сервер в связке с DDNS-доменом
Для этого варианта у нас, во-первых, должен быть DDNS-домен (который обновляется при смене IP), например, domain.ddns.net, а во-вторых, придется установить и настроить BIND на нашем сервере.
Всего необходимо сделать ровно 5 шагов. Везде под словами «domain» или «domain.ru» подразумевается ваше имя домена (короткое или полное).
1. Настроить 2 или 3 DDNS-поддомена
Почему 2 или 3? Потому, что ряд регистрантов не разрешит вам использовать домен только с одним NS-сервером. Самое обидно, что не все про это скажут — ваш домен просто не будет работать, но вы не будете понимать почему.
Тут все просто — идем на noip.com, там регистрируем аккаунт и добавляем 3 бесплатных поддомена (больше 3 не даст).
2. Настраиваем собственный DNS-сервер
Устанавливаем BIND:
$ sudo apt-get install bind9
Создаем зоны (по одной зоне на каждый наш домен):
$ sudo nano /etc/bind/zones.my
с содержимым:
zone "domain.ru" {
type master;
file "/etc/bind/db.domain.ru";
};
и собственно файл с настройками зоны:
$ nano /etc/bind/db.domain.ru
и пишем внутри:
;
; BIND data file for local loopback interface
;
$TTL 60
@ IN SOA domain.ru. admin.domain.ru. (
1477015437 ; Serial
10800 ; Refresh
3600 ; Retry
604800 ; Expire
1800 ) ; Negative Cache TTL
@ IN NS domain.ddns.net.
@ IN NS domain.ddnsking.com.
@ IN NS domain.myftp.biz.
@ IN MX 10 mx.yandex.net.
@ IN A 1.2.3.4
mail IN CNAME domain.mail.yandex.net.
* IN CNAME domain.ru.
Примечание: обращаю внимание, что TTL устанавливаем равным 60 секунд. В файле /etc/bind/named.conf.local добавляем подключение нашей зоны:
include "/etc/bind/zones.my";
Все, рестартуем BIND:
$ sudo service bind9 restart
И глянем /var/log/syslog чтобы там не было сообщений об ошибках
3. Настроить наш домен(ы)
Идем в панель управления регистратора и там в настройках нашего домена в качестве NS-серверов указываем созданные DDNS-поддомены:
nameserver1 = domain.ddns.net
nameserver2 = domain.ddnsking.com
nameserver3 = domain.myftp.biz
После этого возможно придется подождать несколько часов (или даже сутки) пока настройки среплицируются между всеми серверами.
4. Настроить периодическое обновление IP-адресов
Мой роутер поддерживает обновление IP-адреса на одном домене, но мне нужно это делать сразу для 3-х доменов. Плюс нам надо обновлять IP-адрес в конфиге BIND'а, поэтому напишем скрипт который будет делать:
- Определять наш внешний IP-адрес
- Проверять изменился ли IP адрес, если не изменился, то ничего делать не надо
- Обновлять IP-адрес у всех DDNS-поддоменов через API сервиса noip.com
- Прописывать новый IP адрес в конфиг BIND'а
- Перезапускать BIND
Сам скрипт пусть будет на шелле:
#!/bin/sh
# This script works via noip.com service + local Bind server
# Settings
ZONES_CONFIG=zones.my
IP_FILE=./current_ip.txt
DDNS_USER=user
DDNS_PASS=password
DDNS_HOST=domain.ddns.net
DDNS_HOSTS=domain.ddns.net,domain.ddnsking.com,domain.myftp.biz
# Start
DATE=$(date +"%Y-%m-%d %H:%M:%S")
# detect an external IP
IP=$(dig +short $DDNS_HOST)
if [ $? -ne 0 ] || [ -z $IP ] || [ $IP = "0.0.0.0" ] ; then
echo "$DATE Can't detect a remote IP. Aborting."
exit 1
fi
# verify IP changing
PREV_IP="(unknown)"
if [ -e $IP_FILE ] ; then
PREV_IP=$(cat $IP_FILE)
fi
if [ $IP = $PREV_IP ] ; then
echo "$DATE IP '$IP' has not changed"
else
echo "$DATE IP has been changed from '$PREV_IP' to '$IP'"
echo "$DATE IP will be updated on DDNS server"
/usr/bin/curl -u $DDNS_USER:$DDNS_PASS "https://dynupdate.no-ip.com/nic/update?hostname=$DDNS_HOSTS&myip=$IP"
fi
echo $IP > $IP_FILE
# check BIND config
cd /etc/bind
if [ ! -e $ZONES_CONFIG ] ; then
echo "$DATE File $ZONES_CONFIG not found!"
exit 1
fi
# read the list of active zones
ZONE_FILES=$(grep file $ZONES_CONFIG | grep -v ^# | perl -ne '/file "(.+)"/ && print "$1\n"')
for ZONE_FILE in $ZONE_FILES; do
echo "$DATE Process the zone config $ZONE_FILE"
cat $ZONE_FILE | perl -ne "s/([\t ]+IN[\t ]+A[\t ]+)[\d\.]*/\${1}${IP}/; print \${_}" > $ZONE_FILE.tmp
if [ $(diff -w $ZONE_FILE $ZONE_FILE.tmp | wc -l) -ne 0 ] ; then
# update serial number
STAMP=$(date +%s)
cat $ZONE_FILE.tmp | perl -ne "s/\d+(?=.+Serial)/$STAMP/; print \${_}" > $ZONE_FILE
# reload BIND
service bind9 reload
echo "$DATE Config $ZONE_FILE is updated"
else
# nothing to do
rm $ZONE_FILE.tmp
echo "$DATE Config $ZONE_FILE is NOT changed"
fi
done
Скрипт нужно запускать под рутом (чтобы ему хватило прав обновлять конфиги BIND'а и рестартовать его). Добавляем в crontab рута его запуск каждую минуту:
* * * * * cd /home/root && ./update_bind_config.sh >> /var/log/update_bind_config.log
Пару слов про определение текущего IP-адреса. В скрипте выше это делается через резолвинг DDNS-поддомена domain.ddns.net. То есть сначала наш роутер его туда прописывает, а потом мы читаем. Это не очень хороший вариант, поскольку мы завязываемся на роутер и можем потерять несколько минут пока на DDNS-поддомене обновится IP-адрес на актуальный. Все это время наш сервер будет недоступен.
Поэтому у себя я использовал улучшенный вариант, который заодно не лазит в интернет:
IP=$(perl -le 'use LWP::UserAgent; my $content=LWP::UserAgent->new->get("http://router")->decoded_content(); $content =~ q(<span id="wan_ipaddr">([\d\.]+)</span>); print $1')
В данном варианте мы загружаем главную страницу роутера (через http), дальше регэкспом находим на ней текущий IP-адрес. Разумеется, этот вариант подходит далеко не всем, но на DD-WRT прошивках работает.
5. Настройка роутера
Про необходимость настроить обращение к DDNS-сервису я уже писал, но еще не забывайте про необходимость настроить форвардинг портов на вашем роутере:
- HTTP — TCP, 80-ый порт
- DNS — TCP+UDP, 53 порт
Вывод
Итак, что я получил в итоге:
- Мои сайты живут на домашнем сервере, за который я никому не плачу;
- Мои домены резолвятся через мой собственный DNS-сервер, время жизни записей 1 минута, то есть обновление происходит очень быстро;
- В качестве NS-записей указаны не реальные IP-адреса (которые у меня часто меняются), а DDNS-поддомены;
- Актуальность записей в DDNS-поддоменах и в конфиге моего DNS-сервера обеспечивается автоматически, без какого-либо вмешательства со моей стороны.
По моим замерам, когда МТС (мой провайдер) обновляет мне IP-адрес, то мои сайты начинают работать спустя где-то 2 минуты. Это вполне приемлемо для меня.
P.S. Если кому-то понравилась данная заметка, то я могу написать вторую часть, где расскажу как настроить работу с использованием DNS-хостинга Яндекса. Это позволит отказаться от собственного DNS-сервера, отказаться от DDNS-поддоменов, плюс чуть улучшит надежность работы (поскольку DNS-сервер никогда не будет менять свой IP). Именно такую схему я использую в настоящий момент.