Posts Tagged ‘работа’

2012-08-22 RBL за български спам

Wednesday, August 22nd, 2012

След като много време се каних и не го свърших, Велин направи RBL за източници на български спам. Попълнен е от един списък мои правила и един негов, репликиран е на три машини с добра свързаност и може да се ползва свободно от който си иска (на собствена отговорност, as usual).

Update: Правило за spamassassin:

header FCCF_BG_RBL      eval:check_rbl('fccf_bg','rbl.fccf.net')
describe FCCF_BG_RBL    rbl.fccf.net for sources of Bulgarian spam
score FCCF_BG_RBL       3.5 3.5 3.5

(score-овете вече може да си ги настроите както искате)

2012-08-13 Лекцията ми от VarnaConf (tldr)

Monday, August 13th, 2012

Това е лекцията ми от varnaconf – “Какво ми се иска да знаеха програмистите (а явно не го знаят)”.
(имаше няколко различни заглавия в тоя смисъл, не успях да подбера най-грубото)

Може би най-важното е да знаят, че имам лопата и си я държа под ръка…

Иначе, малко по-сериозно, да почна от там защо изобщо реших да водя лекцията. Пряко свързана е с работата ми и реално представлява мрънкане/оплакване от някаква част от проблемите, с които съм се срещал и не съм очаквал, че ще се срещна.
Моята работа по принцип е да карам неща, писани от други хора да работят. Това включва много debug-ване (което ми е едно от любимите занимания), много четене на код и малко писане. Държа да си кажа, аз не мога да пиша кой-знае колко добре, липсва ми времето и желанието за толкова съсредоточаване (ttee ми отне няколко дни, а не би трябвало).
Четенето на код е основно да разбера защо нещо не работи (или понякога как изобщо работи), съответно с мисъл за бъдещето обяснявам на хората къде е проблема, как може да се оправи, как аз съм го оправил, така че в бъдеще да не видя същото нещо. За съжаление ако историята ни учи на нещо, то е, че хората не се учат от историята, та моите опити са доста неуспешни. Приемете това като едно просто изливане на мъката.

Спрях се на два типа проблеми – теоретични и от неинформираност, понеже бях ограничен в 30 минути, но ще се опитам да засегна нещата в по-голяма дълбочина тук.

Ще започна с първия теоретичен проблем – copy-paste.
Copy-paste е метод за разпространение на грешката. Не мога да преброя колко пъти съм видял код, копиран няколко пъти и във всичките места със същата грешка. Човек би си помисли, че това е понеже няма как да се избегне (наистина има такива случаи), но най-често изглежда или като мързел от страна на програмиста, като липса на абстрактно мислене или като непознаване на езика и средствата на разработка. Голяма част от повторения код изглежда като писан от хора, които не са наясно че има неща като for цикли, функции, макроси и т.н..
Доколкото знам, започват да се появяват инструменти, които поне могат да откриват такива неща, но не съм забелязал сериозната им употреба. Тези неща много лесно се хващат с четене на кода (deja vu, “това някъде съм го виждал) и е едно от нещата, които code review може лесно да хване.

Умното писане ми е друг проблем. Много често се случва след-начинаещ програмист да открие нова възможност на езика, нов lib, нов метод на писане и да започне да го прилага навсякъде, където види, просто защото му се вижда много готин. Така се прилага безсмислено сложно средство за решаване на прости проблеми, което прави debug-ването много трудно, защото както е казал Браян Кърниган, “дебъгването е два пъти по-сложно от програмирането, така че ако програмирате с пълния си капацитет, не сте достатъчно умен да да го дебъгвате после”.
Някои езици много улесняват подобни неща, например Perl и C++. Мнението на Al Viro за C++ и защо не се ползва за kernel-а много добре показва проблема – накратко, езикът има твърде много възможности, всеки програмист свиква с някакво под-множество от тях, и когато в един проект се съберат да пишат няколко човека, се получава страшна смесица от стилове.
(на лекцията бях казал грешно, че идва от Линус, но мисля, че говорех за това, доста отдавна съм го чел)
По принцип често ме викат, когато трябва да се debug-не нещо такова супер сложно и омазано и най-честото нещо, което казвам е, че трябва да се пренапише.
(За пример за умен код давам примерните реализации на fizzbuzz, ако някой някога ми напише нещо като последната в production код, ще трябва да има преди нея поне толкова голям коментар, който обяснява защо е написано така и как точно работи)

Проблемът с валидацията може би ще иска отделна публикация, лекция, учебник, курс или религия по темата. Факт е, че след толкова години security и всякакви подобни проблеми никой не проверява получените данни.
(след малко дискусии с Кънев и още няколко човека искам да обясня, че например трансформирането на данните до вид, който е валиден също е вид валидация, т.е. правилното escape-ване например)
Докато водих лекции на едни ученици около летния лагер на БАН преди година-две във Варна, присъствах на тяхно предаване на проект, който представляваше симулация на банкомат – в общи линии му се подаваше сума и програмата по някакъв начин казваше в какви банкноти и по колко ще я върне. Имаше всякакви красиви реализации и т.н., но повечето изгърмяваха по неприятен начин (или зацикляха, или програмата умираше) на всичко, което не беше съвсем валидно – отрицателни числа, дроби, такива, за които нямаха типове банкноти – само защото нямаха няколко прости проверки в началото и вярваха, че входът ще е верен.
(това с вярването сигурно работи в религиите, но не и в програмирането)
Елементарното нещо – да се направи проверка още на входа на данните, се пропуска от всички. Много често ако има валидация, е от типа “shotgun” (т.е. все едно сте лепнали кода на стената и от далече сте стреляли по него с пушка със сачми, и където е паднала сачма там сте сложили проверка за нещо) и повече пречи, отколкото помага.
Друга такава елементарна грешка е идеята “аз пиша клиента и сървъра за нещо, значи данните ще са ми верни и няма защо да ги проверявам”, което е така до момента, в който някой друг се добере до този интерфейс и започне да праща там. Резултатите от това варират между викове “кой го е писал това” и вопли “как са ни хакнали и са ни потрили всичко?”…
Вариация на предното е “само аз пиша в базата, знам какво е и няма нужда да го проверявам” – имаше няколко случая на cross-site scripting през такива проблеми.
И нещо, за което малко хора се сещат изобщо, а на малкото останали хора, които държат на performance (като например game developer-ите) им е противопоказно е defensive programming-а – да се прави допълнителна проверка на още няколко места, понеже в крайна сметка всички допускаме грешки, нормално явление е да ги допускаме и е добре да ги хващаме. Пряко следствие от това е, че assert-ите не се пускат само в debug код, а и в production.

Като допълнение към валидацията, което не можах да разпъна добре на лекцията е, че няма замисляне колко сложни да се правят протоколите, така че да са лесни за валидация. Писах за лекциите от 28c3 и по-точно за Packet-in-packet атаката и за the science of insecurity, така че няма да повтарям (много), но е важно да правим всичко така, че да ни е нужен максимално прост апарат за обработката и валидацията му – колкото повече от нещата ни могат да се разберат и обработят с краен автомат например, толкова по-добре. В противен случай можем да се озовем в ситуацията на антивирусния софтуер, който спрямо математическата теория не може да бъде направен да работи напълно правилно.
(Проблемът там е като следствие от теоремата на Гьодел, която казва, че вътре в една система не можем да проверим дали всяко твърдение в нея е вярно или невярно, т.е. няма как със средствата на машина на Тюринг да валидираме друга машина на Тюринг)

И за пример за невъзможна за валидиране и използва сериозно система ще дам комбинацията от HTML5 и CSS3 (без JavaScript), която се оказва, че е Turing-complete.

След чистата теория нека да хванем няколко по-преки проблема.

“I don’t believe in miracles, I rely on them” изглежда да е стандартна програмистка философия. Трудно се схваща, че почти всичко може да върне грешка и съответно трябва да се направи нещо, ако това се случи. Като за начало, имам две парчета код за пример. Първото е “наивната версия”:

#define BUFSZ 8192
int fd0, fd1;
size_t len;
char buff[BUFSZ];

fd0 = open(file1, O_RDONLY);
fd1 = open(file2, O_RDWR);

while ( (len = read(fd0, buff, BUFSZ) !=0 ) ) {
	write(fd1, buff, len);
}

close(fd0);
close(fd1);

Второто е ремонтираната (DIE трябва да печата име на файл, име на функция, ред, подадения string и strerror(errno)):

#define BUFSZ 8192
#define DIE()...

int fd0, fd1;
size_t len;
char buff[BUFSZ];

if ( ( fd0 = open(file1, O_RDONLY) ) <0 ) DIE("open fd0");
if ( ( fd1 = open(file1, O_RDONLY) ) <0 ) DIE("open fd1");

while ( (len = read(fd0, buff, BUFSZ) > 0 ) ) {
	if ( write(fd1, buff, len) < len) DIE("writing");
}
if (len<0) DIE("reading");
close(fd0);
close(fd1);

(Оставил съм втората версия както ми е в презентацията, с грешките от един copy-paste. И аз съм идиот, това го видях на самата лекция, когато ми го посочиха)

Разликата е ясна, и примери от първия тип може да се срещат къде ли не. Най-често съм виждал такива неща при php програмистите, което може би идва от това, че понеже всяка маймуна може да пише на php, твърде много маймуни са започнали да го правят.

Втората версия не прави някаква магия и да решава проблема – тя просто ни дава едно важно свойство, наречено “failfast”, т.е. програмата да прекрати изпълнението си колкото се може по-скоро след като стане ясно, че не може да го завърши правилно. С код с подобно поведение и няколко други прекрасни неща, като идемпотентност на изпълнението (много дразнеща дума, значи в общо линии че ако кодът се изпълни 1 или N пъти, резултатът в крайното състояние ще е все същия, т.е. можем да повтаряме колкото си искаме) и ACID свойства можем да правим истински работещи системи, а не такива, които се чупят, като някой ги погледне накриво.

Fallacies of distributed computing са друго нещо, което много ми се искаше да е известно на повечето програмисти. Много често хората пропускат колко гнусно нещо като поведение е мрежата. Ще се спра накратко на няколко от проблемите:

Мрежата не е с нулева латентност – усеща се когато например се изисква два компонента да работят синхронно и да си разменят постоянно съобщения, за да си синхронизират състоянието. Тогава дори бързата локална мрежа ще вкара сериозни забавяния, а в момента, в който минем на нещо на по-дълги разстояния, повечето такива неща просто спират да работят.
Това е и едно от нещата, които не можем да очакваме по-добрия хардуер и физиката да поправят, понеже поне до момента няма нещо, което да можем да използваме за предаване на данни и да е по-бързо от скоростта на светлината.

Пропускателната способност не е безкрайна – понякога хората не се усещат, че предаването на указател към огромни данни през мрежата не става точно така.

Мрежата не е reliable – нормално е за мрежата да губи пакети, да изчезва, да има jitter, а ако е internet е нормално това да е още по-зле. Съответно не може да се пише какъвто и да е софтуер, който я използва без да се имат в предвид тези failure modes и да се взимат мерки за тях.

Мрежата не е сигурна – може да се подслушва, някой да се представя за някой друг и т.н. и т.н. и т.н., неща, които ги чуваме даже по новините и все пак никой не се сеща да ползва криптография.

Накратко, мрежата ви мрази.

Накратко два доста конкретни проблема от ползването на version control-а – още не се преподава сериозно, хората започват да го учат в движение в първата си работа и това води до всякакви проблеми, например до ползване на CVS или до това ако двама човека работят заедно, да седят един до друг и да си разменят файлове по skype.

Първият проблем от неяснотата как се използват VCS (version control systems) е че когато кажеш на някой “branch-ни това, за да работим спокойно по trunk-а” изобщо не те разбират, а като обясниш “направи копие еди-къде-си”, хората просто взимат файловете и ги add-ват наново там, което води до загуба на history-то. След като им се посочи грешката, те продължават да не схващат защо това е такъв проблем, понеже за тях VCS-а е само backup и commit messages са някакъв бълвоч, който никой не гледа, а когато потрябва да се гледат, вече е късно.
(Много е забавно да се анализират всички commit messages на някоя фирма и да се види кои са най-често срещаните думи. Моята любима (беше на 10то място в една фирма) е “blahovina”)

Вторият проблем е как като се прави някакъв сайт, редовно се слага config файла в repository-то. Понеже този файл е различен за production-а, staging-а и за машините на developer-ите, редовно се случва някой да го commit-не от грешната машина и да го update-не в production-а, чупейки всичко. Двете решения, за които аз знам са или да се прави template на този файл и само той да стои в repo-то, а другото е да се detect-ва средата и да се load-ват подходящите настройки (както прави rails, доколкото схванах).

И един bonus за четящите тук – нещо, което не можах да спомена в лекцията, но обсъждахме доста подробно след това, външните dependencies на един проект, кой носи отговорност за тях и как се update-ват. Ще говоря основно за неща, които се deploy-ват по сървъри, но има доста паралели и с end-user-ския софтуер.

По принцип имаме два варианта. Единият е да използваме външните неща от дистрибуцията/операционната система, оставяйки на тях отговорността (и подбирайки ги правилно, например да ползваме debian stable или centos или rhel), другия е ние да си ги вкараме в проекта и да си носим отговорността за тях.

Много проекти се спират на втория вариант, след което обаче забравят какво са вкарали, или пък дават зависимости през външна пакетна система (например ruby gem-ове) и пак забравят да ги update-ват. Или не забравят да ги update-ват, но не смеят, понеже ще се счупи нещо. Или ще update-нат цялото нещо към най-новата версия заради някакъв супер готин нов feature и ще потрошат цялата система.

За това хората, които не разбират как се прави това, не трябва да го правят – ако човек не участва в оперативната работа (я като админ, я като част от devops екип), по-добре да остави на другите да му кажат версии и външни пакети, за да може да се работи стабилно и без downtime. Като малка реклама на debian stable (и донякъде ubuntu server lts), те правят дистрибуция много подходяща за сървъри, понеже въпреки, че са със стари пакети, те реално за живота на дистрибуцията винаги backport-ват важните patch-ове (основно за security проблеми), така че системата е едновременно и сигурна и не се променя поведението ѝ.

Специално за външните dependencies също мога да направя цяла отделна лекция, в която да си излея мъката.

За всички, преживели изчитането на това – снимка на обстановката, в която спах във Варна :)

(най-много ме зарадваха силно невярващите погледи на някои хора от залата, т.е. има надежда, че има програмисти, които знаят тия неща)

2012-07-18 лекция “Дребен пример от разпределеното програмиране”

Wednesday, July 18th, 2012

Мина лекцията във вторник, има запис и може да си свалите пълния архив с презентацията и парчетата псевдокод.

Отделно ето я и самата презентация.

Става въпрос за тип задача, която не намерих в design patterns, и за която има различни парчета софтуер, които правят нещо подобно (rabbitmq, gearman). Основната причина да се пише от нулата, вместо да се ползва нещо готово е, че се интегрира много по-добре в съществуващата система и така е доста по-просто, отколкото да се добавя още някакво парче код.
(и е интересна задача :) ).
Имам в практиката си три реализации, като това, което показвам прилича най-вече на една от тях, система за encode-ване в няколко формата на видео. Имаме много сървъри, които се занимават с encode-ването (cli.*) и които си взимат задачи от централен диспечер (srv.*), който има някакъв вариант да пази persistent state (в моя случай – база данни). Задачите са индемпотентни, т.е. могат да бъдат изпълнени повече от един път, ако се наложи.

Езикът, който съм ползвал в примерите е в общи линии псевдокод, който прилича на смесица от perl и php. Странните неща в него са, че има мнoжествено връщане (т.е. конструкция от типа $a, $b = f()) и че respond в srv.* връща отговор на клиента и излиза, т.е. прилича малко на return. man pages описват семантиката на fork и wait.

Начален вариант на решението би бил с този диспечер и този клиент.

Първият проблем, който се вижда е, че ако сървърът не успее да свърши задачата, няма как да го съобщи на диспечера. Това лесно се коригира с добавяне още на един тип заявка към диспечера:
Версия 1: диспечер и diff от предишната версия, клиент и diff от предишната версия.

Вторият проблем е какво става, ако заявим, че искаме задача, диспечера ни я задели, но не получим отговора? Ако нямаме обработка на този случай, в такива ситуации ще се натрупват задачи, които се водят, че се обработват и реално никой не ги е взел. Решението, до което аз стигнах е да добавя на всеки сървър transaction id и при заделяне на задача диспечерът да отбелязва сървъра и transaction id. Ако клиентската част подаде заявка за нова задача и не получи отговор, трябва специално да подаде обратно заявка за “cancel”, за да сме сигурни, че неполучената задача е върната в pool-а на свободните задачи.
Версия 2: диспечер и diff от предишната версия, клиент и diff от предишната версия.

Третият проблем е рестартирането на някой от сървърите, които обработват задачи – например поради спрял ток. Когато той се стартира отново, според диспечера ще има няколко задачи, които той обработва и за които той не знае. Решението е просто – добавя се тип заявка, която се подава при рестарт и почиства работещите задачи за даден сървър.
Версия 3: диспечер и diff от предишната версия, клиент и diff от предишната версия.

Четвъртият проблем (който би трябвало да е един от първите) е колко често и кога да се опитваме да повторим заявка към сървъра. Всяка заявка, която може да подадем може да стигне, но може и да не стигне до сървъра, или ако стигне, нямаме гаранция, че ще получим отговор. Съответно трябва да добавим към srv_request() в клиентската част логика колко пъти и как да опитва – само веднъж, много пъти или безкрайно. Заявяването на задача трябва да се изпълнява точно един път, останалите неща – докато се получи отговор.
(от “много пъти” смисъл в повечето случаи няма и би трябвало да го махна от кода)
Друг проблем, който се вижда доста бързо е, че ни трябва нещо от типа на exponential backoff, за да разредим честотата на опити от страна на сървърите към диспечера. Това се прави, за да се избегне ситуация от която след restart изведнъж се изсипват твърде много заявки в/у диспечера и има шанс да го претоварят. Същото нещо може да се види и в доста мрежови протоколи, например TCP.
Версия 4: клиент и diff от предишната версия.

Петият проблем е да ограничим колко товарим себе си (и донякъде сървъра), като ограничим броя задачи, които изпълняваме. Прави се сравнително просто, с брояч на вървящите в момента child процеси.
Версия 5: клиент и diff от предишната версия.

Шестата версия е основно дописване и доподреждане на кода, с оправяне на няколко проблема, които само ми хрумнаха и не съм виждал на живо. Едното нещо е валидация на state на определена задача, другото е един race condition м/у fetch и cancel (който по принцип не трябва да може да се случи).
Версия 6: диспечер и diff от предишната версия.

Има функционалност, която по различни причини не е дописана в този код:

– да връщаме на всеки сървър колко да изчака, преди пак да пита за задача, като метод за flow control.
– job timeout/job restart – да решаваме по някакъв начин кога да рестартираме определена задача (понеже е възможно сървърът и да е умрял и да не се е върнал повече). Това не пасва добре в текущия код, т.е. трябва да се напише отделен компонент, който се вика периодично или работи като демон при диспечера, който да изпълнява тази функционалност, а самата логика за това зависи твърде много от контекста.
– Log на всички събития – животоспасяващ при всякакво дебъгване.
– Monitoring и аларми при различни състояния, дефинирани като проблемни (твърде много чакащи задачи, твърде много обработвани и т.н.) – пак трябва да е в отделен от тези два компонента.

2012-07-12 пак лекция

Thursday, July 12th, 2012

Ще водя още една лекция в initLab във вторник (17.06) от 19:30. Пак ще се stream-ва на http://tyler.ludost.net:8787/lab.ts и пак през irc ще могат да се задават въпроси.

2012-07-01 leap second

Sunday, July 1st, 2012

Jul 1 02:59:59 marla kernel: [3317066.443888] Clock: inserting leap second 23:59:60 UTC

Полезна команда: /etc/init.d/ntp stop; date; date `date +”%m%d%H%M%C%y.%S”`; date; /etc/init.d/ntp start

(при някой може да е ntpd, видях го в outages листата)

Поради високосната секунда, която се появи снощи доста java приложения, firefox/iceweasel и някои версии на mysql, всичкото това под някои linux kernel-и и при още няколко условия зависват/започват да ядат много CPU. Горната команда помага, по принцип и с рестарт на приложението.

Моите наблюдения:
Стандартен debian-ски mysql със стандартен debian-ски kernel (stable) няма проблем на две машини (marla и tyler);
mysql 5.5.25-1~dotdeb.0 в/у debian stable имаше проблема;
tomcat6 на debian stable има проблема (tyler);
jenkins на debian stable има проблема;
virtualbox на ubuntu 10.10 (2.6.32-41-generic) и debian testing (3.2.0-2-amd64) virtualboxsvc-то има проблема (на phyllis);
gentoo с mysql 5.1 при ядро 3.3.6 (компилирано от мен) няма проблема;
debian testing с iceweasel има проблема;

Събирам още информация.

(12:47) Данни от Весо: RHEL6, kernel-2.6.32-220.23.1.el6.x86_64, mysql 5.1.61-1.el6_2.1 няма проблема.
(13:01) Данни от Пейо: fedora 15, kernel 2.6.43.2-6, mysql-5.5.22-1.fc15.x86_64 няма проблема.

Update: Хубаво обяснение на проблема.
Update 2: Още по-добро обяснение.

2012-04-18 прибиране от Холандия

Tuesday, April 17th, 2012

Днешния ден си заслужава описване сам по себе си…

Всичко си беше добре, докато не ми се обадиха с един проблем. Спряла сравнително важна машина (и сложна за дублиране), която не е убила всичко, но е добре да се върне.
Стандартният начин с reset не свърши работа, та се засилих към ipmi-то да се опитам да видя конзолата. Да, ама там на софтуера изтекли някакви сертификати и се оказа много много сложна задача да бъде подкаран, а понеже машината е доволно отдавнашна, не е ясно каква е точно и реших да не flash-вам firmware на сляпо.
Намери се един tool от supermicro, който да може да си говори с ipmi-то и конзолата. Последва паралелно подкарване на няколко варианта – пускане на тоя софтуер на машина там и гледане през remote X, подкарване на друга машина, подкарване вкъщи (много тъпа идея, щото vpn-а ми от там отиваше до счупената машина), подкарване при мен на лаптопа и на нов vpn (аз все пак си бях още в Холандия). Всичко това се развива в последните часове преди полета ми, та съответно трябва да се бърза…
В крайна сметка се добрах до желязото (първо през една толкова претоварена машина, че можеше да се работи до 10 минути и после се успиваше) и се оказа, че след всичките upgrade-и прекрасното gentoo просто не си казва и не си update-ва конфигурационните файлове, та мрежата (която има доста сериозна конфигурация) просто не тръгнала, заедно с още 4-5 service-а, дето пак има промени по конфигурацията им.
С проби и грешки (които, колкото и да е странно ми се струват повече от пробите) успях да подкарам базови неща по машината и да се вижда отвън. Финалните неща ги дооправях по пътя към летището, през tethering през някакъв телефон (за което много много много благодаря). Опитах се да се свържа с някой да види дали не съм пропуснал нещо, ама не можах да открия никой.
(останали бяха две не-спешни неща, които оправих преди малко)

Успях да си забравя една от книгите, та в самолетите четох от лаптопа, добре, че и там си държа поне няколко книги.

На летището в Амстердам ме забавиха, защото някаква част от usb оборудването ми (един usb вентилатор) им беше заприличал на патрон (мисля, че Тинчев или Чорбаджийски ми го подариха), беше си направо смешно…
(нещо такова, ама само горната част, то е разглобяем комплект)

Полетът ми до Виена закъсня и трябваше малко на бегом да стигна до изхода за следващия, но те малко го забавиха и всичко стана както трябва (като гледам, и багажа ми са го прекачвали на бегом, има една лепенка на Lufthanza “HOT”).

А София ме посрещна с дъжд. В Холандия не успя да ме навали, а тук успя, направо ми е трудно да го повярвам. Мисля да видя дали няма още нещо счупено или за дооправяне и да си легна.

2012-02-04 борба със скуката

Saturday, February 4th, 2012

Сериозното нещо, което пиша не е готово, така че ето с какво се забавлявах в последно време, за да не ми е скучно:

Дойде желязото за курса по системна администрация и проучвам точно с какво ще го ползвам. Дотук vmware бяха дисквалифицирани заради windows-only клиенти, така като гледам това, което има за Xen за linux е силно счупено (openxenmanager), вероятно ще трябва да направя някоя магия. Ето така ми изглеждаше бюрото снощи, по време на началния setup.
(да живее ipmi-то, мога да държа желязото в другата стая и да го паля/спирам отдалечено, че вие ужасяващо)

Компилирах си osmocombb за openmoko gta02 телефона. Задачката беше забавна, понеже има няколко различни среди за компилация, а самия osmocombb е мислен да работи на pc-то (host-а) и да сипва един малък firmware на отсрещната машина, а вече на host-а няколко приложения да се закачат към osmocon-а и да правят каквото правят. Съответно имаше компилиране на osmocon за moko-то, което отне един следобед в проби и грешки, заедно с още няколко часа подкарване на правилната версия на cell_log. Сега обаче цялото нещо умира в първите няколко минути, трябва да се види дали е от хардуера.

Около работата има други забавления. Последното е компилация на libprotobuf за symbian, та в момента се точи SDK-то. Имаше преписване на чужди заявки, дебъгване на странни рядко-случващи се явления (хората стават много нещастни, като се пропусне да се отбележи плащане, а знаехте ли, че в php при FastCGI се ползва един формат на header(), в останалите случаи друг?), обработка на binary данни в java (какъв език е тва, че няма htonl()), търсене на ntfs partition в някакъв пратен от на майната си диск и разни други стандартни неща за правене.

Взех си два албума на deathmole (виртуалната група на автора на Questionable content), звучат приятно.

Подкарах си statusnet на s.ludost.net, чиято цел е да ми замести twitter-а (вече го има него в sidebar-а на блога). Остава ми да го вържа с jabber-а да ми праща какво се случва, да му вдигна https, вероятно да му напиша филтри и ще е съвсем използваемо. Който иска да ме чете/добавя – http://s.ludost.net/krokodilerian
(а си подкарах statusnet, понеже съм решил, че е крайно време да се мине от cloud бози на federated тип услуги, но това ще е тема на друг post (или по-скоро няколко). Още пиша бележки, да видим какво ще излезе.)

Вече има ipv6 адрес на marla.ludost.net (раздадоха ми /126 от evolink, май даже на тях самите им се вижда странно) и вече web-а и още няколко неща се виждат спокойно от там. Има няколко неща, които още не съм пипнал поради мързел и понеже очаквам странни трудни-за-виждане-и-още-по-трудни-за-дебъгване-проблеми (ejabberd + две машини + dialback + комуникация с gtalk и някои други хора), та ще си ги оставя за когато ми стане наистина скучно.

2012-01-08 Кръщене

Sunday, January 8th, 2012

Имам да кръщавам една машина, която трябва да замени zver.fsa-bg.org (преди тотално да се е разпаднал). Машината е дребна, средно мощна (определено повече от предишната), тоя път rack-mountable.

Двата дефиниращи принципа са дребност и унверситет. Ето идеите:
Ескарина (от Eskarina Smith, “Equal Rites” (“Еманципирана магия”) на Тери Пратчет);
Neville на Neville Longbottom от сериите за Хари Потър;
Kvothe (от книгите на Патрик Ротфус);
Tiffany (Tiffany Aching пак от Тери Пратчет);
Ayaan (Ayaan Hirsi Ali, въпреки че може би няма да пасва толкова);
Miles (Майлс Воркосиган, от книгите на Л. М. Бюджолд);

Приемам и други. Cassie (от “Skins”) вече е е заето, да я кръстя на Николай Генчев не върви (за него си трябва нещо по-голямо), някой математик (като Галоа) също може, въпреки че аз не ги обичам кой-знае колко, “Ada” (Ada Lovelace) вероятно е твърде използвано в тия среди.
Ако някой измисли наистина добро име, обещавам да го отбележа на страницата на машината :)

(мислех и по темата да кръстя машината на някой жив човек, студент/студентка или преподавател(ка), но по принцип хората това никак не ги радва. Помня как кръстих едно време машина на приятелката на един приятел и той ме гледа на кръв поне две седмици)

Update: Кръстих я octavo, “preslaff” да каже как да го отбележа :)

2012-01-03 лекции от 28c3

Tuesday, January 3rd, 2012

Какво (още) гледах от 28c3:
(mirror-нал съм всичките английски записи на 28c3.ludost.net)

Keynote беше донякъде интересен, но имаше доста дупки в живото предаване. Ставаше въпрос за SpyFiles на wikileaks и изобщо индустрията, която се занимава с подслушване, мисля, че нямаше нещо много ново там.

От лекцията за Atari 2600 не можах да гледам много, но ме зарадва с това, че вече не ни се налага да работим с толкова ограничен и ужасяващ хардуер (частта за това как се избира банка от паметта с четене на определен байт и как писането се прави с четене бяха направо плашещи).

SCADA and PLC Vulnerabilities in Correctional Facilities беше интересно, въпреки че в основата си е просто хакване на хардуер, който никога не е мислен да е сигурен (и който за съжаление се използва твърде много). В общи линии полезна лекция за всеки, който реши да бяга от затвора.

Лекцията за еволюиране на алгоритми беше забавна, почти “как с random и малко техники да си създадем алгоритъм за каквото си искаме”. В тази лекция обясниха основните неща и показаха как са правили алгоритъм за един филтър за картинки, в другата показаха как са еволюирали протокол за комуникация (което беше наистина адски интересно и поне в началото трудно за вярване).

802.11 packets-in-packets беше една от най-забавните лекции на конгреса и като цяло интересна атака – да се вкара пакет на layer1 от layer7 (т.е. накратко можете да бълвате специфични пакети през tcp, udp или каквото ви падне, да ги предаде някое AP и клиентите да го прочетат по различен начин). Определено си струва гледането.

Не можах да гледам The coming war on general computation на Cory Doctorow, но някакви добри хора са написали transcript, мисля, че е важно да се прочете/гледа.

Kartsten Nohl и Luca Melette говориха за как да си предпазим мобилния телефон, последните им разработки по темата за GSM и компания. Например са направили firmware за телефон, който report-ва т.нар. “flash sms” и може да усеща дали някой прави man-in-the-middle атака.

Black OPs of 2011 на Дан Камински беше същата лекция като от CCC Camp-а, т.е. нищо ново.

Вторият ден започна с Food hacking лекция, която мога да използвам да плаша всичките “еколози” и противници на ГМО. Имаше всякакви забавни неща, от грейпфрути, отглеждани чрез облъчване с радиация до суши от светещи риби. Във въпросите след лекцията една девойка пита как точно да готви скакалци…

Data mining the Israeli census беше приятна лекция, но нищо особено – какви анализи са правили на изтеклата (5 пъти за 10 години) база данни с населението на Израел.

За лекцията за DoS-ването на web неща вече писах подробно.

The science of insecurity според мен беше най-важната лекция на конгреса. Meredith Patterson обясни много добре как сами си копаем гроба, като правим протоколи, за които няма дори теоритичен начин да проверим дали някакви данни са валиден вход, понеже представляват Turing-complete езици, а там проблемът с валидацията се свежда в общи линии до halting проблема. Аз не знаех, че някой вече е доказал, че HTML5 и CSS3 (без javascript) са turing-complete комбинация (и се зачудих колко е вероятно от web-а да се роди skynet).
Друг интересен момент беше колко по-сложно е да се напише прост parser за контекстно-зависими граматики (например, всичките протоколи, които имат length поле), и как би трябвало да се стремим към прости неща, които един елементарен краен автомат може да parse-не (т.е. които могат да се parse-нат еднозначно с регулярни изрази, например). Като пример за проблеми с length полето беше дадена атаката за 802.11 packet-in-packet.
И една от важните идеи, които със сигурност ще приложа (преди нямах толкова добро оправдание) ще е всичките parser-и и подобни неща да се генерират автоматично от ясна формална граматика, така че винаги да се работи с ясни данни и ясна валидност. Това така и така щеше да ми трябва, понеже ще гоним междуплатформеност…
(на който не му е ясно какво говоря, да почете малко за йерархия на граматиките на Чомски, машина на Тюринг и какво значи Turing-complete).

От третия ден трябва да спомена лекцията на Пейо за електронните пари (както и да му кажа, че той вече е celebrity :) ), която беше малко по-съкратен и подреден вариант на тази от Openfest. Иска ми се това да го направи на хартия и да му даде цялото нужно място (т.е. около 2-3 часа говорене), ама да видим кога ще успея да го изнудя.

Лекцията за атаките в/у принтери също беше от много веселите, а проблемите в сигурността, които се оказа, че има там бяха пак от смешния тип (например възможност да смениш firmware на устройството с печатане на файл). Ако имате HP принтер, вижте лекцията и дали трябва да се update-нете.

От четвъртия ден май си струва да спомена само лекцията на NOC-а за мрежите на CCC Camp-а и на текущия конгрес. Особено забавна беше реализацията на “таван/чадър” за wifi AP-тата от кофи и тръби.

Имаше и няколко доста неприятни лекции, или много объркващи (например една за квантовата криптография), или тотално неразбираеми (имаше един французин, който говореше за криптография и на 20тото казване на “Titanic” (с ударение на последната сричка) се отказахме да го траем), или bullshit (един, който говореше за влиянието на leak-овете в/у конспирации в контекста на целта на wikileaks и който накрая го питах не смята ли, че математическия модел, който ползва е почти толкова смислен, колкото сферичен кон във вакуум).

Има още няколко неща, които искам да гледам и едно, за което искам да напиша отделен post – depression panel-а, който се е случил почти против желанието на организаторите, понеже са счели темата за неподходяща. Надявам се да намеря време в следващите дни:)

2011-12-29 28c3 – атака в/у hash таблици при web платформи

Thursday, December 29th, 2011

Малко за гледаните лекции от 28c3 – ще бъдат в няколко post-а по ред причини.

Ще започна с една лекция, която описа в общи линии нов проблем в повечето web-facing езици/framework-ове в хеш реализациите, за който даже написах малко код.

Къде е проблемът – повечето такива езици (в случая – perl, php, python, java, ruby, asp.net) използват hash-ове (познати още като асоциативни масиви), за да подадат към програмиста параметрите, които са дошли от HTTP request-а (най-вече от POST-а). Почти всички го реализират, използвайки стандартни hash таблици с 32 или 64битов hash (не-криптографски, т.е. даже и CRC32 би свършил работа, повечето ползват нещо, писано от DJB, например DJBX33A).
По принцип insert-а на нов елемент в такава таблица е с ниска/константна сложност, но ако вмъкваме само елементи, които дават същия hash, сложността става максималната възможна, т.е. O(n) и съответно вмъкването на n елемента ще е от порядъка на O(n^2).
Накратко, ако подадем (например) през POST параметри, които се хешират към същата стойност, времето, което ще отнеме на езика/framwork-а да обработи заявката (преди да стигне до вашето приложение) ще е бая, като тестовете при мен показаха нещо от порядъка на 1 минута за заявка с 62000 параметъра и голяма около 400kb. В лекцията (има и запис, mirror-нат при мен) има повече подробности и тестове.

Реших да видя доколко мен ме лови тоя проблем. Като за начало трябваше да си напиша генератор на тия стрингове (ВНИМАНИЕ: грозен гаден код на C), което се оказа сравнително лесно – измъкнах от source на php от Zend/zend_hash.h тяхната функция, поразгледах кода и се оказа, че от hash функцията се взимат първите X бита, като X е в общи линии log2(N) (където N е броя елементи в стуктурата). Съответно ако ми трябват по-малко от 65536 collide-ващи стринга ми е достатъчно да търся колизии само в първите 16 бита. Моята некадърна програмка на машина със 192GB памет (трябваха и около 120GB) се справи за около 5 минути.
(пускам кода като пример, който може да го разбере би могъл да си го напише и сам сравнително лесно).

Имам да се поровя още малко, но в някои случаи debian-ската default-на конфигурация реже тия атаки (понеже не позволява повече от 1000 променливи в какъвто и да е request, което па от своя страна чупи малко (малоумен) софтуер), в някои не и повечето php-та, които човек може да намери по net-а ги лови тоя проблем. Реализирането на DoS-а за да направи реален проблем изисква прилично количество паралелни връзки и определено не е толкова опасно, колкото беше проблемът с Range request-ите от август, но пак не е приятно. Също така може да се атакува и през други места, например ако трябва да се сглоби json request или какъвто и да е hash, чиито ключове зависят от данни, подадени от потребителя.

Решението е да се random-изира hash-а на всяка заявка, за което си написах една тестова програмка, която да пробва в/у такива подбрани string-ове hash, който освен всичко XOR-ва всеки 8-байтов блок от входа с един random seed. Мисля ако скоро не изкарат някакво хубаво решение да си patch-на директно php-то, но още не съм имал време да намеря подходящия entry point, в който да вкарам инициализацията на seed-а, така че хем да е различен за всеки request, хем да не счупи нещо по много лош начин (ако някой е бърникал по кода на php и знае къде, много моля да пише).

Та, добри хора, прочетете оригиналното advisory и се patch-вайте, ако правите нещо свързано с web най-вероятно проблемът ви засяга.

2011-12-09 fizzbuzz

Friday, December 9th, 2011

Странен сезон е. Сутринта валя, два дни подред пия, едвам намирам време да си свърша работата (не щото е много, а щото нещата се припокриват и има чакане) и съм пил вечерта, че да блогна.

Всички вероятно са чували какво е fizzbuzz, но пак да го кажа, накратко – задачка да се отпечатат числата от 1 до 100, като ако числото се дели на 3, вместо него се печата “Fizz”, ако се дели на 5 вместо него се печата “Buzz”, а ако се дели на 15 вместо него се печата “FizzBuzz”.
(това се дава на интервюта да се види дали човека изобщо може да програмира)

Оригиналното решение, което всеки може да напише на листче (говорим само за C) изглежда така:

for (i=1;i< =100;i++) {
	if (i%3==0) printf("Fizz");
	if (i%5==0) printf("Buzz");
	if (i%3!=0 && i%5!=0) printf("%d",i);
	printf("\n");
}

(което е почти същото на повечето езици за програмиране)

Оптимизираният вариант, който ми хрумна изглеждаше по следния начин:

int i,p;
char *s[4]= {"%d\n", "Fizz\n", "Buzz\n", "FizzBuzz\n"};
int s3[3]={1,0,0},s5[5]={2,0,0,0,0};

for (i=1;i<=100;i++) {
	p= s3[i%3] | s5[i%5]; 
	printf(s[p],i);
}

(накратко си избира максимално бързо format string-а, като се прави индекса му от два бита – единия за дали се дели на 3, другия на 5, след което се вика printf() с него и аргумента, а ако във format string-а няма “%”, то вторият аргумент изобщо не се гледа)

Методът с lookup таблиците е известен от зората на програмирането и е един от най-хубавите примери за time-memory trade-off.

Това решение няма branch-ове (т.е. if() и компания) в основния си код, но пък разчита на printf(), който не е особено бърз. На пиенето на Титов му хрумна, че може да се направи масив от функции, които да правят различните неща, но па на мен идеята за call и ret не ми хареса особено, за това се замислих и открих, че в C всъщност има масив от label-и. Съответно, ето извратено и максимално бързо решение:


int i,p;
static void *pos[4]= {&&digit, &&fizz, &&buzz, &&fizzbuzz};
int s3[3]={1,0,0},s5[5]={2,0,0,0,0};
char buff[2048];
char dgts[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
int buffpos=0;

for (i=1;i<=100;i++) {
	p= s3[i%3] | s5[i%5]; 
	goto *pos[p];

fizz:
	memcpy(&buff[buffpos],"Fizz", 4);
	buffpos+=4;
	goto end;
buzz:
	memcpy(&buff[buffpos],"Buzz", 4);
	buffpos+=4;
	goto end;
fizzbuzz:
	memcpy(&buff[buffpos],"FizzBuzz", 8);
	buffpos+=8;
	goto end;
digit:
	buff[buffpos++]=dgts[i/16];
	buff[buffpos++]=dgts[i%16];
end:
	buff[buffpos++]='\n';
}
write(1,buff, buffpos);

(т.е. както в предния пример имаме масив от format string-ове, тук имаме масив от позиции, на които директно можем да скочим. Също така не викаме никакви външни функции (memcpy се inline-ва и е от едни по-бързи инструкции) и единствения branch, който имаме е за for() (който също може да се избегне с една lookup таблица и едни goto-та, ама това вече ще е гадно)

Човек, способен да напише подобен код на интервю вероятно трябва да го пратят в Карлуково.

Ако на някой му хрумне нещо по-забавно, да пише :)

Update: Оптимизация – да се изместят p3, p5 и dgts като глобални променливи, понеже ако са във функцията, компилатора ги прави на много mov-ове.

2011-11-08 интервюта

Tuesday, November 8th, 2011

Уважаеми програмисти.

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

Имайте какво да покажете. Код, нещо работещо някъде, каквото и да е, просто да може да се прецени как пишете. Даже няма чак такова значение точният език, на който ще го покажете.

Имайте идея какво показвате, да не ви се случва да попадна на следната конструкция в кода ви (оригиналът беше на objc, това е приближение):

if (a!=NULL && b) {
	do_something();
	do_another_thing();
	if (b) {
		do_crap();
	}
}

и да не можете да ми обясните защо трябва пак да се проверява b.
(напълно е възможно да има причина. Проблемът е с неспособността да се отговори на такъв прост въпрос)

Ако сте учили в (и даже завършили) някой университет по специалността, имайте базова идея от алгоритми и сложност. Това да ми обясните двоично търсене и да не ми кажете каква му е сложността и до колко е сравнимо с различни други такива търсения не е хубаво.
(също така, оценяването на сложността на алгоритъм, алгоритмите за търсене и сортиране и т.н. хубави неща не може да казвате, че не ги знаете, защото “аз предпочитам програмирането пред математиката”)

Ако работите с някаква технология, познавайте я поне отчасти. Много е лошо да задам въпроса “защо ползваш mysql вместо текстов файл”, и да не може да ми се даде смислен отговор. Също така, не бъдете от хората, които правят “SELECT * FROM table” и после си взимат каквото им харесва от резултата.
(ако все пак сте от последните, моля, купете си литър белина и го изпийте)

Намерете малко увереност в себе си. Казвайте си какво знаете и какво не знаете. “Момент да помисля” също е приемлив отговор на разни въпроси.

Ако смятате, че сте програмист, понеже сте направили нещо тривиално и то сработва – грешите. Пример – ако сте направили мобилно приложение, което показва конституцията на Армения, това не ви прави програмист на мобилни устройства. Придобийте поне бегла представа какво значи “тривиално”.

Не бъдете коне с капаци. “Аз искам да пиша за MobileOS версия 9.жм.жд.жбр и друго не искам” е тъпо изказване, почти като “аз пиша на php4 и не искам да се занимавам с php5”. Ако нямате желание да се учите и развивате, моля послушайте изказванията на текущия ни идиот^Wпремиер и ходете да гледате овце, доколкото разбрах, има недостиг на работна ръка.

2011-10-11 скъпи програмисти

Tuesday, October 11th, 2011

Скъпи програмисти,

Днес, дебъгвайки поредният проблем, причинен от вас, реших, че е крайно време да обясня нещо животоспасяващо. Животоспасяващо, защото ако го следвате, шансът да ви издебна в тъмна нощ и да ви заколя намалява сериозно.

В общи линии са две неща.

Едното е болестното ползване на framework-ове и други подобни нива на абстракция без реален смисъл. Примерни такива бози има на много места, на мен едно от най-омразните ми е cakephp (вероятно понеже с него съм се борил най-много). В повечето случаи нещо, което спестява 10% от вашето писане за сметка на едно огромно мазно средно-рядко лайно, което 1) стои във version control-а, 2) прави проследяването на действието на кода един порядък по-трудно и 3) е нещо, което не може да се update-не лесно (което ще обясня след малко) не си струва. Нито за вас (щото ще ви е по-трудно да намерите проблемите, които сами сте си създали), нито за мен, докато се опитвам да го подкарам или мигрирам, нито за който плаща. Just say no, и пишете кода колкото се може по-близо до естествената му среда – системни библиотеки, стандартни драйвери и т.н..
(друг пример е начинът, по който request-tracker ползва база данни и заявките от типа на “SELECT main.* FROM table1 main, table2 b …” и невероятната плетеница от callbacks, които са направили).

Второто нещо е, че външните библиотеки не са ваш проблем, ваша работа, ваша отговорност и по НИКАКЪВ начин не са от нещата, които трябва да се набият във version контрола, освен ако не поемете пълна отговорност да ги поддържате. В противен случай оставете работата на хората, които разбират от upgrade-и, миграции, системата на която работи софтуера ви и т.н. и не им създавайте допълнителни главоболия. Не ви е възможно да следите всички security update-и, всичките несъвместимости на стария lib с новите среди, а авторите на тия неща се справят доста добре с правенето на нещо, което да е backwards compatible (т.е. да работи с ужасът, който сте накодили) и същевременно със средата, в която оперирате.

Благодаря за вниманието.

(за тези, които ще ми обясняват колко са прекрасни тия framework-ове – аз мигрирах един магазин от cake на чисто php (дето не ставам за програмист) и излезе доста по-кратко и по-изчистено)

2011-07-25 разсейване

Monday, July 25th, 2011

В последните дни на два пъти попаднах на хора, които казваха неща от типа “трябва да си махна X от компютъра, за да не се разсейвам и да върша работа”. Смятам това за лоша/глупава идея, по следните причини:

Като за начало, нещата, които искат да махнат не са прекъсвания, т.е. не им отвличат сами вниманието, а те сами трябва да си ги погледнат (пощата, rss четеца и т.н.). Това автоматично значи, че го правят сами, тяхното желание за разсейване ги води и проблемът не е външен, а вътрешен. Колкото и да си режат нещата, с които могат да се разсейват, те винаги ще намерят нещо друго (например да гледат в една точка в стената, или да пропишат стихове, или някоя подобна глупост).

Също така, ако човек има желание да си отвлича вниманието, това в общи линии значи, че нещото, което върши не му е интересно. Насилването да се върши скучна работа по принцип не води до особено добри резултати. По-добре да се отклоним малко, да направим нещо друго и после да се върнем към задачката, като другото ни писне. Аз лично в такива случаи гледам да правя по няколко неща и просто да сменям едната работа с другата, за да си почивам.
Има задачи, които не се поддават на този вариант – дадоха ми пример с писането на документация за завършен проект. Нямам добра идея за тях, освен да се измисли някакъв hack (например за документацията – да се пише по време на проекта, като почивка от самото подкарване).

Понякога трябва и да се почива от някаква работа, или просто да се прочисти главата (като се забием някъде) и тогава разсейванията вършат тази работа – дават възможност на мозъка да спре, да почине и да сдъвче на заден план проблема. На мен са ми хрумвали решения на проблеми, докато чета книга, която няма нищо общо.

Имам и едно много хубаво сравнение за тая практика, да се самоограничаваш насила, за да се подобриш – в “Архипелага ГУЛАГ” на Солженицин има в една глава описание как като преминеш през лагера, характерът ти се закалява и се получават други различни подобрения на човека (ако оцелее, и като не броим съсипаното здраве). Така по същия начин човек няма проблем да се научи на дисциплина, като иде я до Северна Корея, я някоя друга държава с подобен режим (или може да ходи в казармата, може би още имат подходящо обучение). Накратко, прекрасна идея за мазохисти.

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

2011-07-18 jabber сървър на ludost.net

Monday, July 18th, 2011

След много мърморене от разни хора и борба със собствения ми мързел, вече има jabber сървър на ludost.net.

Броя го за момента за beta версия, т.е. очкавам да се каже какви проблеми се появяват, за да мога да ги оправя.

В момента има SSL сертификат, подписан от cacert, и е сложен на две машини – едната в evolink (marla), другата в telepoint (tyler), т.е. трябва да се справя сравнително добре с отпадания на някакви части от българския net и да не е чак толкова лесно за подслушване.
(аз обещавам да не чета какво си пишат потребителите, то така или иначе е скучно)

Регистрацията е отворена за момента, ако намеря причина за в бъдеще може да я огранича. Планирам бавно да преместя всичките си контакти от другия jabber сървър, който ползвам (minus273) при мен, т.е. ако сте ми контакт по jabber, очаквайте request от vasil@ludost.net.

Малко отговори на предполагаеми въпроси:
1) Защо jabber и за какво ни е изобщо?
XMPP (jabber) е в общи линии единственият отворен протокол за instant messaging и свързаните с него неща (като изключим SIP, ама там е един тих ужас). Поддържа криптография както трябва, и се поддържа от много различни услуги – например gtalk на google реално е xmpp, с което човек може да си говори и от други сървъри (някой ако иска може да погледне на jabber като една гигантска irc мрежа, в която всеки може да си пусне сървър, но не може да влияе на потребителите на останалите, само да си говори с тях). За разлика от нещата като MSN, ICQ и skype всеки може да вярва само на хора, на които реши (т.е. на мен или на някой оператор на друг jabber сървър), а не на едно-единствено entity.

2) Защо при мен?
Близо по мрежата (добре сложено в българския peering). Дистрибутирано (и да умре едната машина, другата ще продължи да работи и няма да се усети толкова сериозно проблемът). Стабилно (щото и аз самия го ползвам усилено и се старая :) ).

3) Какъв софтуер се ползва?
ejabberd в/у debian.

2010-12-02

Thursday, December 2nd, 2010

Писахме лекция/презентация по мрежова сигурност, та не ходих на ИББ.

1) Свърших текущата бутилка Lagavulin и се отвори следващата
2) отне ни около 6 часа
3) имаше паузи с тестване на разни неща на китарите и обсъждане дали утре да замъкна баса до ФМИ (един студент си носи неговата китара така или иначе)
4) за пореден път си правих в главата асоциаиции м/у струните и свиренето спрямо ползването на клавиатурата, които май изискват някакви ниво на интоксикация за разбиране.
5) открихме интересни проблеми при работата с openoffice и msoffice
6) и тримата вършихме някаква работа така между другото, докато пишехме нещата.

2010-11-26 v6sux

Saturday, November 27th, 2010

Понеже не ми стигна времето на lightning talk-а на OpenFest, ето едно по-подробно разписване на темата ми, “Защо мразим IPv6”.
Презентацията може да се свали от тук.

Ще започна със следната статистика по темата за IPv4 адресите:
Percentage of available address space announced: 62.1
Percentage of allocated address space announced: 65.4
Percentage of available address space allocated: 95.0
(weekly routing table report от 20ти ноември 2010)
Счита се, че някъде около април 2011та година IANA ще раздаде последните си останали /8 мрежи и изведнъж ще стане страшно. Това не значи, че RIR-овете нямат още достатъчно за раздаване, а и както виждате по статистиката от раздадените адреси още не всички се announce-ват, което ни дава още съвсем прилично количество време.
Дори обаче да свършат тотално за раздаване адресите, има съществуващи решения от типа на LSN (large-scale NAT) или CGN (carrier-grade NAT), две имена за почти същото, които ще помогнат да продължи растежа на мрежата, най-вече защото повечето трафик така и така е HTTP, който минава прекрасно през всякакви NAT-ове.
И, дори и да го нямаше това, пак Internet няма да спре, защото са свършили адресите, небето няма да падне, колкото и човека да се изредят да го кажат. Така че, аман от паника и натиск да се въведе нещо, което е пълно с глупости.

Разбира се, във IPv6 има и някои неща, които (може би по случайност) са хубави:
– прилично голямо адресно пространство, което позволява и да се отдели network locator-а в първите 64 бита
– премахната фрагментацията от router-ите и PMTUD е задължителна част от протокола, т.е. няма да има начин вече (малоумни) security експерти да казват “спрете всичкото ICMP”
– Няма (нужда от) NAT. Малко хора обичат NAT-а, и при подходящи stateful firewall-и спокойно ще може да се постигне същата функционалност.
– По-добра интеграция на IPSec (което трябва да се види доколко ще е полезно/работещо)

Като почнем с проблемите обаче става интересно:
– четейки документацията, човек остава с впечатлението, че са се старали (на принципа на Intercal) да направят нещата максимално различни от IPv4, точно като проява на синдрома “Not invented here”. Вместо ARP се използва ND (протокол, който работи върху ICMPv6), по подразбиране се прави stateless address autoconfiguration и по принцип в началната конфигурация на host-овете има добавен един още един елемент – router-а, който да раздава разни неща. Т.е. началния setup изглежда по следния начин:
машината тръгва
генерира си по някакъв начин 64 бита и с тях си прави link-local адрес, който през ND проверява дали е уникален, вдига го и се join-ва в multicast група
(навсякъде broadcast-а е заменен с multicast, да се чуди човек защо)
в multicast групата чува локален router пак по ND протокола (т.нар. router advertisement), който дава prefix и още няколко параметъра, вкл. дали да си говори с dhcp сървър (два бита, дали да иска адрес от него, и/или да иска и други параметри)
нататъка според двата бита решава как да си говори с dhcp сървър

Понеже dhcp-то се счита от IPv6 хората за нещо срамно, поддръжката му и работата му са бая странни и даже има разширение (още експериментално) да се раздава и DNS сървър от router-а (т.е. нека да омажем нещата колкото ни е възможно). Поради всичките тия неща на HAR миналата година открихме как най-лесно се раздават IPv6 адреси на nameserver-и чрез писането им на листи и лепенето им по разни стени.

Изобщо като цяло поне за мен го няма principle of least surprise. Би трябвало да се вземе в предвид как много хора са правили IPv4 мрежи, имат идея как работят и че принципите в тях не случайно са станали такива след прилично дебъгване и доизпипване.

– стари грешки – бяха направили задължителен т.нар. Type 0 routing header (т.е. source routing), добре, че преди около година се сетиха да го махнат. Source routing-а е прекрасен начин за реализация на tcp spoofing атаки.

– Като цяло има малко свързаност все още, особено в България – ако сте краен клиент е почти невъзможно да получите IPv6 свързаност вкъщи директно от доставчика си, не само защото те не са го подкарали навсякъде, а и защото крайните router-чета, които повечето хора ползват вкъщи просто не го поддържат. Всъщност има две причини да има IPv6 свързаност в България – едната е ентусиазма на разни хора, другата е, че в изискванията на Софийския Университет за Internet доставчик това е задължително условие и така бяха успели да накарат БТК да подкарат някаква такава свързаност.

– Липсва v6-only съдържание, с малки изключения (някои академични неща).

– IPv6 свързаността в почти всички случаи е с по-ниско качество от IPv4 – разчита се твърде много на тунели, тези тунели минават през всякакви странни места и винаги имат някакъв overhead. Всъщност, знам само за един случай, в който е валидно обраното – един доставчик, дето по една и съща тръба доставял v4 и v6 и за v6 нямало shaper-и. Като добавка, повечето router-и (особено тия, които Cisco прави) имат по-ниска производителност на IPv6 пакети.
Тази причина е основната да не виждам смисъл да подкарвам за моя проект IPv6 свързаност.

– Има и разни други неща, които слава богу (на сървърите) бяха преборени от здравия разум (например да няма PI адреси и multihoming да се прави като на всяка машина се дават по един адрес от всяка мрежа, към която сте свързани и чрез SHIM6 и черна магия машините да избират от кой адрес с кого да си комуникират, т.е. да изнесем routing-а от router-ите).

Като цяло, deployment-а на IPv6 се дължи на една сериозна група ентусиасти и на маркетингов натиск от тях и техни сподвижници. За момента нито е лесно и удобно, нито е особено смислено за повечето хора. Когато стане достатъчно лесно и удобно да се подкара и стане достатъчно нормална част от internet-а, може да се мисли по въпроса, но дотогава просто не си струва.

бележка: още съм скапан от openfest и разни други работи, така че може да не съм обяснил нещо достатъчно точно, ако имате въпроси/изяснявания, коментирайте.

2010-09-29 работен процес

Wednesday, September 29th, 2010

Наскоро Стефан Кънев писа нещо по темата “Как работя”. Идеята ми хареса, та ето как работя аз.

Като изключим буденията за спешни работи, първите неща, които правя сутрин са да погледна monitoring-а (има много хубав plugin за firefox, който дава текущите проблеми от nagios-ите, които следя) и да пипна, ако има нещо спешно (имам един folder в пощата, в който идват писмата, които биха били нещо по-важно, по принцип са малко).

Следва пиене на кафе (което правя през ден, понякога през повече) и четене на поща, агрегатор и twitter. Част от нещата се гледат диагонално, а и по принцип през нощта не се събира твърде много. Повечето mailing list-и оставям за през деня (чета основно NANOG, от доста време съм се отписал от LKML), след което гледам дали имам да правя нещо по-специално през деня. Някъде по това време си пускам и messenger-а.

По принцип имам по някоя задача за правене и останалото са неща, за които ми припомня някое събитие. Имам много странна памет и не помня всички неща, за които трябва да следя, съответно за всяко такова нещо има един от следните типове trigger-и:
1) mail от някаква автоматична система
2) IM или mail от човек по някаква тема
3) някакъв лесно видим monitoring (като nagios-а)
4) оставен отворен прозорец или терминал с нещото (за това много рядко си гася laptop-а и вече почти не го разнасям)

Почти никога не правя само едно нещо – мога да водя няколко IM разговора, докато дебъгвам или настройвам нещо, случвало ми е и да оправям две различни неща по едно и също време. Единственото нещо, което ми пречи са разговорите на живо или по телефона, понеже ми е трудно да слушам/говоря и да правя нещо друго в същото време, за това по-често не си вдигам телефона, отколкото да не отговоря по някой messenger.
(по същия начин това не го пиша на един път, а си поглеждам разни други неща на всеки няколко изречения, докато измисля с какво да продължа)

Така реално се старая да работя максимално stateless – на всяко нещо се обръща внимание, като трябва, помня основните неща (т.е. схеми, мрежи, софтуер, кое как работи), но не помня дребните оперативни неща (например трябва да се замисля и да погледна в mail-а, за да съм сигурен колко cross-connect-а се изграждат в текущия момент). Редовно ми се случва да погледна оставените screen-ове на router-а вкъщи и да открия, че се е изтеглил някакъв torrent, за който съм забравил, че съм го пускал.
(опитвал съм да ползвам какви ли не системи за целта, или да помня всичките неща, но все не ми се получава. Редовно забравям да ги ползвам)

Има и редки случаи, в които работя само по едно нещо – по принцип дебъгване на някакъв по-спешен или сложен проблем. В такива моменти мога да си изгася messenger-а (рядко, понеже трябва да комуникирам с някой през него, докато дебъгвам), да не си гледам mail-а, агрегаторите и т.н.. В тия случаи понякога си сипвам малко алкохол, помага със съсредоточаването.

Старая се да нямам спешни и много твърди срокове за свършването на каквото и да е, така че се заемам с всяко нещо, когато имам желание. Така времето, което сумарно отделям на всеки проблем е минималното нужно – вместо да се блъскам 5 часа над нещо, просто в един момент ми хрумва решение и го свършвам за 10 минути. Съответно отстрани най-вероятно изглежда, че работя много объркано и разхвърляно (което е в общи линии вярно).

Понеже така или иначе доста от работата ми включва чакане, в паузите през деня си чета mailing list-ите, “Дневник”, агрегатора ми, понякога някоя книга (винаги на монитора, за да мога да превключвам от време на време към другите неща). Правя го доста често и по принцип, така ми идват идеи какво да е следващото действие по някой проблем.

2010-08-31 два проблема

Tuesday, August 31st, 2010

И малко по работа – занимавах се с два проблема тия дни, които заслужават малко внимание.

Единия е свързан с thread-ове, сигнали и libc I/O. Ситуацията излеждаше в общи линии по следния начин – един демон с няколко thread-а, които пишат в log, който пък се re-open-ва в един signal handler. Има един lock, който се ползва за друга синхронизация, колкото да направи нещата по-весели.
Накратко изводът е “не правете така”. В signal handler нищо не трябва да се прави, освен може би да се пипне някоя глобална променлива, ползвана като семафор, иначе се получава deadlock, който е бая сложен за откриване (виждате няколко thread-а, висящи във futex() и почти нищо друго), понеже и lock-овете съвсем не са ясни (понеже са вътре в libc, а семантиката на futex е бая крива, в man-а даже си пише – това иска и малко асемблер да се ползва, предназначено е за lib-ове, не за простосмъртни).

Вторият проблем оправих преди малко и е един от най-глупавите, в които съм се набивал (и съм си причинявал сам). Имаме в общи линии следния код:

int a,b,crap;

log=fopen("/path/to/log",a);
while (!feof(log))
{
// log format: 120102121 25 1024
// timestamp seconds bytes
fscanf(log,"%d %d %d",&crap,&a,&b);
// do something
}

който в общи линии обработва един log, обръща го в sql заявки и го насипва в една база. Изведнъж започна да не свършва работа – като в началото реших, че базата се претоварва и не успява да поеме всичките (около 800 000) заявки. След половин ден тестове (и няколко други неща за оправяне, с почивки) най-накрая открих проблема – в log формата изведнъж (е, не особено изведнъж, написано беше преди месец, сега случайно беше пуснато в действие) изведнъж се появило още едно поле, което води до fscanf да не прочете нищо и същевременно feof() да не познае, че файла е свършил.

Решенията са две – или да се проверява колко точно елемента е прочел fscanf(), или да се оправи какво точно се чете. За момента е второто, поне докато не си измисля малко по-хубав начин от първия.

2010-07-31 кажете не на ip redirects

Saturday, July 31st, 2010

(някой се беше оплакал, че не пиша по работа)

Днес около рутинно оглеждане на разни графики забелязах на втория ни router в проекта (първия вече се напълни) как процесора стои на около 60%. Видя ми се адски странно, понеже другия router е далеч по-пълен, търкаля 15тина BGP сесии и един-два порядъка повече трафик и стои на 8-10%. Реших, че не трябва да стои така и седнах да дебъгвам…

Като за начало, в списъка процеси проблем нямаше, но за сметка на това повечето CPU отиваше в interrupt-ове. Отне ми малко време да го разбера, поради веселия начин, по който това се вижда в sh processes cpu, след което се зачетох как точно мога да разбера какво става. Четенето доведе до извода, че трябва да пусна един profile и да видя какво става, понеже нищо друго не звучеше подходящо.

Цялата процедура по профилирането ме върна почти във времената на DOS и на debug.com … В общи линии процедурата е се видят началния и краен адрес на main:text (т.е. самия изпълняващ се код на IOS-а), да се подадат на една команда, на която единия параметър изисква внимателно прочитане на документацията и чакане 5 минути. После по документация – спираме профилирането и казваме sh profile terse.
Аз го направих и при вида на изхода така изпсувах, че вероятно са ме чули в съседния блок.

r2#sh profile terse
PROF 8000000 BFFFFFF 2
PROFSKIP 806AA40
 0 0 0 0 2 0 0 0
PROFSKIP 806AED0
 0 0 0 0 0 0 1 0
...

(и така прилично количество екрани)

Другият вариант на изхода беше почти толкова полезен. Стигнах до извода, че ми трябва начин да направя map между тоя адрес в паметта и функцията на ios-а, която се вика (имаше на няколко места по-големи стойности), след като не намерих документация по въпроса (човек открива “show profile” командите в списъците с недокументирани IOS команди и толкова, доста възможно е да греша какво извежда). Не го намерих (логично) в show memory и реших, че така няма да стане и ми липсват няколкото месеца ровене в кода на IOS-а, за да мога в някакво нормално време да намеря проблема.

Почнах да събирам допълнително информация и се оказа, че натоварването е започнало да расте заедно с трафика. Последва сравняване на всякакви възможни параметри на двата router-а и в крайна сметка се оказа, че на интерфейса, който гледа навътре (един VLAN с много портове в него) на единия router понеже съм сложил два адреса (имах един в 10/8 за разни тестове), автоматично се слага и no ip redirects. Пробвах го на другия и магически 60% от натоварването изчезнаха.
(нямам никакъв трафик, който реално да изисква пращането на redirect-и, проверих. Да припомня, icmp redirect се праща ако router-а трябва да върне някакъв пакет през същия интерфейс, от който го е получил.)

Вероятно съм се набил в някакъв бъг я на IOS-а (12.2SRC), или на някоя от картите, които търкалят пакети и твърде много пакети се качват до layer3 частта, вместо директно да се switch-нат. Google нищо не намери по въпроса…