В днешно време прехвърлянето на огромни обеми данни на далечни разстояния става все по-често занимание на системните администратори (Забележка: пряката ми работа не е свързана със системно администриране, възможно е някои изводи да са ми изкривени). Освен физическите ограничения на преносния канал, трябва да се вземе предвид и протокола за предаване на данни, както и особеностите на неговата имплементация.
Работейки на място, където боравим изключително с чувствителна информация ми се наложи да харесам решение, което да предоставя високо ниво на сигурност при комуникацията, както и производителност близка до оптималната за преносната среда.

Варианти тук, разбира се, не липсват. Аз исках да заложа на изпитани решения, които най-добре вече да са на въоръжение и които няма да усложнят допълнително плетеницата от връзки, технологии и външни компоненти, в която и без това сме затънали.

След известно разглеждане се спрях на SSHFS – отдалечена файлова система, използваща SCP за преносен протокол. Sshd имам на всяка машина, а се оказа, че и под Windows има shell extension-и, които директно mount-ват отдалечения ресурс.

Който е прехвърлял големи обеми данни със SCP е забелязал силното намаляване на производителността спрямо ширината на канала, както и лекото „насичане“ в комуникацията.

Мислейки си за 300-те GB компресиран бекъп на една от базите, която е с навика да расте с по 10 GB на ден, се зарових в търсене на проблема.

Такъв недостатък не би останал незабелязан и съответно вече имаше решение – High Performance Networking patch за OpenSSH.

Причините за деградиралата производителност са следните:

  • Статичен размер на I/O буфера в имплементацията на протокола.
    До версия 4.6p1 въпросният буфер е бил едва 64 KB, което е крайно недостатъчно и предизвиква ненужно фрагментиране на данните.. Всеки фрагмент от своя страна се криптира отделно и води до допълнителен overhead.
    В последната версия на OpenSSH 4.7p1 буфера е увеличен на 2 MB. Това дава добро увеличение на производителността, но все още има какво да се желае.
  • Имплементациите на използваните алгоритми за криптиране не са multithread.
    Това директно оказва влияние върху оптималното използване на процесорите. В днешно време сървърите разполагат с повече от един процесор, да не говорим за дву- и четири ядрените хардуерни решения.
  • Когато използваме собствени (или dedicated) канали, които може би имат и криптиране на по-долен слой или пък не пренасяме чувствителни данни, можем да използваме eNULL алгоритъм за криптиране, или иначе казано – без такова.

По решението на горните проблеми работи екип на Pittsburgh Supercomputing Center, който е реализирал patch за OpenSSH. По редица причини този patch все още не е станал част от официалната дистрибуция и се налага прилагането му на ръка.

Работейки с Ubuntu, реших първо да намеря прекомпилирани deb пакети, с които да експериментирам. За продукционна машина това не е добра идея, тъй като заедно с HPN patch-а може да ви нахулят и хубав излъскан троянски кон – но вие това си го знаете :)

След като не открих прекомпилиран пакет се заех да свърша работата сам. Както се досещате, гредата дойде от там, че както всяка уважаваща себе си дистрибуция, разработчиците на Debian/Ubuntu имаха свои собствени patch-ове, които решават един или друг проблем за интегрирането на OpenSSH. Прилагането на patch-a гръмна на 6 места, като две от тях бяха вече наложени от допълнителните patch-ове, а за останалите трябваше лека намеса на ръка. Няма да се впускам в подробности, защото те са конкретни за текущото състояние на двете кодови дървета и са тривиални за решение.

Ето накратко стъпките:

  1. Ако не сме прекомпилирали пакети до момента е добре да си дръпнем необходимите ни tool-ове:
    alex@dawn:~/openssh$ sudo apt-get install build-essential devscripts fakeroot
  2. Изтегляме необходимите ни dev пакети спрямо информацията за връзките в openssh:
    alex@dawn:~/openssh$ sudo apt-get build-dep openssh
  3. Изтегляме source пакета на openssh (в случая е openssh_4.7p1-5ubuntu1):
    alex@dawn:~/openssh$ apt-get source openssh
  4. Изтегляме двата HPN patch-а (в случая версия 13v1), включващи динамичното оразмеряване на I/O буфера, eNONE алгоритъма и multithreading имплементацията за брокера за криптиране:
    alex@dawn:~/openssh$ wget http://www.psc.edu/networking/projects/hpn-ssh/openssh4.7-dynwindow_noneswitch.diff.gz
    alex@dawn:~/openssh$ wget http://www.psc.edu/networking/projects/hpn-ssh/openssh4.7-CTR-threading.diff
  5. Влизаме в директорията със source кода и прилагаме двата patch-а:
    alex@dawn:~/openssh$ cd openssh-4.7p1
    alex@dawn:~/openssh$ zcat ../openssh4.7-dynwindow_noneswitch.diff.gz | patch
    alex@dawn:~/openssh$ cat ../openssh4.7-CTR-threading.diff | patch
    Първия би трябвало да изгърми тук-таме, втория трябва да се приложи безпроблемно. Тук трябва да се разходим из кода, като в генерираните .rej файлове има информация за това какво не е успяло да се приложи. Редактираме .h и .c файловете на ръка.
  6. Обновяваме changelog-а, където е важно да инкрементираме версията на пакета, за да не го намажем при по-късен upgrade:
    alex@dawn:~/openssh$ dch -i
  7. Компилираме source-а и изготвяме пакетите:
    alex@dawn:~/openssh$ dpkg-buildpackage -rfakeroot
    Ако всичко е минало добре, би трябвало да имате няколко .deb и .udeb пакета, тъй като в Debian OpenSSH е разделен на модули. Инсталирате първо клиента, след това сървъра така:
    alex@dawn:~/openssh$ sudo dpkg -i openssh-client_4.7p1-5ubuntu1alex-hpn13v1_i386.deb
    alex@dawn:~/openssh$ sudo dpkg -i openssh-server_4.7p1-5ubuntu1alex-hpn13v1_i386.deb
    Разбира се, имената на пакетите могат да варират според това какво сте написали на стъпка 6.

След рестартиране на sshd можете да направите малко експерименти. За да използвате patch-а не е необходимо и клиента на отсрещната машина да е да patch-нат – достатъчно е само сървъра да е подобрен.

При моите експерименти в 100 MBit локална мрежа установих два пъти повишаване на производителността. През Интернет(колкото и относително да е това, bgpeering) около 20%.

На финала, ако горните стъпки са ти се сторили сложни и времеемки, можете да използвате моите пакети:

openssh-server_47p1-5ubuntu1alex-hpn13v1_i386.deb (md5:774856d4167be8770203f7c1c8e9af80)

openssh-client_47p1-5ubuntu1alex-hpn13v1_i386.deb (md5:0e5499487010c1e18ca7832318aa87a1)

Отново не препоръчвам инсталирането им в продукционна среда – ако го направите сигурно много ми вярвате :)

Ще се радвам да споделите вашите наблюдения върху производителността с HPN-SSH patch-а.

Bonus info:

Прегледах и двете платени Windows имплементации за mount на sshfs като локално устройство:

  • SftpDrive – просто приложение, което прави точно това, което очакваме. Няма настройки за SSH протокола (алгоритми за криптиране, SCP и т.н.)
  • WebDrive – може да mount-ва Amazon S3, WebDav по SSL, SFTP/SCP, като поддържа подробната настройка на комуникационните параметри. За съжаление поне последната версия, която тествах бе доста бъглива. Има и допълнителен cache, който когато е включен се грижи за background трансфер на данните. Малко по-скъп е от горното приложение.
  • Мернах и решение с отворен код на SourceForge, което обаче беше докарано до под кривата круша и е дефакто неизползваемо.

Накратко, ако ви трябва прозрачна интеграция на sshfs под Windows, препоръчвам SftpDrive (да си помислят за комисионна в моя полза;)