Об IPv6
2018-11-17
Тихо и незаметно наступает эпоха IPv6. Уже можно заполучить IPv6 дома или в офисе, по крайней мере, клиентам ЭР-Телекома. Уже подключают к интернетам только по IPv6, по крайней мере, некоторых клиентов нашего заказчика, где-то в Америке. Уже без проблем можно получить IPv6 адрес для любого сервера любого уровня виртуальности почти у любого хостера или облачного провайдера. Уже встречаются дешманские виртуалки только с IPv6, и с IPv4 через NAT, где проброшен десяток портов.
В IPv4, как помните, адрес 32-битный. Лишь четыре миллиарда адресов. И они закончились ещё в 2011.
В IPv6 адрес уже 128 бит. Этого хватит всем. Всем землянам, по крайней мере. И миллионам их карманных устройств, у каждого.
IPv6 адреса записываются в виде шестнадцатеричных чисел.
Восемь четырёхзначных чисел,
разделённых двоеточием.
Начальные нули в каждом числе можно упустить.
Самую длинную группу из нулевых чисел тоже можно упустить.
В результате адрес localhost выглядит как ::1
.
$ ip addr show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
IPv6 адреса на интерфейсе, глядящем в Интернет, выглядят примерно так:
$ ip -6 addr show dev wlp2s0
2: wlp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 fd9e:ecc8:b68d::13f/128 scope global noprefixroute
valid_lft forever preferred_lft forever
inet6 2a02:ffff:ffff:12f0::13f/128 scope global dynamic noprefixroute
valid_lft 85082sec preferred_lft 2282sec
inet6 fd9e:ecc8:b68d:0:49ba:acb9:11b5:5adb/64 scope global temporary dynamic
valid_lft 597201sec preferred_lft 78558sec
inet6 fd9e:ecc8:b68d:0:fcd2:44e9:bb4d:d28b/64 scope global mngtmpaddr noprefixroute
valid_lft forever preferred_lft forever
inet6 2a02:ffff:ffff:12f0:49ba:acb9:11b5:5adb/64 scope global temporary dynamic
valid_lft 85081sec preferred_lft 2281sec
inet6 2a02:ffff:ffff:12f0:c354:cdb3:9794:b0a/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 85081sec preferred_lft 2281sec
inet6 fe80::ff0b:c674:5528:a3c8/64 scope link noprefixroute
valid_lft forever preferred_lft forever
Да. IPv6 адресов всегда больше одного.
Адрес, начинающийся с fe80::
, который scope link
,
присутствует всегда.
Просто, если у вас включен IPv6.
Даже если вы никуда не подключены.
Этот адрес назначается автоматически,
и уникален для данного интерфейса.
Можно считать это неким аналогом адресов 169.254.0.0/16
в IPv4.
Только в IPv4 адрес 169.254
выдаётся только
если не удалось получить адрес другим способом,
например, по DHCP.
И на это иногда уходит несколько секунд
при загрузке ОС.
А в IPv6 адрес fe80::
назначается сразу, локально.
Он конструируется из MAC адреса.
И, в результате, в IPv6 хост
может сразу общаться с другими IPv6 хостами,
правда, в рамках только локальной сети.
Этого вполне достаточно, чтобы запросить публичный маршрутизируемый адрес у ближайшего маршрутизатора. Таким образом, адреса получаются автоматически без привлечения других протоколов. Это называется Router Advertisement.
Адреса раздаются префиксами.
Подсетями чудовищного размера с маской /64
.
Прикиньте, да,
1.8e+19
адресов на абонента.
В данном случае у нас виднеется два префикса.
$ sipcalc fd9e:ecc8:b68d:0:49ba:acb9:11b5:5adb/64
-[ipv6 : fd9e:ecc8:b68d:0:49ba:acb9:11b5:5adb/64] - 0
[IPV6 INFO]
Expanded Address - fd9e:ecc8:b68d:0000:49ba:acb9:11b5:5adb
Compressed address - fd9e:ecc8:b68d:0:49ba:acb9:11b5:5adb
Subnet prefix (masked) - fd9e:ecc8:b68d:0:0:0:0:0/64
Address ID (masked) - 0:0:0:0:49ba:acb9:11b5:5adb/64
Prefix address - ffff:ffff:ffff:ffff:0:0:0:0
Prefix length - 64
Address type - Unassigned
Network range - fd9e:ecc8:b68d:0000:0000:0000:0000:0000 -
fd9e:ecc8:b68d:0000:ffff:ffff:ffff:ffff
То, что начинается на fd9e:ecc8:
—
это "Unique Local Unicast" (ULA) адреса.
Это аналог 192.168.0.0/16
,
или 10.xxx.xxx.xxx
или 172.16.xxx.xxx
.
Это немаршрутизируемые адреса,
применимые только в локальной сети.
В данном случае эти адреса нам зачем-то выдал
маршрутизатор на OpenWRT.
$ sipcalc 2a02:ffff:ffff:12f0:49ba:acb9:11b5:5adb/64
-[ipv6 : 2a02:ffff:ffff:12f0:49ba:acb9:11b5:5adb/64] - 0
[IPV6 INFO]
Expanded Address - 2a02:ffff:ffff:12f0:49ba:acb9:11b5:5adb
Compressed address - 2a02:ffff:ffff:12f0:49ba:acb9:11b5:5adb
Subnet prefix (masked) - 2a02:ffff:ffff:12f0:0:0:0:0/64
Address ID (masked) - 0:0:0:0:49ba:acb9:11b5:5adb/64
Prefix address - ffff:ffff:ffff:ffff:0:0:0:0
Prefix length - 64
Address type - Aggregatable Global Unicast Addresses
Network range - 2a02:ffff:ffff:12f0:0000:0000:0000:0000 -
2a02:ffff:ffff:12f0:ffff:ffff:ffff:ffff
А вот префикс 2a02:ffff:ffff:12f0::/64
—
это уже настоящий публичный префикс,
выданный провайдером.
И в этом настоящем префиксе у нас почему-то аж три адреса.
$ ip -6 addr show dev wlp2s0 | grep 2a02
inet6 2a02:ffff:ffff:12f0::13f/128 scope global dynamic noprefixroute
inet6 2a02:ffff:ffff:12f0:49ba:acb9:11b5:5adb/64 scope global temporary dynamic
inet6 2a02:ffff:ffff:12f0:c354:cdb3:9794:b0a/64 scope global dynamic mngtmpaddr noprefixroute
Адрес, помеченный mngtmpaddr
, —
это адрес, автоматически назначенный для данного префикса
и данного MAC адреса.
Точнее для EUI-64.
$ ipv6calc -i 2a02:ffff:ffff:12f0:c354:cdb3:9794:b0a/64
Address type: unicast, global-unicast, productive, iid, iid-global, iid-eui64
Interface identifier: c354:cdb3:9794:0b0a
EUI-64 identifier: c1:54:cd:b3:97:94:0b:0a
EUI-64 identifier is a global unique one
У этих адресов беда с безопасностью. Вторая половина IPv6 адреса у вашего компьютера будет всегда одной и той же, куда бы вы не перемещались, и какой бы IPv6 префикс вы не получали. Так можно отследить ваши перемещения.
Поэтому генерируется ещё второй адрес,
помеченный как temporary
.
Здесь суффикс уже полностью случайный.
Это называется "Privacy Extension"
(RFC 3041).
$ ipv6calc -i 2a02:ffff:ffff:12f0:49ba:acb9:11b5:5adb/64
Address type: unicast, global-unicast, productive, iid-random, iid, iid-local
Interface identifier: 49ba:acb9:11b5:5adb
Interface identifier is probably generated by privacy extension
Последний адрес выдан DHCPv6. На самом деле, DHCP для IPv6 не особо нужен, и так адреса нормально назначаются. Но иногда, вроде, он нужен. По крайней мере у ЭР-Телекома нужно заполучать префиксы через DHCPv6 внутри PPPoE соединения.
$ ipv6calc -i 2a02:ffff:ffff:12f0::13f/128
Address type: unicast, global-unicast, productive, iid, iid-local
Interface identifier: 0000:0000:0000:013f
Interface identifier is probably manual set
Так под каким адресом мы ходим в интернет? В таблице маршрутизации всё запутанно.
$ ip -6 route show dev wlp2s0
2a02:ffff:ffff:12f0::13f proto kernel metric 600 pref medium
2a02:ffff:ffff:12f0::/64 proto ra metric 600 pref medium
fd9e:ecc8:b68d::13f proto kernel metric 600 pref medium
fd9e:ecc8:b68d::/64 proto ra metric 600 pref medium
fd9e:ecc8:b68d::/48 via fe80::c66e:1fff:feb9:e41b proto ra metric 600 pref medium
fe80::/64 proto kernel metric 256 pref medium
fe80::/64 proto kernel metric 600 pref medium
default via fe80::c66e:1fff:feb9:e41b proto ra metric 600 pref medium
Тут видно, что адрес маршрутизатора (via
) указан
в виде локального адреса fe80::
.
Локальная сеть, оказывается, имеет большой префикс /48
:
fd9e:ecc8:b68d::/48
.
Адреса, полученные по DHCPv6,
помечены как proto kernel
.
А адреса, полученные через Router Advertising,
помечены как proto ra
.
И default
маршрут тоже proto ra
.
Выходит,
что Router Advertising вроде как предпочтительнее DHCPv6.
А temporary
адрес, который случайный,
должен быть предпочтительнее.
И действительно,
Яндекс Интернетометр
говорит,
что наш IPv6 адрес — 2a02:ffff:ffff:12f0:49ba:acb9:11b5:5adb
.
Собственно,
остальные адреса и помечены как noprefixroute
,
то есть с ними не связаны маршруты.
Похоже, моя домашняя сеть — это какой-то IPv6 ад. На серваках всё проще.
# ip -6 addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
inet6 2001:ffff:ffff:19c:5400:ff:fe54:a41/64 scope global mngtmpaddr dynamic
valid_lft 2591971sec preferred_lft 604771sec
inet6 fe80::5400:ff:fe54:a41/64 scope link
valid_lft forever preferred_lft forever
Тут нет DHCPv6.
Тут нет нужды в Privacy Extension,
потому что серваки не ездят по планете.
В результате у нас только два адреса:
автоматический локальный fe80::
и настоящий публичный IPv6.
$ ip -6 route show dev eth0
2001:ffff:ffff:19c::/64 proto kernel metric 256 expires 2591828sec
fe80::/64 proto kernel metric 256
default via fe80::fc00:ff:fe54:a41 proto ra metric 1024 expires 1628sec hoplimit 64
С маршрутами тоже всё просто и понятно.
Сетевые приложения, как правило, предпочитают IPv6 сокеты. Серверный IPv6 сокет способен принимать подключения как по IPv6, так и по IPv4, не пугайтесь.
# ss -lnpt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.1:6379 *:* users:(("redis-server",pid=571,fd=4))
LISTEN 0 128 *:80 *:* users:(("nginx",pid=598,fd=6),("nginx",pid=596,fd=6))
LISTEN 0 128 *:22 *:* users:(("sshd",pid=555,fd=3))
LISTEN 0 128 *:443 *:* users:(("nginx",pid=598,fd=8),("nginx",pid=596,fd=8))
LISTEN 0 128 :::8080 :::* users:(("java",pid=516,fd=39))
LISTEN 0 128 :::80 :::* users:(("nginx",pid=598,fd=7),("nginx",pid=596,fd=7))
LISTEN 0 128 :::22 :::* users:(("sshd",pid=555,fd=4))
LISTEN 0 128 :::443 :::* users:(("nginx",pid=598,fd=9),("nginx",pid=596,fd=9))
А вот для Nginx нужно явно указать слушание обоих протоколов.
server {
listen 80 default_server;
listen 443 ssl default_server;
listen [::]:80 default_server;
listen [::]:443 ssl default_server;
#...
В URL IPv6 адрес
положено брать в квадратные скобки:
http://[2a00:1450:4011:808::1001]
.
Для IPv6 адресов в DNS предусмотрен
специальный тип записи AAAA
.
$ dig +noall +question +answer aaaa google.com
;google.com. IN AAAA
google.com. 299 IN AAAA 2a00:1450:4011:808::1008
У самих DNS серверов, включая публичные DNS гугла, тоже есть IPv6 адреса.
$ dig +noall +question +answer +stats @2001:4860:4860::8888 aaaa google.com
;google.com. IN AAAA
google.com. 271 IN AAAA 2a00:1450:4011:80b::1002
;; Query time: 48 msec
;; SERVER: 2001:4860:4860::8888#53(2001:4860:4860::8888)
;; WHEN: Sat Nov 17 19:38:19 +06 2018
;; MSG SIZE rcvd: 67
$ dig +noall +question +answer +stats @2001:4860:4860::8844 aaaa google.com
;google.com. IN AAAA
google.com. 299 IN AAAA 2a00:1450:4011:80e::1009
;; Query time: 52 msec
;; SERVER: 2001:4860:4860::8844#53(2001:4860:4860::8844)
;; WHEN: Sat Nov 17 19:39:00 +06 2018
;; MSG SIZE rcvd: 67
$ dig +noall +question +answer +stats @2606:4700:4700::1111 aaaa google.com
;google.com. IN AAAA
google.com. 188 IN AAAA 2a00:1450:4011:804::1004
;; Query time: 35 msec
;; SERVER: 2606:4700:4700::1111#53(2606:4700:4700::1111)
;; WHEN: Sat Nov 17 19:40:06 +06 2018
;; MSG SIZE rcvd: 67
$ dig +noall +question +answer +stats @2606:4700:4700::1001 aaaa google.com
;google.com. IN AAAA
google.com. 157 IN AAAA 2a00:1450:4011:804::1004
;; Query time: 35 msec
;; SERVER: 2606:4700:4700::1001#53(2606:4700:4700::1001)
;; WHEN: Sat Nov 17 19:40:37 +06 2018
;; MSG SIZE rcvd: 67
IPv6 вполне поддерживается в соответствующих типах данных PostgreSQL.
postgres=# select network('2a02:ffff:ffff:12f0:49ba:acb9:11b5:5adb/64');
network
--------------------------
2a02:ffff:ffff:12f0::/64
(1 строка)
postgres=# select inet '2a02:ffff:ffff:12f0:49ba:acb9:11b5:5adb/64' && cidr '2a02:ffff:ffff:12f0::/64';
?column?
----------
t
(1 строка)
Вроде как существует возможность, имея только IPv6 адрес, ходить в IPv4 сети. Чтобы занатить IPv6 адреса в IPv4, есть NAT64. Чтобы резолвить то, что резолвится только в IPv4, в IPv6 адреса, есть DNS64.
Доля мирового IPv6 трафика уже доходит до 25%. Так что пора, пора приобщаться к новому Интернету. Пока не поздно.
К сожалению, ЭР-Телеком не выдаёт статические IPv6 префиксы. То есть IPv6 вы попробовать сможете, но вот поднять у себя сервер без DynDNS не выйдет. Ну тоже неплохо.
И не забывайте, что IPv6 — это настоящий адрес. Безо всякого NAT. Так что настраивайте файерволы на маршрутизаторах, чтобы ваши телефоны в вайфае не похакали. В OpenWRT по дефолту всё норм, входящие соединения запрещены, получается как за NAT.