Май 2010

IPv6 мудрец

31.05.2010

Получил тут письмо от he.net (он же tunnelbroker.net), в котором, помимо прочих новостей, сообщалось, что они решили выслать футболки всем, кто получил высший статус Sage (мудрец) в их программе бесплатной IPv6 сертификации. Эту сертификацию я у них и раньше видел, когда регистрировал 6in4 туннель, но тогда пренебрежительно прошел мимо. Бесплатная футболка же сильно меняет дело, под таким соусом можно и сертифицироваться.

Процесс сертификации несложный, нужно ответить  на пару десятков вопросов и сделать несколько практических шагов: настроить в собственном домене веб-сервер, почту и DNS для доступа по IPv6. Однако выполнение этих шагов позволит достичь только уровня Guru. Чтобы перейти на последний уровень Sage, нужно, чтобы в информации о домене, который ты администрируешь, присутствовали IPv6 «glue» записи. Эти записи заводятся у регистратора домена и хранятся на серверах домена первого уровня. И вот тут наступает облом: в зоне .ru IPv6 glue записи не поддерживаются.

В расстройстве я решил пошарить, вдруг где можно зарегистрировать домен ненадолго в приличной зоне и у приличного регистратора, чтобы нужные мне «приклеенные» записи поддерживались. Зашел на GoDaddy и обнаружил там распродажу доменов в зоне .info по $1. Без промедления приобрел домен ipv6sage.info, настроил на нем все необходимые для сертификации сервисы (кстати это «чистый» IPv6 домен, все его сервисы, включая пресловутые glue records, доступны только по IPv6) и за пару минут получил статус Sage.

IPv6 Certification Badge for ipv6sage

Осталось дождаться футболку, обещали выслать в конце июня.

Тест дисков на Linode

27.05.2010

Протестировал тут производительность дисковой системы Linode. Тестировал на самой маленькой VPS за $20 с 360 MB RAM. Тестировал с помощью iozone на файле размером 500 MB. Результаты порадовали:

  • Случайное чтение блоками по 4 KB: 290 IO/s
  • Случайная запись блоками по 4 KB: 470 IO/s
  • Линейное чтение блоками по 1 MB: 42 MB/s
  • Линейная запись блоками по 1 MB: 60 MB/s

На первый взгляд запись должна проходить медленнее чтения, но, видимо, из-за наличия кэша и отложенной записи на физических дисках, она опережает чтение. Относительно невысокая пропускная способность не должна смущать, для интерактивных приложений вроде базы данных гораздо важнее количество операций ввода-вывода в секунду, а оно весьма высокое. Для сравнения один диск SAS 15k RPM способен выдать около 170 IO/s.

В слове «РЖД» буква Ж неспроста

25.05.2010

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

Осторожно, реклама!

24.05.2010

Хочу поделиться двумя сайтами, которые меня неизменно радуют и служат источником вдохновения.

sparkfun.com

Сайт американской компании, занимающейся продажей товаров для любительской микроэлектроники. Продают все, от комплектующих до готовых изделий собственной разработки. Согласно недавнему исследованию Adafruit годовая выручка компании превысила $10 млн. Представляете, среди «тупых америкосов» так много увлеченных электроникой, что на них можно зарабатывать хорошие деньги. В умной, смекалистой и вставшей с колен России аналогичной компании я не видел. Помимо непосредственно продукции на сайте есть блог и масса практических руководств по схемотехнике и пайке.

talerka.ru

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

Atmel – жадины

20.05.2010

Вторую неделю пытаюсь выпросить у Atmel пару образцов микроконтроллеров для своих поделок. Послал два запроса, они даже не ответили. AD, например, мне без вопросов присылает. Придется, видимо, покупать.

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

Мирная ртуть

17.05.2010

Поднял на днях для личных нужд сервер с Mercurial репозиториями. С авторизацией и шифрованием, как и положено личным нуждам. Почему не Git? Да кто его знает. Git’а мне и на работе хватает, кроме того, уж очень инопланетянский у него интерфейс. Mercurial в этом плане мне более симпатичен. А почему не CVS/SVN? Мне нравится возможность иметь локально репозиторий со всей историей. Кроме того в DVCS работа с ветками сделана поприятнее.

В общем-то в процессе поднимания ничего особенного нет, вся информация доступна в Интернете. Но для интересующихся приведу последовательность команд с краткими комментариями. Установка происходит на Debian Lenny с nginx и без Apache.

Ставим пакеты mercurial и apache2-utils. Последний понадобится для создания файла с паролями для авторизации.


apt-get install mercurial apache2-utils

Создаем пользователя, из под которого будет работать сервер.


useradd -c "Mercurial Server" -d /var/hg -r -s /bin/false -U hg

Создаем структуру директорий.


mkdir -p /var/hg/{conf,logs,repos}

Ставим правильные права.


chown hg:hg /var/hg/{logs,repos}
chmod o-rwx /var/hg/{logs,repos}

Должно получиться как-то так:


# ls -l /var/hg
total 12
drwxr-xr-x 2 root root 4096 2010-05-14 15:53 conf
drwxr-x--- 2 hg   hg   4096 2010-05-14 16:19 logs
drwxr-x--- 3 hg   hg   4096 2010-05-14 16:14 repos

Создаем пробный репозиторий.


su -s /usr/bin/hg hg init /var/hg/repos/test

Проверяем.


# ls -l /var/hg/repos
total 4
drwxr-xr-x 3 hg hg 4096 2010-05-17 10:06 test

Теперь создаем файл /var/hg/conf/webdir.conf следующего содержания:


[collections]
/var/hg/repos = /var/hg/repos

Такой конфиг позволяет не описывать репозитории по одному, а указать все сразу в виде коллекции. Еще нам понадобится файл /var/hg/conf/hgrc, который мы будем копировать в каждый новый репозиторий. В этом файле отключается встроенный в Mercurial SSL (потому что мы будем использовать SSL в nginx) и разрешается всем push (потому что мы будем использовать авторизацию в nginx).


# cat /var/hg/conf/hgrc
[web]
push_ssl = false
allow_push = *
# cp /var/hg/conf/hgrc /var/hg/repos/test/.hg/

Все готово для запуска сервера. Чтобы было совсем хорошо, создаем скрипт /etc/init.d/hg-serve с таким содержимым:


#!/bin/sh
### BEGIN INIT INFO
# Provides:          hg-serve
# Required-Start:    $remote_fs
# Required-Stop:     $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Mercurial server
### END INIT INFO

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Mercurial server"
NAME=hg
HOME=/var/$NAME
DAEMON=/usr/bin/$NAME
PIDFILE=$HOME/logs/$NAME.pid
DAEMON_ARGS="serve -d -A $HOME/logs/access.log -E $HOME/logs/error.log \
	     -p 9001 -a 127.0.0.1 --webdir-conf $HOME/conf/webdir.conf \
	     --pid-file $PIDFILE"
SCRIPTNAME=/etc/init.d/$NAME

[ -x "$DAEMON" ] || exit 0
. /lib/init/vars.sh
. /lib/lsb/init-functions

do_start()
{
	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON \
		--test > /dev/null || return 1
	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON \
		--chuid hg:hg -- $DAEMON_ARGS || return 2
}

do_stop()
{
	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \
		--pidfile $PIDFILE --name $NAME
	RETVAL="$?"
	[ "$RETVAL" = 2 ] && return 2
	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 \
		--exec $DAEMON
	[ "$?" = 2 ] && return 2
	rm -f $PIDFILE
	return "$RETVAL"
}

case "$1" in
  start)
	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
	do_start
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  stop)
	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
	do_stop
	case "$?" in
		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
	esac
	;;
  restart|force-reload)
	log_daemon_msg "Restarting $DESC" "$NAME"
	do_stop
	case "$?" in
	  0|1)
		do_start
		case "$?" in
			0) log_end_msg 0 ;;
			1) log_end_msg 1 ;; # Old process is still running
			*) log_end_msg 1 ;; # Failed to start
		esac
		;;
	  *)
	  	# Failed to stop
		log_end_msg 1
		;;
	esac
	;;
  *)
	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
	exit 3
	;;
esac

:

Добавляем в автозагрузку.


update-rc.d hg-serve defaults

И запускаем.


/etc/init.d/hg-serve start

Проверяем, что все работает.


# hg clone http://localhost:9001/test
destination directory: test
no changes found
updating working directory
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
# cd test
# touch test
# hg add test
# hg commit -m test
No username found, using 'root@example.com' instead
# hg push
pushing to http://localhost:9001/test
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
# cd .. && rm -rf test

Теперь настраиваем nginx. Сначала заводим пользователя с паролем для авторизации.


htpasswd -c /var/hg/conf/htpasswd user

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


cd /var/hg/conf
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Исправляем права для секретных файлов.


chgrp www-data /var/hg/conf/{htpasswd,server.*}
chmod o-rwx /var/hg/conf/{htpasswd,server.*}

Проверяем.


# ls -l /var/hg/conf
total 28
-rw-r--r-- 1 root root       38 2010-05-14 15:41 hgrc
-rw-r----- 1 root www-data   19 2010-05-17 10:30 htpasswd
-rw-r----- 1 root www-data 1001 2010-05-14 15:45 server.crt
-rw-r----- 1 root www-data  725 2010-05-14 15:45 server.csr
-rw-r----- 1 root www-data  891 2010-05-14 15:45 server.key
-rw-r----- 1 root www-data  963 2010-05-14 15:45 server.key.org
-rw-r--r-- 1 root root       44 2010-05-14 15:53 webdir.conf

Создаем конфиг для nginx /etc/nginx/sites-available/hg.example.com:


server {
	listen 443;
	server_name hg.example.com;
	access_log /var/log/nginx/hg.example.com.access.log;

	ssl on;
	ssl_certificate /var/hg/conf/server.crt;
	ssl_certificate_key /var/hg/conf/server.key;

	ssl_session_timeout 5m;

	ssl_protocols SSLv2 SSLv3 TLSv1;
	ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
	ssl_prefer_server_ciphers on;

	location / {
		auth_basic "Mercurial Repositories";
		auth_basic_user_file /var/hg/conf/htpasswd;

		proxy_pass http://localhost:9001;
	}
}

Включаем конфиг и перезапускаем nginx.


cd /etc/nginx/sites-enabled
ln -s /etc/nginx/sites-available/hg.example.com
/etc/init.d/nginx restart

Финальная проверка с удаленной машины.


$ hg clone https://hg.example.com/test
http authorization required
realm: Mercurial Repositories
user: user
password:
destination directory: test
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
updating working directory
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd test
$ ls
test
$ echo >>test
$ hg commit -m test
$ hg push
http authorization required
realm: Mercurial Repositories
user: user
password:
pushing to https://hg.example.com/test
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files

Блог-роман

14.05.2010

Интересно, есть ли уже такой литературный жанр? Ведет, скажем, человек свой блог в той же жежешечке, рассказывает о своей жизни, даже выкладывает какие-то фотографии. У него куча подписчиков, все читают, комментируют, дивятся причудливости поворотов судьбы автора. Могут быть даже связи с другими дневниками. Длится вся эта канитель год или два, а потом появляется пост: «Конец.» Мол, все события были выдуманы, все персонажи нереальны, всем спасибо за внимание.

непорядок v6

12.05.2010

Рад сообщить, что «непорядок» теперь доступен по IPv6. Те, кто используют IPv6, увидят маленький синий значок «v6» рядом с названием сайта.

К сожалению Linode не предоставляет собственной IPv6 связности, но дает подробные инструкции, как получить оную через туннель от Hurricane Electric, он же Tunnel Broker. Ширина полосы в бесплатном туннеле конечно регулируется, но на времени отклика это никак не сказывается. Одна из точек присутствия Hurricane Electric находится в Лондоне, там же расположен ДЦ Linode, где у меня VPS. Поэтому вход в туннель оказывается очень близко:


li153-251:~# ip link show 6in4
11: 6in4@NONE:
 mtu 1280 qdisc noqueue state UNKNOWN
    link/sit 0.0.0.0 peer 216.66.80.26
li153-251:~# traceroute 216.66.80.26
traceroute to 216.66.80.26 (216.66.80.26), 30 hops max, 40 byte packets
 1  109.74.192.2 (109.74.192.2)  0.437 ms  0.462 ms  0.526 ms
 2  te3-1-border76-01.lon2.telecity.net (217.20.44.217)  0.744 ms * *
 3  217.20.44.194 (217.20.44.194)  0.687 ms * *
 4  10gigabitethernet1-1.core1.lon1.he.net (195.66.224.21)  8.024 ms  7.974 ms  7.829 ms
 5  tserv5.lon1.ipv6.he.net (216.66.80.26)  0.938 ms  0.779 ms  0.812 ms
li153-251:~# ping -c3 216.66.80.26
PING 216.66.80.26 (216.66.80.26) 56(84) bytes of data.
64 bytes from 216.66.80.26: icmp_seq=1 ttl=60 time=1.02 ms
64 bytes from 216.66.80.26: icmp_seq=2 ttl=60 time=3.39 ms
64 bytes from 216.66.80.26: icmp_seq=3 ttl=60 time=2.98 ms

--- 216.66.80.26 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 1.021/2.466/3.398/1.036 ms

Непосредственная связность с внешним миром тоже очень хорошая, наличие туннеля совсем незаметно:


li153-251:~# ping6 -c3 ipv6.google.com
PING ipv6.google.com(2a00:1450:8006::68) 56 data bytes
64 bytes from 2a00:1450:8006::68: icmp_seq=1 ttl=57 time=8.25 ms
64 bytes from 2a00:1450:8006::68: icmp_seq=2 ttl=57 time=8.35 ms
64 bytes from 2a00:1450:8006::68: icmp_seq=3 ttl=57 time=8.75 ms

--- ipv6.google.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 8.259/8.458/8.758/0.240 ms

Для того, чтобы nginx начал обрабатывать IPv6 запросы, пришлось обновить его до версии 0.7.65. В стандартном репозитории Debian Lenny есть только версия 0.6.32, поэтому пришлось подключить репозиторий Backports и ставить из него.

Еще один интересный момент связан с конфигурацией. nginx по умолчанию открывает порт только для IPv4 соединений, это задает директива listen в файле /etc/nginx/sites-available/default:


listen 80 default;

Чтобы принимать IPv6 соединения, нужно добавить еще одну директиву listen для IPv6:


listen [::] default;

Специальный адрес [::] является так называемым wildcard и означает «все IPv6 адреса». Однако с такой конфигурацией nginx не запускается и выдает ошибку:


[emerg]: bind() to [::]:80 failed (98: Address already in use)

Дело в том, что в IPv6 существует такое понятие как IPv4-mapped адрес. Суть его в том, что пространство IPv4 адресов отображается в пространство IPv6 адресов с помощью специального префикса ::ffff. Сделано это, видимо, для облегчения процесса перехода на новый протокол. Покойный itojun говорил, что это возможность является потенциальной дырой в безопасности, поэтому, например, в OpenBSD она отключена. В других системах, более терпимых к дырам, наличие этой возможности контролируется специальным параметром для сокетов IPV6_V6ONLY. И в Linux по умолчанию IPv4-mapped адреса включены. Это приводит к тому, что вызов bind(2) с IPv6 wildcard в качестве адреса пытается помимо IPv6 адресов захватить и IPv4 адреса, которые уже заняты предыдущей директивой listen. Чтобы решить проблему, необходимо отключить IPv4-mapped адреса с помощью параметра ipv6only в конфиге nginx:


listen [::] default ipv6only=on;

Уличные музыканты

11.05.2010

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

Громов молодец

09.05.2010

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