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

 

Вместо введения

Балансировщики нагрузки, кеширование, избыточность, распределенные базы данных, обратный прокси, IaaS, CDN — все эти термины уже давно стали обыденными не только для DevOps-инженеров, но и для IT-шников, работающих в совершенно иных сферах. Сегодня крупные интернет-компании используют кластеры из десятков и сотен серверов, формирующих инфраструктуру, которая выдержит и резкие наплывы посетителей, и отказ основных серверов, а нередко и физический обрыв кабеля.

Времена конфигураций «один сервер — один веб-сайт» уже давно прошли. Однако, как и раньше, мы продолжаем использовать все те же веб-технологии, что и старик Тим Бернерс-Ли. Мы изобрели HTTP/2, но до сих пор не придумали способа отвязать сервис от единой точки входа; у нас есть огромное количество технологий оптимизации отдачи контента, но почему-то мы до сих пор страдаем от DDoS-атак; у нас есть HTML5, однако мертвые ссылки остаются одной из главных проблем веба; мы платим копейки за мегабайт трафика, но отдаем огромные суммы за то, чтобы наш сервис оставался онлайн.

Мы делаем все, что в наших силах, чтобы веб был быстрым, высокодоступным и полезным, но, кажется, становится только хуже. Кто-то может назвать это нормальным, сославшись на растущее количество пользователей сети, нагрузки, объемы и «тяжесть» контента, однако корень проблемы заключается в ущербности самого HTTP как средства для отдачи огромных объемов трафика. Он просто для этого не предназначен. Система, построенная по принципу «один провайдер — миллионы потребителей», во все времена будет страдать от всех перечисленных проблем со все большим усложнением инфраструктуры провайдера, постоянно возрастающими расходами на ее содержание и опасениями, что в любой момент придет Роскомнадзор и выключит доступ к сервису одним нажатием кнопки.

Впервые это осознали создатели первых P2P-сетей и предложили совершенно иной способ распространения контента. Идея была проста как сапог: вместо того чтобы складировать все данные в одном месте, задачу их хранения и распространения возложили на самих потребителей, превратив их в полноправных участников раздачи контента. Как мы все знаем, технология не просто взлетела, а стала одним из столпов, на которых держится современный интернет.

Можно ли применить тот же принцип для построения сайтов? В каком-то смысле да, и именно этим занимаются разработчики IPFS.

 

Веб 3.0

IPFS (InterPlanetary File System) — это стек протоколов и технологий, позволяющий создать нечто вроде глобальной распределенной файловой системы, построенной по принципу P2P-сети. В такой сети все ноды равны и могут выступать как потребителями, так и провайдерами контента (но не обязательно). Поиск информации ведется с использованием распределенной хеш-таблицы (DHT), а адресация контента, как следствие, с помощью хеш-сумм файлов.

Проще всего представить IPFS как надстройку (оверлейную сеть) над интернетом, в которой используются иные методы доступа к ресурсам. Вместо привычного нам понятия «такой-то файл на таком-то веб-сервере» здесь используется понятие «хеш-сумма такого-то файла, который должен быть где-то в сети». Для получения файла клиенту нужно знать только хеш, все остальное сеть сделает сама: найдет узел, у которого есть копия файла, запросит у него файл и отдаст его нам. При этом сеть не имеет пределов горизонтального роста, и при увеличении ее размеров всего лишь незначительно увеличится длительность поиска файла в хеш-таблице (20 хопов для сети из 10 миллионов узлов с увеличением на один хоп при удвоении размера сети).

Применительно к вебу IPFS позволяет решить многие проблемы HTTP и обладает следующими преимуществами:

  • Высокая доступность. Веб-сайт, размещенный с помощью IPFS, не имеет точек отказа. При достаточно большом количестве узлов, реплицирующих веб-сайт или его части (или даже части файлов) у себя, выход одного, нескольких или даже большинства из них никак не повлияет на доступность веб-сайта. Более того, нагрузка на узлы, распространяющие контент веб-сайта, будет равномерно распределена между ними, что защитит от резких наплывов посетителей и DDoS-атак.
  • Параллельная загрузка. Клиент может загрузить части веб-сайта и отдельных файлов с разных узлов одновременно, равномерно распределяя нагрузку на них и увеличивая общую скорость загрузки.
  • Решение проблемы мертвых ссылок. Все файлы в IPFS адресуются с помощью хеш-сумм, так что, если один или несколько узлов перестанут хранить у себя файл, он все равно будет найден.
  • История версий. IPFS — версионная файловая система. При модификации файла старая версия остается неизменной и может быть адресована и найдена. Это позволяет из коробки получить wayback machine, которая будет работать до тех пор, пока хоть один узел будет хранить старую копию файла.
  • Обход цензуры. В IPFS нет единой точки входа и единого сервера, отвечающего за обслуживание веб-сайта или сервиса. Чтобы «выключить» сайт в IPFS, придется выключать все узлы, ответственные за хранение его частей. При достаточно больших размерах сети это нереализуемая задача.
  • Экономия на трафике. Благодаря равномерному распределению нагрузки на узлы можно существенно сократить расходы на трафик, размазав их по всем раздающим.

Есть, однако, и две серьезные проблемы. Во-первых, не совсем понятно, что делать с динамическим контентом. Frontend-часть сайта будет работать как положено, поменяется лишь адресация JS-, CSS- и HTML-файлов, а вот с backend’ом сложнее. И основной вопрос здесь в том, что делать с server-side скриптами и базами данных: придется либо по старинке запускать их на выделенных серверах, либо реализовать некий механизм кеширования для хранения актуальных данных в виде уже готовых HTML-страниц, что не всегда возможно. Плюс, конечно же, вопрос защиты конфиденциальных данных и интеллектуальной собственности, но для этого в IPFS уже есть почти готовый механизм шифрования.

Вторая проблема: как попасть в IPFS. Браузеры, само собой, не поддерживают IPFS из коробки: мы не можем просто вбить хеш-сумму файла index.html нужного сайта в адресное поле и получить к нему доступ. Нужен шлюз для переадресации запросов. Сегодня есть как минимум два таких шлюза: это официальный шлюз IPFS, позволяющий получить доступ к любому файлу в IPFS, указав его хеш, и шлюз хостинга neocities.org, первого крупного сервиса, полностью поддерживающего IPFS.

К любому сайту, опубликованному на neocities.org, можно получить доступ с помощью IPFS-хеша. Например, вот ссылка, открывающая сайт dragonquest.neocities.org с помощью IPFS. Хеш его главной страницы (на момент написания статьи) — QmTwEt89e6y3bRNMuZwhZHk7JjoeiYbqcASYHh6gkgnCoQ, открыть его можно и через официальный IPFS-шлюз, разницы ты не заметишь. Если в будущем появятся другие шлюзы, в том числе твой собственный, ты сможешь получить доступ к любому IPFS-сайту и через них.

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

 

Выходим в IPFS

Реализация IPFS доступна для Windows, Linux и OS X. Различия в них минимальны, и все они представляют собой один бинарный файл, с помощью которого можно и подключиться к IPFS, и добавить в нее свои файлы, и создать шлюз. Поэтому приведенные далее примеры для Linux будут справедливы для всех остальных систем (за исключением процесса установки, разумеется).

Итак, для начала скачиваем последнюю версию IPFS (в данном случае для 64-битного Linux):

$ wget https://gobuilder.me/get/github.com/ipfs/go-ipfs/cmd/ipfs/ipfs_master_linux-amd64.zip
$ unzip ipfs_master_linux-amd64.zip

Далее просто копируем бинарник IPFS в /usr/local/bin или в ~/bin:

$ cp ipfs/ipfs ~/bin
$ chmod +x ~/bin/ipfs

Последний шаг — инициализация локального хранилища файлов:

$ ipfs init
Инициализация IPFS
Инициализация IPFS

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

$ ipfs daemon &

С этого момента мы онлайн, то есть можем запрашивать файлы с помощью команд ipfs cat /ipfs/<хеш>, ipfs get /ipfs/<хеш> и размещать файлы с помощью ipfs add <имя_файла>. Причем адресовать можно не только отдельные файлы, но и целые каталоги. Например, чтобы получить страницу index.html того самого сайта dragonquest.neocities.org, мы можем использовать такую команду:

$ ipfs cat /ipfs/QmTwEt89e6y3bRNMuZwhZHk7JjoeiYbqcASYHh6gkgnCoQ/index.html > index.html

Вторая особенность нашего онлайн-статуса в том, что другие узлы сети могут использовать наш хост для поиска нужных файлов (то есть мы становимся участником распределенной хеш-таблицы). Узнать IP-адреса и уникальные ID ближайших узлов можно так (в IPFS ближайший не значит близкий географически):

$ ipfs swarm peers
Список пиров IPFS
Список пиров IPFS

Третья особенность — любые запрошенные или размещенные нами файлы будут локально кешированы, а это значит, что мы будем участвовать в их раздаче (тот же принцип, что в файлообменных сетях). Само собой разумеется, кеш можно и нужно время от времени очищать:

$ ipfs repo gc

С другой стороны, мы можем захотеть оставить некоторые из этих файлов и каталогов у себя — и чтобы использовать в будущем (офлайн-доступ), и чтобы помочь в раздаче. Это можно сделать, «закрепив» нужные файлы (так сборщик мусора их не тронет):

$ ipfs pin add index.html

Четвертая особенность онлайна в том, что теперь у нас есть собственный IPFS-шлюз (я же говорил, что запустить его просто). Он доступен по адресу localhost:8080/ipfs/, при необходимости его можно пробросить на 80-й порт.

Также теперь у нас есть веб-консоль localhost:5001/webui/, с помощью которой можно узнать адреса подключенных узлов, добавить файлы или просто получить тот или иной файл через собственный шлюз. При этом все HTML-, CSS- и JS-файлы, необходимые для формирования веб-консоли, также загружаются напрямую из IPFS (с последующим кешированием, разумеется).

 

Размещаем веб-сайт

Как видишь, подключиться к сети IPFS и начать размещение файлов очень просто. Все делается в одну-две команды и не вызывает вопросов. Но как насчет real world example? Так ли легко добавить в IPFS целый сайт и сделать его децентрализованным? Давай проверим. Для примера сделаем простейшую веб-страницу с одним заголовком и изображением.

Для начала создадим каталог:

$ mkdir /tmp/ipfs-site
$ cd /tmp/ipfs-site

Затем скопируем в него изображение (пусть это будет cat.jpg) и добавим в IPFS:

$ ipfs add cat.jpg
added QmP3MnEmYv7mxvqrduBFBhLUKSSjZxPBXwkfVko2yWdqnx cat.jpg

Запоминаем хеш, полученный от IPFS, и для проверки пробуем открыть файл через локальный IPFS-шлюз:

http://localhost:8080/ipfs/QmP3MnEmYv7mxvqrduBFBhLUKSSjZxPBXwkfVko2yWdqnx

Картинка должна благополучно загрузиться. Теперь очередь HTML-файла, и здесь сразу встает вопрос: как адресовать картинку? Самый очевидный вариант — это использовать ссылку выше, но в таком случае картинку увидим только мы, так как наш шлюз локальный. Поэтому мы будем использовать официальный IPFS-шлюз. Пишем следующий быдлокод:

<body>
<head>
  <title>Hello IPFS!</title>
</head>
<body>
  <h1>Hello IPFS!<h1>
  <img decoding="async" src="https://ipfs.io/ipfs/QmP3MnEmYv7mxvqrduBFBhLUKSSjZxPBXwkfVko2yWdqnx">
</body>

Опять же добавляем файл в IPFS:

$ ipfs add index.html
added QmZzfWhi8DTofwkFPvHyN9pABtrRYSubjGYvpbw2HharHp index.html

Теперь наша HTML-страничка и картинка в IPFS-сети, а значит, они должны быть доступны не только через локальный шлюз, в котором эти файлы изначально есть, но и через любой другой. Что ж, пробуем:

https://ipfs.io/ipfs/QmZzfWhi8DTofwkFPvHyN9pABtrRYSubjGYvpbw2HharHp

И ждем. Первая загрузка может длиться довольно долго, так как нагрузка на шлюз высокая, а копий наших файлов, кроме нас, ни у кого нет. Но в конечном итоге страничка все-таки загружается. Теперь мы можем убить локальный демон IPFS с помощью команды killall ipfs и попробовать открыть страницу вновь. Как и положено, страница открывается.

Неубиваемая веб-страница
Неубиваемая веб-страница
 

В заключение

Какие выводы мы можем сделать из нашего эксперимента?

  1. Разместить в IPFS статический веб-сайт так же легко, как и любой другой набор файлов (при необходимости можно опубликовать весь каталог целиком).
  2. Проблему единой точки отказа (в виде шлюза) мы так и не решили, зато в отличие от традиционного подхода можем в любой момент заменить все ссылки, указав в них другой шлюз (это можно сделать, применив команду sed s#ipfs.io/ipfs#другой_шлюз#g ко всем файлам).
  3. «Выживаемость» нашей странички напрямую зависит от ее популярности и количества желающих хранить ее в своем кеше IPFS.
  4. Чтобы решить проблему изменения хеш-суммы при каждом изменении страницы, можно использовать IPNS — механизм, позволяющий получить хеш, всегда ссылающийся на последнюю версию сайта. На момент написания статьи IPNS был в стадии преальфа, поэтому я не стал расписывать его использование. Но в целом все так же просто, как с самим IPFS.
  5. Тем, кто желает помочь в распространении контента и развитии сети, достаточно просто установить IPFS и запустить демон. Также желательно установить расширение IPFS Gateway Redirect для Chrome и Firefox, которое будет автоматически перенаправлять все запросы к ipfs.org/ipfs/ на локальный шлюз. Таким образом запрошенные через официальный шлюз страницы будут оседать в кеше, а узел участвовать в раздаче.
  6. По-настоящему децентрализованным IPFS станет только после включения его поддержки в браузеры. Как вариант, разработчики могут выпустить собственную версию Chrome или Firefox, которая будет распространяться в комплекте с IPFS-демоном и плагином IPFS Gateway Redirect.

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    2 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии