Переезд на новый VDS

Вот уже 7-й год я пользуюсь услугами FirstVDS, и я впервые написал об этом в статье Лучший хостинг в своем классе еще в 2008 году. С тех пор многое изменилось, и некоторые изменения пошли в лучшую сторону.

Недавно у них появились уж очень вкусные тарифы, которые по ценам приблизились к европейским; но старым клиентам на FreeBSD 6 эти тарифы были недоступны и для того, чтобы воспользоваться новыми тарифами, пришлось заказать новый VDS, перенести сайты и отказаться от старого.

Первые впечатления были резко отрицательными, т. к. панель управления ISP Manager 5 очень и очень сырая. Импорта пользователей и сайтов из ISP Manager 4 не предусмотрено, настроить что-либо без глюков в нем проблематично. Но с другой стороны, они не навязывают использование этой панели. В общем, я наваял пару-тройку скриптов по добавлению новых доменов в apache, nginx и в bind — скриптами это делать быстрее, надежнее и лучше.

Вторая неприятность — IP адрес VDS на московской площадке определяется в базе GeoIP как бельгийский, и в результате чего мой сервис Просмотр сайтов с московского IP-адреса (Proxy View) стал показывать сайты так, как будто вы находитесь в Брюсселе, а не в Москве. Я приношу искренние извинения всем, кто пользовался моим сервисом — но тут я ничего не могу поделать. Возможно когда-нибудь в Maxmind одумаются и изменят запись для моего айпишника; но пока сервис работает как есть и показывает бельгийскую выдачу поисковиков — может, кому-то и пригодится.

Еще одна претензия к FirstVDS — это скорость реакции техподдержки на сообщения о проблемах с их стороны. При заведении нового VDS мой айпишник не сразу прописался в их базах маршрутизации, поэтому VDS не был доступен. Проблему они решили достаточно быстро — в тот же день, но сам факт возникновения таких ошибок не по моей вине немного настораживает. Хотя их тоже можно понять, в бесплатные запросы техподдержки наверняка валится множество сообщений и они их просматривают в порядке очереди с низким приоритетом.

Во всех остальных отношениях меня полностью устраивает их хостинг, а особенно — партнерская программа и программа лояльности.

Прощай, Google App Engine!

Это завершающая статья про Google App Engine. Я принял решение отказаться от использования GAE в своих проектах.

Сначала платформа Google App Engine мне показалась очень интересной. Я даже наваял на ней пару тестовых приложений, и когда меня все устроило, запустил несколько более-менее серьезных проектов на GAE.

Потом выяснилось, что Google стал блокировать доступ к сайтам на GAE по непонятным причинам, а спустя какое-то время даже прикрыл свой проект appgallery.appspot.com, написанный на GAE и предназначенный для популяризации этой платформы.

Такой зависимости от капризов гугла я терпеть не мог, и решил уйти с платформы Google App Engine.

Когда я забрал данные из хранилища в Google App Engine в формате sqlite3, я думал, что сконвертировать их, например в mysql, будет совсем не сложно.

Я ошибался. Данные в дампе оказались нечитаемыми, и с ними нормально работать мог только движок Google App Engine. Поэтому мне пришлось сделать реэкспорт данных из хранилища GAE в другой читабельный формат.

К счастью, bulkloader умеет экспортировать данные и в других форматах, например, CSV или XML. Про экспорт в XML есть хорошая статья на Хабре, где по полочкам и разложено, как настроить bulkloader.yaml для корректного преобразования данных в XML.

Так как сайты на платформе GAE может хостить только Google, платформа оказалась тупиковой ветвью в развитии фреймворков на Python, использовать ее стало бесполезно и даже опасно. Уж лучше писать на Django, чем бездарно тратить время на GAE.

Как свалить с платформы Google App Engine

Логотип Google App Engine

Примерно с 17 февраля 2011 года гугл без предупреждения стал блокировать доступ к сайтам на платформе GAE. Причем блокировались IP адреса из Германии, Канады, США и многих других “правильных” стран. Прошло 3 месяца, а воз и ныне там, что-либо менять они не собираются.

При таком раскладе можно только распрощаться с этой говноплатформой, но сделать это не так-то просто. Очень жаль потраченного времени на написание CMS под GAE, разработку шаблонов, да и времени на миграцию остается не так много. Но тем не менее, если вам дороги постоянные клиенты, Google не оставляет другого выбора.

К счастью, для работы с приложениями на платформе GAE предусмотрен так называемый remote api. Он то и позволяет забрать или залить данные без использования веб интерфейса. В моем приложении этот интерфейс был реализован, и забрать данные для меня не составило особого труда.

Забрать дамп базы можно так:

./bulkloader.py –dump –app_id=your-app-id –url=http://your-app-id .appspot.com/remote_api –filename=dump.sql3

Дальше надо бы перенести данные на новую CMS, или на худой конец, согнать данные в статику.

Понятно, что статика не позволит интерактивно взаимодействовать с клиентами, и эту часть придется реализовать самостоятельно; однако страницы с описанием товаров/услуг можно оставить в виде статических файлов HTML.

Получить статику можно, натравив на сайт обычный wget с рекурсией; но при невысокой скорости интернета этот процесс может затянуться. Поэтому будет рационально развернуть скачанный дамп на локальной машине, и натравить wget на localhost.

Сначала стартуем свое приложение:
./dev_appserver.py your-app-id
В другой консоли разворачиваем скачанный дамп, используя remote api:
./bulkloader.py –restore –app_id=your-app-id –url=http://127.0.0.1:8080/remote_api –filename=dump.sql3
Используем wget для получения статических файлов HTML:
wget -r http://localhost:8080

Все, теперь у нас есть куча статики, которую можно использовать.

Не исключено, что гугл все-таки одумается, и снимет блокировки айпи адресов на своей стороне. Поэтому окончательно отказываться от GAE я бы не стал, пока что есть возможность поддерживать CMS на локальной машине.

Однако неожиданно выяснилось, что так же просто забрать данные с локальной машины и залить их в гугловский GAE не получится. При попытке скачать dump с локальной машины в один файл, bulk_uploader ругается примерно так:

[ERROR ] Unable to download kind stats for all-kinds download.
[ERROR ] Kind stats are generated periodically by the appserver
[ERROR ] Kind stats are not available on dev_appserver.

Девелоперская среда не умеет сливать все данные локального хранилища в один файл, поэтому данные с локалхоста можно забрать в несколько приемов, по числу сохраненных моделей в локальном хранилище. Примерно так:

./bulkloader.py –dump –app_id=your-app-id –kind=table1 –url=http://127.0.0.1:8080/remote_api –filename=table1.sql3

./bulkloader.py –dump –app_id= your-app-id –kind=table2 –url=http://127.0.0.1:8080/remote_api –filename=table2.sql3

Сохраненные таким образом дампы таблиц без проблем заливаются по очереди на Google App Engine.

Первое разочарование от Google App Engine

Логотип Google App Engine

Как я уже писал, Google App Engine представляет собой очень интересную платформу для разработки веб-приложений на Python или Java. Однако совсем недавно Google в одностороннем порядке и без каких-либо уведомлений стал блокировать доступ к платформе googleappengine из некоторых стран. Причем, часть IP адресов были взяты просто от балды, и вместе с Ираном и Северной Кореей в список запрещенных стран попали и многие IP адреса из Германии. Просьба ко всем, кто хостит свои приложения на Google App Engine, отписаться здесь в случае обнаружения блокирования доступа к приложению из “правильной” страны, из которой у вас есть свои посетители.

Как защитить Asterisk от подбора паролей.

Решил я как-то раз поднять SIP-сервер для своих нужд. Выход во внешние сети был не нужен, поднял я этот сервис только для своих. Не успел его поднять, как доблестные тайваньские хакеры дружно начали брутфорсить логины и пароли на мой астериск. Причем делали это внаглую в многопоточном режиме, цифры подставляли методом научного перебора:

[Jan 13 09:45:12] NOTICE[15489] chan_sip.c: Registration from '"0"' failed for '210.240.176.51' - No matching peer found 
[Jan 13 09:45:12] NOTICE[15489] chan_sip.c: Registration from '"1"' failed for '210.240.176.51' - No matching peer found
[Jan 13 09:45:12] NOTICE[15489] chan_sip.c: Registration from '"test"' failed for '210.240.176.51' - No matching peer found
[Jan 13 09:45:12] NOTICE[15489] chan_sip.c: Registration from '"2"' failed for '210.240.176.51' - No matching peer found
[Jan 13 09:45:12] NOTICE[15489] chan_sip.c: Registration from '"3"' failed for '210.240.176.51' - No matching peer found
[Jan 13 09:45:12] NOTICE[15489] chan_sip.c: Registration from '"4"' failed for '210.240.176.51' - No matching peer found
[Jan 13 09:45:12] NOTICE[15489] chan_sip.c: Registration from '"5"' failed for '210.240.176.51' - No matching peer found
[Jan 13 09:45:12] NOTICE[15489] chan_sip.c: Registration from '"6"' failed for '210.240.176.51' - No matching peer found
[Jan 13 09:45:12] NOTICE[15489] chan_sip.c: Registration from '"7"' failed for '210.240.176.51' - No matching peer found
....

С такими темпами они могут вычислить реально существующие внутренние номера телефонов и перейти ко второму этапу – подбору паролей. Чтобы не выдавать проклятым буржуином государственных секретов информацию о существующих номерах, надо в sip.conf в секцию [general] добавить всего одну строчку:

alwaysauthreject = yes

Тогда астериск при неуспешной авторизации будет давать им отбивку 401 Unauthorized, и они не будут знать, верный ли логин был введен. Такая настройка осложнит им жизнь, но полностью от них не избавит.

Вторая вещь, которую следует сделать, это анализировать логи астериска на предмет наличия неверной аутентификации. И в случае обнаружения попыток подбора пароля отправлять подозрительные айпишника в бан.

Для Linux есть подходящее решение, связанное с установкой и настройкой fail2ban, которое построено на iptables. Мне же это решение не подошло, потому что мой Астериск крутится на хостинге с FreeBSD, а там используется ipfw вместо до боли знакомого iptables. Путем долгих экспериментов пришел к тому, что не стоит добавлять все вражеские айпишники в общую очередь в баню. Список правил на пару сотен айпи прилично нагружает VDS, что не есть гуд.

Но ipfw оказался намного лучше, чем казалось на первый взгляд. У него предусмотрен механизм обработки тысяч правил обработки IP адресов, если их загнать в так называемые таблицы ipfw:

Если в firewall.conf добавить одну единственную строчку:

add reject ip from table(15) to me

то все айпишники, оказавшиеся в таблице 15 будут забанены. Причем уже не так уж и важно, сколько их там будет сотня или тысяча, скорость обработки таких списков остается очень высокой, и это намного лучше, чем их обрабатывать обычными правилами вроде таких:

add reject ip from 1.2.3.0/24 to me
add reject ip from 175.12.135.0/24 to me

Правила добавляются в таблицу в любой момент времени, и моментально начинают свою работу. Погуглив немного, я нашел готовый скрипт для FreeBSD, который всех неудачно авторизовавшихся загоняет в бан на сутки. Его можно аккуратно допилить, немного ужесточить правила и все будет работать на отлично.

У таблиц ipfw есть один недостаток, они работают только с IPv4. А так как переход на IPv6 не за горами, то работоспособность чудо-скрипта в ближайшем будущем останется под вопросом.

О пользе nginx

Вот уже болльше 2-х лет я пользуюсь хостингом от FirstVDS и MiniVDS, причем для моих небольших нужд вполне хватает самых дешевых тарифов, на которых дается всего 64 Мб RAM. Свободной памяти у меня практически никогда не бывает, но все сервисы стабильно работают.

Я всерьез задумался, а есть ли смысл включать nginx. Кроме статики, у меня еще есть куча скриптов; причем php работает как модуль apache. Да и сам nginx тоже будет висеть в памяти и есть ресурсы.

Удивительно, но после того, как я у себя включил nginx, apache стал есть меньше памяти. И как выяснилось, это заслуга nginx.

Зачастую апач генерит страницу быстрее, чем отдает ее клиенту; особенно, если клиент имеет не очень хороший канал. И пока он ее отдает, процесс висит в памяти и жрет системные ресурсы. Вот тут и приходит на помощь nginx, который работает как прокси. Он мухой забирает все, что сгенерил апач, и отдает все это добро клиенту. Апач же, законив свою грязную работу, спокойно умирает.

Включить nginx в панели ISPmanager можно одним кликом мыши, и уже через пару-тройку минут можно будет видеть результат. У меня, правда, процесс не совсем корректно отработал, nginx стартовал, а апаче почему-то нет. Пришлось апач запустить вручную. И еще, если автоматически созданные поддомены сделаны вручную через mod_rewrite, возможно некорректное отоборажение картинок на сабах. В этом случае придется вручную править правила раздачи картинок с поддоменов для nginx

Blogger на своем домене и настройки firewall

Платформа Blogger
Платформа Blogger умеет вести блоги не только на blogspot.com, но и на своих доменах. Публикация постов представляет собой заливку готовых html-файлов на хостинг с помощью FTP или SFTP. А чтобы отсечь любителей подбирать пароли FTP, Blogger опубликовал IP-адреса серверов, с которых он может проводить публикацию постов:

66.102.15.83
216.34.7.186
64.233.166.192-207
64.233.178.192-207

Т.е. достаточно в firewall.conf дописать всего 5 строчек, чтобы отсечь брутфорсеров паролей:

add allow tcp from 66.102.15.83 to me 21
add allow tcp from 216.34.7.186 to me 21
add allow tcp from 64.233.166.192/28 to me 21
add allow tcp from 64.233.178.192/28 to me 21
add reset tcp from any to me 21

Хостинг для хранения бэкапов

Вообще я не люблю бесплатный хостинг, потому что там ограничений навалом. Мало диска, трафика и вообще много чего нельзя; да и еще хостер своей рекламой обвешает страничку, и будет совсем уж несмотрибельно и разаляписто. Хостинг без рутового доступа под свои проекты для меня неинтересен.

Но в принципе, бесплатный хостинг может быть полезен для хранения бэкапов, так же, как и файловая система gmail.

Как вариант, можно посмотреть в сторону 000webhost. Вот основные фичи этого хостинга:

  • дают свой домен 3-го уровня, или можно приспособить свой
  • 250 Мб на диске
  • PHP и MySQL, доступ по ftp
  • cPanel
  • 100 Гб трафика в месяц

Делаем страничку с фотографией любимой кошки, и используем его под хранение бэкапов. По самым пессимистичным прогнозам (250 Мб трафика ежедневно) лимит трафика на месяц на нем не преодолеть.

Минус есть один, низкая надежность. Если хостеру что-то не понравится, снесут моментально аккаунт и бэкапы будут потеряны. Бесплатный сыр…

Лучший хостинг в своем классе. Небольшой обзор VDS-хостингов, в сторону которых стоит посмотреть.

Не ожидал я, что uptime моего VDS превысит 90 дней. Однако, смотрите сами:
VDS Uptime / Аптайм VDS
В общем-то, для темплейта “Современный софт” и операционки FreeBSD для VDS это очень хороший показатель. Если бы у меня была бы голая фря, на которую бы я ставил только нужный мне софт, такой аптайм был бы вполне нормальным. Но для площадки, где хостер своевременно вносит патчи на установленный софт, такой аптайм является на удивление хорошим.

Очень порадовала цена этого хостинга, всего 5.95 USD за месяц. Пользуюсь их услугами со дня открытия, и серьезных замечаний к их работе у меня нет. Особой привлекательностью является американский айпишник у VDS, что позволяет легко превратить его в прокси-сервер (SOCKS5) для своих нужд. А тем, кто работает такими партнерками, как COPEAC или AffiliateCube, не надо объяснять, зачем нужен полноценный американский IP-адрес.

Все те же самые вкусности (кроме американского IP-адреса) можно получить и у FirstVDS. Но там айпишик будет московский, который тоже можно использовать для SEO-шных целей. Например, с помощью моего сервиса просмотра сайтов с московского айпи удобно смотреть выдачу яндекса/рамблера (если вы находитесь не в Москве и под рукой нет московской проски). Цена такого хостинга составит 149 рублей в месяц.

Да, забыл добавить. Все, кто зарегистрируются по моим ссылкам, получат скидку в 25% на первый месяц обслуживания.

Как автоматически создавать поддомены

Задача: при обращении к поддомену сервер должен отдавать контент из соответствующей поддиректории для заданного VirtualHost.

Есть 2 способа решения задачи, и какой из них лучше – решайте сами.
В любом случае, сначала надо настроить WildCard DNS на домене, иначе ничего работать не будет.

Если Ваш проект хостится у firstvds или у minivds, то при добавлении домена на Ваш аккаунт файл зоны будет выглядеть примерно так:


$TTL 3600
domain.com. IN SOA ns1.minivds.com. root.mylogin.minivds.com. (2007041702 10800 3600 604800 86400)
;
domain.com. IN NS ns1.minivds.com.
domain.com. IN NS ns2.minivds.com.
domain.com. IN MX 10 mail
domain.com. IN MX 20 mail
domain.com. IN A XXX.YYY.ZZZ.WWW
www IN A XXX.YYY.ZZZ.WWW
ftp IN A XXX.YYY.ZZZ.WWW
mail IN A XXX.YYY.ZZZ.WWW
smtp IN A XXX.YYY.ZZZ.WWW
pop IN A XXX.YYY.ZZZ.WWW
domain.com. IN TXT "v=spf1 a mx ~all"

Чтобы включить WildCard DNS, достаточно в файл зоны добавить всего одну строчку и поменять цифры в serial number зоны. После исправлений файл доменной зоны будет выглядеть так:


$TTL 3600
domain.com. IN SOA ns1.minivds.com. root.mylogin.minivds.com. (2007041703 10800 3600 604800 86400)
;
domain.com. IN NS ns1.minivds.com.
domain.com. IN NS ns2.minivds.com.
domain.com. IN MX 10 mail
domain.com. IN MX 20 mail
domain.com. IN A XXX.YYY.ZZZ.WWW
www IN A XXX.YYY.ZZZ.WWW
ftp IN A XXX.YYY.ZZZ.WWW
mail IN A XXX.YYY.ZZZ.WWW
smtp IN A XXX.YYY.ZZZ.WWW
pop IN A XXX.YYY.ZZZ.WWW
* IN A XXX.YYY.ZZZ.WWW
domain.com. IN TXT "v=spf1 a mx ~all"

Через некоторое время можно попробовать пингануть домены abc.domain.com, asfwsegws.domain.com – доменное имя 3-го уровня должно определяться с тем же IP-адресом, что и доменное имя 2-го уровня.
Вот теперь можно переходить к настройке сабдоменов.

Способ номер 1: вносим изменения в httpd.conf
Выглядит это примерно так:


RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.domain.com
RewriteCond %{HTTP_HOST} !^cgi-bin\.domain\.com$ # запрещаем перенаправление для cgi-bin
RewriteCond %{HTTP_HOST} ^(www\.)?(([^\.]+)\.){1}domain.com$
RewriteCond /home/domain/data/www/domain.com/%3 -d
RewriteRule ^/(.*) /%3/$1

Перезапускаем apache и все – любая поддиректория, созданная в /home/domain/data/www/domain.com/ будет доступна как поддомен. Это самый правильный вариант создания поддоменов.

Но такой способ не будет работать на виртуалхостингах, поскольку доступ пользователю к httpd.conf никто не даст.

Способ номер 2: поддомены через .htaccess:


RewriteEngine on
RewriteCond %{HTTP_HOST} ^subdomain1.domain.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.subdomain1.domain.com$
RewriteRule ^(.*)$ http://www.domain.com/subdomain1/ [R=301,L]
RewriteCond %{HTTP_HOST} ^subdomain2.domain.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.subdomain2.domain.com$
RewriteRule ^(.*)$ http://www.domain.com/subdomain2/ [R=301,L]

В этом случае при обращении к subdomain1.domain.com или к www.subdomain1.domain.com пользователь будет перенаправлен на URL http://www.domain.com/subdomain1/ и он это заметит.