22 дек. 2009 г.

Linux и IPv6

В этой статье мы рассмотрим технические вопросы использования IPv6 под Linux. Многое является общим для всех UNIX, но есть и специфичные для Linux вещи, их я постарался отметить явно. Мы увидим, что нужно поменять в настройках распространенных клиентских и серверных программ для их корректной работы с IPv6.

Часть первая, теоретическая

Прежде всего, следует пояснить суть IPv6. Он является развитием IPv4, преимущественно используемого сейчас для передачи данных в Интернете, и тоже является протоколом сетевого уровня. Все протоколы транспортного и более высоких уровней прозрачно работают поверх него.

Адреса IPv6 в четыре раза длиннее IPv4, то есть содержат 16 байт. Они записываются в виде восьми групп по четыре шестнадцатеричных цифры. Например, 2001:0db8:1a2b:3c4d:005f:0000:0000:0001. Незначащие нули могут быть опущены: 2001:db8:1a2b:3c4d:5f:0:0:1. Если две или более группы цифр состоят только из нулей, то их можно заменить на «::»: 2001:db8:1a2b:3c4d:5f::1.

Существует несколько адресов и сетей специального назначения. Вот часть из них:

Адрес Назначение
:: Неопределенный адрес, аналог 0.0.0.0. Все IPv6 адреса обозначаются как ::/0
::1/128 localhost, аналог 127.0.0.1
fe80::/10 Link local. Адреса для использования в пределах сегмента локальной сети, аналог 169.254.0.0/16
fc00::/7 Unique local. Адреса для использования в пределах локальной сети, аналог 10.0.0.0/8, 172.16.0.0/12 и 192.168.0.0/16.
ff00::/8 Multicast, аналог 224.0.0.0/4
2001:db8::/32 Зарезервировано для документации и примеров. Что-то вроде example.com

Для передачи IPv6-трафика по существующим IPv4-соединениям существует несколько протоколов инкапсуляции, среди них 6in4 и 6to4. Они примерно идентичны по функциональности.

Часть вторая, практическая

Где взять?

Понятно, что экспериментировать с IPv6 в пределах локальной сети не особо интересно. Однако непосредственно его сейчас почти никто из провайдеров не предоставляет. Но есть ряд сервисов, предоставляющий IPv6 через туннель. Вот несколько таких сервисов:

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

Настраиваем туннель.

Это касается только Linux, под другими операционными системами набор команд будет другим. Хотя принцип тот же.

Все последующие действия нужно выполнять от имени суперпользователя (root).

В новых дистрибутивах ядро обычно поддерживает IPv6. Если поддержка собрана в виде модуля и он по умолчанию не загружается, его нужно загрузить (modprobe ipv6). В случае если поддержка отсутствует (в таких случаях ip будет выдавать ошибки в стиле ioctl: No such device), придется собирать самому — это уже выходит за рамки данной статьи.

# Создаем туннель, используя протокол SIT (Simple Internet Transition, он же 6in4)
ip tunnel add tun0 mode sit remote <адрес сервера> local <адрес локальной машины> ttl 255 
# Поднимаем его интерфейс
ip link set tun0 up
# Назначаем ему адрес
ip addr add <ваш IPv6-адрес>/<длина префикса> dev tun0
# Добавляем маршрут к IPv6-сетям по умолчанию через него
ip route add ::/0 dev tun0

Теперь можно посмотреть в ip links show, или в ifconfig. Вы должны увидеть там свой интерфейс. Если вы фильтруете исходящие соединения, то в правилах межсетевого экрана нужно разрешить протокол 41 (SIT).

 iptables -A OUTPUT -p 41 -j ACCEPT

Чтобы туннель поднимался автоматически при загрузке машины, добавьте эти команды в /etc/init.d/rc.local или его аналог в вашем дистрибутиве.

Настраиваем сетевые интерфейсы

Если у вас более одного компьютера, и туннель поднимается с маршрутизатора сети, то потребуется настройка адресов на сетевых интерфейсах. Прописать их разово можно посредством ifconfig ethX /<длина префикса>, но тогда придется делать это каждый раз. Гораздо удобнее прописать эти настройки в /etc/sysconfig/network, чтобы они применялись при загрузке.

Имейте в виду, что для локальной сети нужно использовать не ту подсеть, из которой адреса у туннеля, а другую. Hurricane Electric указывает ее как «routed /64». Это связано с тем, что первая сеть считается соединенной с интерфейсом туннеля, и трафик к ней тоже пойдет через туннель, а не локальную сетевую карту.

Под RHEL/CentOS нужно добавить в файл настроек интерфейса (/etc/sysconfig/networking/ifcfg-ethX) строки:

IPV6INIT=yes
IPV6ADDR=<адрес>/<длина префикса>

Похоже, что адрес лучше указывать в развернутом виде (без сокращений). Под openSuSE нужно добавить /etc/sysconfig/network/ifcfg-ethX строки:

IPADDR_0='<адрес>/<длина префикса>'
LABEL_0='IPv6'

Тут сокращенный адрес использовать точно можно. Чтоб применить изменения, выполните service network restart.

Не забудьте прописать маршрут по умолчанию для локальных машин. Например, ip route add ::/0 via <адрес маршрутизатора>. На самом маршрутизаторе нужно разрешить маршрутизацию IPv6, прописав в /etc/sysctl.conf переменную net.ipv6.conf.all.forwarding=1.

Диагностические утилиты

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

Аналог ping называется ping6.

[dmbaturin@zax /home/dmbaturin]$ping6 ipv6.google.com
PING ipv6.google.com(2a00:1450:8001::68) 56 data bytes
64 bytes from 2a00:1450:8001::68: icmp_seq=1 ttl=55 time=145 ms
64 bytes from 2a00:1450:8001::68: icmp_seq=2 ttl=55 time=149 ms
^C
--- ipv6.google.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 145.769/147.671/149.573/1.902 ms

Аналог traceroute называется traceroute6.

[dmbaturin@zax /home/dmbaturin]$traceroute6 k.root-servers.net
traceroute to k.root-servers.net (2001:7fd::1), 30 hops max, 40 byte packets using UDP
 1  gateway.baturin.org (2001:470:1f0b:a80::1)  0.126 ms   0.091 ms   0.078 ms
 2  dmbaturin-1.tunnel.tserv6.fra1.ipv6.he.net (2001:470:1f0a:a80::1)  137.634 ms   140.468 ms   143.404 ms
 3  gige-g2-4.core1.fra1.he.net (2001:470:0:69::1)  142.312 ms   141.200 ms   140.096 ms
 4  10gigabitethernet1-4.core1.ams1.he.net (2001:470:0:47::1)  147.056 ms   145.959 ms   144.855 ms
 5  g00.router.ams-ix.k.ripe.net (2001:7f8:1::a502:5152:1)  140.678 ms   138.552 ms   141.341 ms
 6  k.root-servers.net (2001:7fd::1)  140.147 ms   139.015 ms   137.826 ms

Многие команды понимают опции -6 и -4, которые указывают явно использовать IPv6 или IPv4 соответственно. Например:

[dmbaturin@zax /home/dmbaturin]$nmap -6 2001:470:1f0b:a80::15
Starting Nmap 5.00 ( http://nmap.org ) at 2009-12-22 09:26 NOVT
Interesting ports on vyatta.tomsk.ru (2001:470:1f0b:a80::15):
Not shown: 994 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
53/tcp   open  domain
80/tcp   open  http
389/tcp  open  ldap
443/tcp  open  https
8443/tcp open  https-alt
Nmap done: 1 IP address (1 host up) scanned in 0.35 seconds

Клиентские программы

Для клиентских программ никакой особой настройки обычно не требуется. У меня точно работают с ним Firefox, Opera, pidgin и irssi. Единственное что нужно учитывать, это то, что при использовании в URL IPv6-адреса нужно заключать в квадратные скобки. Порт, если его нужно явно указать, пишется за закрывающий скобкой.

http://[2a00:1450:8001::63]
http://[2a00:1450:8001::63]:80

Результат:


Межсетевой экран

Теперь настало время подумать о безопасности. В Linux присутствует межсетевой экран для IPv6, но настраивается отдельно от IPv4, поскольку реализации этих протоколов в ядре независимы друг от друга. Управление им производится с помощью команды ip6tables. Синтаксис правил совпадает с синтаксисом iptables. Отличается только возможностью указывать IPv6-адреса и протоколы, например ipv6-icmp.

DNS-сервер

Сервера bind и nsd оба поддерживают IPv6. Более того, по нему уже доступны все корневые сервера имен, а они используют именно эти программы. Мы будем рассматривать bind как наиболее пригодный для локальной сети (nsd может быть только ответственным за зону, но не кэширующим).

Чтобы убедить bind принимать соединения, пропишите в раздел options в named.conf следующее:

listen-on-v6 
    {
        any; 
    };

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

Настройка зон мало чем отличается от традиционной. Следует помнить только то, что для назначения хосту IPv6-адреса используется AAAA-запись. Называется так, видимо потому, что в четыре раза длинее чем A. Почти все клиентские программы эти записи понимают, в том числе всем известные dig и host. Вот пример:

[dmbaturin@zax /home/dmbaturin]$host vyatta.tomsk.ru
vyatta.tomsk.ru has address 90.188.116.151
vyatta.tomsk.ru has IPv6 address 2001:470:1f0b:a80::15
vyatta.tomsk.ru mail is handled by 20 vyatta.tomsk.ru.
[dmbaturin@zax /home/dmbaturin]$dig vyatta.tomsk.ru AAAA
...
;; ANSWER SECTION:
vyatta.tomsk.ru. 8640 IN AAAA 2001:470:1f0b:a80::15
...

Теперь посмотрим, как это выглядит в описаниях зон:

vyatta.tomsk.ru         IN AAAA     2001:470:1f0b:a80::15
                           A        90.188.116.151
                           MX       20 vyatta.tomsk.ru.
desktop.vyatta.tomsk.ru IN AAAA     2001:470:1f0b:a80::25

Как видно, AAAA-записи используются в точности так же, как и A. Теперь нужно настроить обратное разрешение. Hurricane Electric позволяет делегирование обратных доменов, поэтому проверить в реальных условиях тоже будет можно.

Для обратного разрешения используется домен ip6.arpa (аналог in-addr.arpa для IPv4). В named.conf придется написать следующее (это пример для моей подсети 2001:470:1f0b:a80::/64):

zone "0.8.a.0.b.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa" in 
{
 <настройки зоны>
};

Это адрес подсети, записанный в обратном порядке, без сокращений (даже вместе с незначащими нулями), все цифры разделены точками. Идея та же, что в IPv4, только писать больше. Аналогичным образом пишутся PTR-записи в файле описания зоны:

5.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0  IN PTR vyatta.tomsk.ru.
5.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0  IN PTR desktop.vyatta.tomsk.ru.

Чтобы не писать все это вручную, можно воспользовать вот этим инструментом, или аналогичным.

Почтовый сервер Postfix

В качестве MTA я обычно использую Postfix, поэтому опишу для него. Чтобы он принимал соединения по IPv6, в main.cf нужно написать приблизительно следующее (не указанные здесь параметры легко построить по аналогии):

# Если хотим, чтобы принимал со всех интерфейсов
inet_interfaces = all
# Если только с локальных, то вместо 127.0.0.1 
inet_interfaces = loopback-only

# Используем только IPv6. Если хотим оба, можно прописать all или ipv4,ipv6
inet_protocols = ipv6

# На какой адрес принимать соединения
smtp_bind_address6 = <адрес>

# Адреса IPv6-сетей нужно заключать в квадратные скобки
mynetworks = [2001:db8:abcd::]/48

Веб-сервер Apache HTTPD

При отсуствии явного указания адреса сервера, Apache HTTPD принимает соединения в том числе и по IPv6. Если требуется указать явно, то адрес следует заключить в квадратные скобки:

Listen [2001:db8:abcd:ef::10]

<VirtualHost [2001:db8:abcd:ef::12]>

FTP-сервер vsftpd

Этот сервер не умеет использовать оба протокола одновременно. Поэтому в его настройках придеться прописать либо listen=yes, либо listen_ipv6=yes; но не обе сразу.

Заключение

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

P.S. Для желающих проверить свои знания IPv6 и потренироваться, Hurricane Electric предлагает еще и сертификацию. Вот, к примеру, мои текущие результаты:

IPv6 Certification Badge for dmbaturin

Полный текст сообщения