-Поиск по дневнику

Поиск сообщений в rss_rss_hh_new

 -Подписка по e-mail

 

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.03.2011
Записей:
Комментариев:
Написано: 51


Межпланетная файловая система — Переходим на localhost (локальный шлюз IPFS)

Понедельник, 31 Июля 2017 г. 22:46 + в цитатник

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


Пользователю это даст быстрый доступ к его локальной копии нашего сайта.


Также мы научимся переключать на локальный шлюз IPFS сайты которые этого ещё не делают.


Напомню: InterPlanetary File System — это новая децентрализованная сеть обмена файлами (HTTP-сервер, Content Delivery Network). О ней я рассказывал в статье "Межпланетная файловая система IPFS".



image


Переключаем наш сайт


DNS


У нашего сайта на данный момент уже есть как минимум 3 DNS записи:


A    [Наш домен]             [IP адрес хостинга]
TXT  [Наш домен]             dnslink=/ipfs/[CID контента]
TXT  _dnslink.[Наш домен]    dnslink=/ipfs/[CID контента]

Добавим к ним ещё 3:


A    l.[Наш домен]             127.0.0.1
TXT  l.[Наш домен]             dnslink=/ipfs/[CID контента]
TXT  _dnslink.l.[Наш домен]    dnslink=/ipfs/[CID контента]

[CID контента] — Это идентификатор контента (CID) раньше назывался мультихеш. Его мы получаем публикуя сайт командой ipfs add в сети IPFS.


Скрипты и стили


В HTML тегах script и link появились поля integrity и crossorigin. Они отвечают за проверку хеша до запуска скрипта или применения стилей. Их мы и используем для определения рабочего шлюза у посетителя сайта.




Расположить их лучше в конце страницы чтоб они не задерживали загрузку и отображение.


Варианты адресов которые нам надо проверить:


  1. http://l.[наш домен]:8080
    8080 это стандартный порт на котором по умолчанию запускается IPFS.
    Если всё настроено правильно то с http версии сайта браузер загрузит скрипт или стиль.


  2. https://l.[наш домен]:8443
    8443 это порт на который пользователь может настроить stunnel.
    Данный вариант нам понадобится если запрос идёт с HTTPS сайта и наш домен добавлен в локальный сертификат.


  3. http://127.0.0.1:8080/ipns/[наш домен]
    Этот вариант на случай если мы не задали l домен для нашего сайта и запрос идёт с http.


  4. https://127.0.0.1:8443/ipns/[наш домен]
    Этот вариант на случай запроса с https. Этот вариант сработает если не задан l домен или не добавлен в локальный сертификат.

Аналогичным образом мы можем проверить порты 80 для http и 443 для https.


Проверяем локальный шлюз и переключаемся на него скриптом


Добавив этот скрипт к странице вашего сайта вы автоматически переключите посетителя на его локальный IPFS шлюз.



redirect_to_ipfs_gateway.js


var redirect_to_local;

/*
Эта функция добавляет к текущему домену третьим уровнем  домен ```l``` 
*/

function l_hostname()
{
    var l_hostname =  window.location.hostname.split(".");
    l_hostname.splice(-2,0,"l");
    return l_hostname.join(".");
}

/*
Эта функция создаёт новый элемент script и с адресом скрипта который должен загрузиться через локальный шлюз пользователя.

Также она создаёт функцию которая будет вызвана этим скриптом в случае удачной загрузки.

В случае не удачи выполниться функция из переменной onerror которая присваивается соответствующему полю элемента script.
*/

function add_redirect_script(prtocol, port, use_ip, onerror){
    var script = document.createElement("script");
    script.onerror = onerror;
    script.setAttribute("integrity", "sha384-dActyNwOxNY9fpUWleNW9Nuy3Suv8Dx3F2Tbj1QTZWUslB1h23+xUPillTDxprx7");
    script.setAttribute("crossorigin", "anonymous");
    script.setAttribute("defer", "");
    script.setAttribute("async", "");
    if ( use_ip )
        script.setAttribute("src", prtocol+"//127.0.0.1:"+port+"/ipns/"+window.location.hostname+"/redirect_call.js");
    else
        script.setAttribute("src", prtocol+"//"+l_hostname()+":"+port+"/redirect_call.js");

    redirect_to_local = function()
    {
        var a = document.createElement("a");
        a.href = window.location;
        a.protocol = prtocol;
        a.port = port;
        if ( use_ip ){
            a.pathname = "/ipns/" + a.hostname + a.pathname;
            a.hostname = "127.0.0.1";
        }else{
            var hostname = a.hostname.split(".");
            hostname.splice(-2,0,"l");
            a.hostname = hostname.join(".");
        }
        window.location = a.href;
    };
    document.head.appendChild(script);
}

/*
Это главная функция которая запускается сразу. Она проверяет не находимся ли мы уже по адресу шлюза. Если нет то начинает проверять его доступность перебирая варианты адресов и протоколов.
*/
!function(location){
    if ( location.protocol.indexOf("http") == 0 &&
         location.hostname.length          >  0 &&
         location.hostname.indexOf("l.")   != 0 &&
         location.hostname.indexOf(".l.")  <  0 &&
         location.hostname                 != "127.0.0.1" ) 
    {   
        add_redirect_script( "http:",  8080, false,
         function(){
            add_redirect_script( "https:", 8443, false,
             function(){
                add_redirect_script( "http:", 8080, true, 
                 function(){
                    add_redirect_script( "https:", 8443, true );
                 } );
             } );
         } );
    }
}(window.location)

В пару ему идет скрипт:
redirect_call.js (sha384-dActyNwOxNY9fpUWleNW9Nuy3Suv8Dx3F2Tbj1QTZWUslB1h23+xUPillTDxprx7)


redirect_to_local();

Integrity этого скрипта можно посчитать командой:


openssl dgst -sha384 -binary < "redirect_call.js" | openssl enc -base64 -A

У меня соответственно результат этой команды:


dActyNwOxNY9fpUWleNW9Nuy3Suv8Dx3F2Tbj1QTZWUslB1h23+xUPillTDxprx7

Если у вас результат другой замените это значение в скрипте выше на своё.


Теперь пользователь будет автоматически перенаправлен на подходящий локальный адрес шлюза с сохранением остальных параметров адреса.


Определяем рабочий шлюз при помощи CSS


  1. Создадим CSS файл который будет маяком работы шлюза.


    httpl.css (sha384-9LLp4PYTHwNvd5whc7IOL6JLDJ4aoPufAFts3rMLZOg5b//BLQZTfe7krAzWAm+a)


    .httpl{display: block;}

  2. Скрываем элементы страницы которые будут показаны только при доступности локального шлюза.



  3. Добавляем CSS маяк в конце страницы



  4. Этот элемент будет отображаться если загрузиться "httpl.css"

Теперь даже если у пользователя отключены скрипты он сможет перейти на шлюз самостоятельно по ссылке. Аналогично можно проверить и остальные варианты адреса шлюза.


Локализуем глобальный шлюз или сайты в IPFS


Возьмём к примеру глобальный IPFS шлюз gateway.ipfs.io и перенаправим этот адрес на наш локальный IPFS шлюз.


Условие: У нас уже установлен и работает на стандартном порту 8080 IPFS шлюз.


  1. В файл hosts добавляем домен который хотим загружать с IPFS шлюза.


    127.0.0.1 gateway.ipfs.io

  2. Устанавливаем и настраиваем Stunnel.
    stunnel.conf:


    ; Открываем дополнительный защищённый порт шлюза для того чтобы сайты могли сами на него переключиться
    
    [https gateway]
    accept  = 127.0.0.1:8443
    connect = 127.0.0.1:8080
    cert = stunnel.pem
    TIMEOUTclose = 0
    
    ; Открываем стандартный порт 443 для HTTPS
    
    [https]
    accept  = 127.0.0.1:443
    connect = 127.0.0.1:8080
    cert = stunnel.pem
    TIMEOUTclose = 0
    
    ; Открываем стандартный порт 80 для HTTP
    
    [http]
    client = yes
    accept  = 127.0.0.1:80
    connect = 127.0.0.1:443

    Таким образом мы открываем 3 дополнительных порта (433, 8443, 80) которые подключают клиента к шлюзу IPFS.


  3. Создаём сертификаты и ключи.


    3.1. В директорию c конфигом копируем makecert.cmd


    echo off
    %~d0
    cd %~p0
    set STUNNELBIN = ..\bin
    set PATH=%STUNNELBIN%;%PATH%;
    
    rem // Первый вызов openssl создаст ключ и корневой сертификат в формате PEM
    rem // openssl попросит пользователя задать пароль которым будет защищён ключ и при каждой новой подписи сертификата шлюза этот пароль потребуется
    
    rem // Второй вызов openssl конвертирует сертификат из PEM в DER формат понятный Windows
    rem // Корневой сертификат в PEM формате понадобиться для Firefox
    
    if not exist "rootkey.pem" (
    echo [ req ]                                             >openssl.root.cnf
    echo distinguished_name = req_distinguished_name         >>openssl.root.cnf
    
    echo [v3_ca]                                             >>openssl.root.cnf
    echo subjectKeyIdentifier = hash                         >>openssl.root.cnf
    echo authorityKeyIdentifier = keyid:always,issuer:always >>openssl.root.cnf
    echo basicConstraints = critical, CA:TRUE                >>openssl.root.cnf
    echo keyUsage = keyCertSign, cRLSign                     >>openssl.root.cnf
    
    echo [ req_distinguished_name ]                          >>openssl.root.cnf
    
    openssl.exe req -newkey rsa:4096 -x509 -sha256 -days 5480 -config openssl.root.cnf -extensions v3_ca -utf8 -subj "/CN=127.0.0.1" -out rootcert.pem -keyout rootkey.pem
    
    openssl.exe x509 -outform der -in rootcert.pem -out rootcert.crt
    
    del openssl.root.cnf
    )
    
    rem // Теперь создаём ключ который будет использоваться шлюзом
    
    if not exist "gatewaykey.pem" (
    openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out gatewaykey.pem
    )
    
    rem // Делаем запрос сертификата шлюза
    
    if not exist "gateway.csr" (
    
    echo [ req ]                                                      >openssl.req.cnf
    echo req_extensions = v3_req                                      >>openssl.req.cnf
    echo distinguished_name = req_distinguished_name                  >>openssl.req.cnf
    
    echo [ req_distinguished_name ]                                   >>openssl.req.cnf
    
    echo [ v3_req ]                                                   >>openssl.req.cnf
    echo basicConstraints = CA:FALSE                                  >>openssl.req.cnf
    echo keyUsage = nonRepudiation, digitalSignature, keyEncipherment >>openssl.req.cnf
    
    openssl req -new -key gatewaykey.pem -days 1096 -batch  -utf8 -subj "/CN=127.0.0.1" -config openssl.req.cnf -out gateway.csr
    
    del openssl.req.cnf
    )
    
    rem // Если это не первое выполнение данного скрипта то в index.txt может храниться индекс следующей DNS записи.
    
    if exist "index.txt" (
    set /p index=/ Мы создаём openssl.cnf один раз и в дальнейшем дополняем его новыми доменами.
    
    if not exist "openssl.cnf" (
    
    echo basicConstraints = CA:FALSE   >openssl.cnf
    echo extendedKeyUsage = serverAuth >>openssl.cnf
    echo subjectAltName=@alt_names     >>openssl.cnf
    echo [alt_names]                   >>openssl.cnf
    echo IP.1 = 127.0.0.1              >>openssl.cnf 
    echo DNS.1 = localhost             >>openssl.cnf 
    
    set index=2
    del "index.txt"
    )
    
    rem // В цикле добавляем в openssl.cnf домены которые заданы в командной строке либо будут введены пользователем.
    
    :NEXT
    set /a aindex=%index% + 1
    set /a bindex=%index% + 2
    
    set domain=%1
    
    if !%domain% == ! (
    set /p domain=enter domain name or space:
    )
    
    if not !%domain% == ! (
    echo DNS.%index% = %domain%    >>openssl.cnf
    echo DNS.%aindex% = *.%domain% >>openssl.cnf
    
    echo %bindex% >index.txt
    
    set index=%bindex%
    shift
    goto NEXT
    )
    
    del gateway.pem
    
    rem // Создаём сертификат IPFS шлюза 
    
    openssl x509 -req -sha256 -days 1096 -in gateway.csr -CAkey rootkey.pem -CA rootcert.pem -set_serial %RANDOM%%RANDOM%%RANDOM%%RANDOM% -extfile openssl.cnf -out gateway.pem
    
    rem // Записываем ключ и сертификат в stunnel.pem который по умолчанию используется программой stunnel
    
    copy /b gateway.pem+gatewaykey.pem stunnel.pem
    
    rem // Даём пользователю прочитать ошибки или информацию
    
    pause

    3.2. Запускаем


    makecert.cmd ipfs.io

    При первом запуске данного скрипта будет создан корневой сертификат (rootcert.pem для firefox и rootcert.crt для остальных) ключ которому надо задать пароль. Корневой сертификат надо добавить в хранилище доверенных корневых сертификатов в браузере и операционной системе.


    Далее автоматически будет создан сертификат для шлюза которому надо задать домены которые он будет обслуживать.


  4. Пере/Запускаем stunnel


    reload.cmd


    echo off
    %~d0
    cd %~p0
    set STUNNELBIN = ..\bin
    set PATH=%STUNNELBIN%;%PATH%;
    stunnel -install -quiet
    stunnel -start -quiet
    stunnel -reload -quiet


Теперь gateway.ipfs.io будет работать на локальном шлюзе. Аналогично можно поступить с любым сайтом который размещён в IPFS.


Сайт для теста: ivan386.tk


Другие мои статьи о "межпланетной файловой системе":


  1. "Межпланетная файловая система IPFS"
  2. Публикуем сайт в межпланетной файловой системе IPFS
  3. Хостим сайт в межпланетной файловой системе IPFS под Windows
  4. Больше нет необходимости копировать в сеть
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/334584/

Метки:  

 

Добавить комментарий:
Текст комментария: смайлики

Проверка орфографии: (найти ошибки)

Прикрепить картинку:

 Переводить URL в ссылку
 Подписаться на комментарии
 Подписать картинку