HTTPS Миграция - IV част

Jump.BG

Сигурната връзка на уеб сайтовете вече е фактор в индексирането им от търсещите машини. Знаете ли обаче, че е възможно наличието на един конкретен проблем в индексирането на вашия уеб сайт, ако се хоства на несигурна връзка. Съществува вероятност търсещата машина да индексира вашия уеб сайт и със сигурна връзка, но със съдържание от друг сайт от същия сървър, на който се намира и вашият. Въможно е дори SSL-ът да се окаже на трети сайт от същия сървър и въпреки невалидния сертификат търсачката да индексира съдържанието. Това са рядко срещани ситуации, но напълно възможни и затова днес решихме да обасним в кои случаи се стига до такива странности, като започнем с HTTP протокола и после ще добавим TLS за да стане HTTPS. Ако техническото обяснение не ви се чете, можете да прескочите накрая където сме дали рецепти за справяне със проблема.

История на HTTP протокола

Развитието на протокола за пренос на хипертекст (Hypertext Transfer Protocol - HTTP) е инициирано през 1989 година от Тим Бърнърс-Лий, английски физик и компютърен специалист, основоположник и създател на World Wide Web. Революционната идея претърпява много метаморфози и в крайна сметка първата документирана версия е HTTP V0.9 през 1991 година. Можете да видите цялата спефицикация тук. Ако трябва обаче да я сравним с текущата версия 2.0, можем да кажем, че е пълна с дефекти. По онова време започна първото мащабно експлоатиране на уеб, създаване на сайтове, браузъри, редактори и редица инструменти за уеб. Едновременно с развитието се видя и първият по-голям проблем на тогаващната версия HTTP – липсата на възможност за хостване на повече сайтове на един сървър. Никой не предполагаше по това време, че един сървър може да обработва стотици, дори хиляди уеб сайтове едновременно. Това от своя страна спъваше цялостното развитие на индустрията за известен период от време, защото, както знаете, интернет адресите версия 4 са ограничени.

Работата по стандартизирнето на следващата версия HTTP V1.0 започва през 1995 година и излиза официално през месец май 1996. Версията може да бъде открита като RFC 1945. HTTP V1.0 включваше много нововъведения – заявки GET/POST, отговори 200 OK, 404 Not Found, параметри Server, User Agent и още много, които днес ги приемаме за даденост. Въпросната версия обаче не реши проблема с обслужването на много сайтове от един сървър. В края на 1995 г. започна работа по стандартизирането на версия 1.1 наричан тогава HTTP-NG. Цялата спецификация може да откриете, като RFC 2068. Въпреки че спефицикацията на версия 1.1 излезе през януари 1997 г., всички вече го поддържаха и предпочитаха нея пред версия 1.0, а причината беше, че версия 1.1 донесе дългоочакваната възможност за много сайтове под един сървър. Това се случи с добавянето на параметъра “host” към самата заявка. Така сървърът при получаването на заявката може да я обработи и да прехвърли потребителя към правилния сайт.

Сега ще ви покажем как различните версии са предавали данни. Първите един - два реда представляват заявката, предавана от клиента към сървъра. След това е отговорът от сървъра.

Пример HTTP 0.9:

GET /index.html

<html><body>Hello World!</body></html>

Пример HTTP 1.0:

GET /index.html HTTP/1.0

HTTP/1.0 200 OK

<html><body>Hello World!</body></html>

Пример HTTP 1.1:

GET /index.html HTTP/1.1

Host: www.jump.bg

HTTP/1.1 200 OK

<html><body>Hello World!</body></html>

Защо параметърът HOST е толкова важен?

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

GET /index.html HTTP/1.1

Host: www.jump.bg

Това е минималната заявка, която браузърите могат да изпратят към сървър, тя да бъде обработена без грешка и резултатът да бъде върнат към клиента.

Как се обработва това на сървърите?

Уеб сървърите имат секция за всеки един уеб сайт, който обслужват. Има обаче един сайт, който е по-важен от останалите, защото е “сайт по подразбиране” (default site). Ролята на този сайт е следната: когато към сървъра се подаде заявка към несъществуващ сайт, тя се препредава към сайта по подразбиране и се обработва от него. Така всяка една заявка може да бъде обработена от сървъра и някакъв резултат да бъде върнат към клиента. В идеалния случай всеки сървър има такава страница, която да показва, че има някакъв проблем със заявка и не може да бъде обслужена. Със сигурност сте виждали такава страница, когато сървърите не са опреснени.

primer-sajt-po-podrazbirane

Ето как и вие можете да зададете нещо подобно:

curl -vvvv --header 'Host: jump.bg' tester.jump.bg

По този начин ще се свържете с tester.jump.bg, но ще подадете в заявката изрично, че искате да работите със сайта jump.bg, което ще покаже текущия сайт по подразбиране на този сървър.

Всичко това работеше сравнително добре до появата на сървърите с възможност за сигурна връзка. Всички версии на протоколите за сигурни връзки - SSL и TLS, нямат възможност за указване на сайта при указване на сигурна връзка. Това доведе до проблеми, подобни на описаните по-горе, а именно “един сървър – един сайт със сигурна връзка”. Така на един сървър можеше да се обработват неограничено количество сайтове с несигурна връзка и само един единствен сайт със сигурна връзка. Тази ситуация се оказа проблем за развитието на индустрията, защото както по-горе написахме броят на на адресите е краен и фиксиран - максималният брой е 4 милиарда, 97 милиона, 152 хиляди и 81 сайта (253*253*253*253). Това е възможно най-оптимистичната стойност, която никога не може да бъде достигната – голяма част от адресите са резервирани за фирми, държавни или академични институции, военни нужди, интернет доставчици, а това срива броя на сайтовете до милиони.

Защо беше създаден SNI?

Както по-горе видяхте, параметърът Host към всяка една заявка позволява на сървъра да прецени към кой сайт да я предаде за изпълняване. Когато обаче се създава сигурна връзка, (без SNI - Server Name Indication) преди не беше възможно да се подаде към кой сайт да се предаде, за да се изпълни. В действителност заявката имаше Host параметър, но той не достигаше до сайта, за който е предназначен. Още по време на процеса за установяване на сигурна връзка, сървърът трябва да знае към кой уеб сайт да предаде заявката, но сайтът се подава с прословутия Host параметър след създаването на сигурната връзка. По този начин се стигна до “Параграф 22”. Решението на този проблем е в създаването на разширение на TLS протокола за сигурни връзки – SNI. Той беше описан за първи път в RFC 3546 и финалната му версия е RFC 6066. По същество това разширение прави същото, както Host параметърът за HTTP протокола. Още по време на процеса на създаване на сигурна връзка се указва в един параметър към кой сайт ще бъде извършена заявката. По този начин, когато клиентът и сървърът поддържат това разширение (SNI), те могат да се договорят по време на установяването на връзката за сайта преди и един бит да бъде обменен повече установената сигурна връзка.

Пример – TLS връзка без SNI:

openssl s_client -connect tester.jump.bg:443

Пример – TLS връзка със SNI:

openssl s_client -connect tester.jump.bg:443 -servername tester.jump.bg

Важно! SNI е разширение на TLS и не е задължително за създаване на връзка. Можете да създадете връзка и през TLS 1.2 (последната одобрена версия) и да не използвате SNI. Можете да създадете връзка и през TLS 1.0 (първата налична версия) и да използвате SNI. Необходимо е единствено да знаете, че и клиентът, и сървърът трябва едновременно да поддържат това разширение, за да се възползвате от него. Всички сървъри и клиенти излязли през последните 10 години го поддържат. Сред най-значимите пропуски от клиентска страна са Android 2.X и Internet Explorer 6.0, 7.0 и 8.0 под Windows XP.

Откакто търсещите машини обаче започнаха да предпочитат сайтове със сигурна връзка настана пълен хаос.

Защо се получава хаос при сайтовете със сигурни връзки?

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

Хаосът е много лесно отстраним с няколко начина при хостинг доставчиците:

  • Липса на сайтове със сигурна връзка – това е прекалено идеалистичен пример, който не може да бъде осъществен. Наличието на дори един сайт със сигурна връзка на сървъра води до използването му от останалите (без сигурна връзка), когато бъде поискана сигурна връзка
  • Използване само на сайтове със сигурна връзка – отново идеалистичен пример, който не може да бъде осъществен. Всички сертификати, издавани от институции са платени, а това беше една спънка за изпълняването. Сега с инициативата LetsEncrypt вече има и безплатни сертификати. Възможно е да се използват и самоподписани сертификати, ако сайтът не разполага с такъв. Някои доставчици стигат по-далече, като инсталират сертификат LetsEncrypt още от момента на създаването на сайт на сървъра. Ако клиентът пожелае, може да инсталира друг сертификат от друг доставчик във всеки един момент.
  • Хибриден тип - използване на самоподписан сертификат за всеки сайт, който няма инсталиран сертификат и показване на страница за грешка при зареждане на сайт без сигурна връзка. Така сайтът ще работи по несигурна връзка и ако бъде изискана сигурна такава, ще се визуализира горепосочената страница.

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

Ако сайтът няма нужда от сигурна връзка по една или друга причина, то ще се наложи и дописването на някой от следните редове във .htaccess за редирект от HTTPS към HTTP:

RewriteEngine On

RewriteCond %{HTTPS} on

RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Или:

RewriteEngine On

RewriteCond %{SERVER_PORT} 443

RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Или:

RewriteCond %{HTTP:X-Forwarded-Proto} =https

RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Всички тези команди имат една и съща функция – реализират пренасочване 301 от всяка една заявка от HTTPS към HTTP за същия сървър и адрес. Остана само да се инсталира един самоподписан сертификат или да използвате LetsEncrypt и вече няма да се безпокоите, че на ваш сайт ще бъде заредено съдържанието на друг.

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

 

HTTPS Миграция – I част

HTTPS Миграция – II част

HTTPS миграция – III част

Статия от Jump.BG

Статии, новини и събития, публикувани от екипа на Jump.BG.

Социални мрежи:
Още статии от автора

Абонирайте се за нашия бюлетин

С абонамента си получаваш повече актуални новини и нашите специални промо оферти

Абонирайте се за нашия бюлетин