Eksperyment - podsumowanie

W tym wpisie znajdują się wyczekiwane przez niektórych wyniki Eksperymentu HTTP. Celem całej tej zabawy było odpowiedzenie sobie na następujące pytanie: Czy jest jakiś sposób, żeby odróżnić zapytanie o zasób osadzony na stronie od 'normalnego' zapytania? Inaczej - czy da się na przykład rozróżnić, kiedy przeglądarka pyta o obrazek osadzony za pomocą <img src=... />, a kiedy o sam obrazek, którego adres wpisany został bezpośrednio lub wywołany za pomocą linka? Czy da się odróżnić, kiedy ktoś osadza obrazek na swojej stronie, a kiedy tylko do niego linkuje? Jedyną rzeczą, która mogłaby zawierać takie informacje jest zapytanie HTTP wysyłane przez przeglądarkę do serwera. We wstępnych badaniach wykluczyliśmy możliwość użycia nagłówka Referer do rozróżnienia zapytań - co prawda Referer przy elementach osadzonych ma zwykle wartość odpowiadającą osadzającej stronie, ale taki sam nagłówek uzyskamy klikając w link znajdujący się na takiej stronie. Z pozostałych nagłówków żaden nie ma na celu informować o rodzaju zapytania. Okazuje się jednak, że takie rozpoznanie jest możliwe - trzeba podejść do sprawy statystycznie. Podejrzenia dość szybko padły na nagłówek Accept... Eksperyment, w którym w zeszłym tygodniu około 200 (+/-50) osób wzięło udział pozwolił mi zebrać trochę danych statystycznych. Obiektem zainteresowania było zapytanie HTTP wysyłane przez przeglądarkę przy próbie pobierania obrazka JPG i PNG celem osadzenia go na stronie (<img src=...) lub bezpośredniego wyświetlenia. W centrum zainteresowania znalazł się nagłówek Accept - jedyny, który okazuje się przenosić istotne dla nas informacje. Wyniki Nagłówek Accept pozwala przeglądarce określić, jakiego typu multimediów spodziewa się w odpowiedzi na swoje zapytanie. Okazuje się, że przeglądarki spodziewając się elementu do osadzenia na stronie często wysyłają w tym nagłówku inne typy, niż w przypadku obrazków pobieranych do wyświetlenia bezpośredniego. Spójrzmy na przykład na ten wykres dla przeglądarki Firefox: Wykres przedstawiający wyniki Eksperymentu dla przeglądarki Firefox. Wykres ten przedstawia szansę wyświetlenia danego wpisu w nagłówku Accept w zapytaniu o obrazek osadzony (EMBEDDED) lub do wyświetlenia bezpośredniego (LINK). Różnica w zawartości nagłówków jest wyraźnie widoczna. Wykres jest znormalizowany - przeskalowany tak, że wartość 1 odpowiada sytuacji, gdy dany nagłówek wystąpił w każdym zapytaniu danego typu. Okazuje się, że w przypadku Firefoksa rodzaj zapytania mamy jak na dłoni, wystarczy spojrzeć w nagłówek Accept! Przyglądnijmy się więc wykresom dla innych przeglądarek: Wykres przedstawiający wyniki Eksperymentu dla przeglądarki Opera. Opera nie daje nam najmniejszych szans - w każdym zapytaniu wysyła identyczny nagłówek Accept. Wykres przedstawiający wyniki Eksperymentu dla przeglądarki Internet Explorer. Internet Explorer jak zawsze sprawia dużo radości - z jednej strony odróżnienie rodzaju zapytania zdaje się być trywialnie proste, z drugiej strony IE ma dziwną tendencję zasypywania nas specyficznymi wpisami w nagłówku. Najbardziej zabawny jest image/pjpeg, który w jednym zapytaniu potrafi wystąpić dwa razy obok siebie. Nie rozumiem przyczyn tego zjawiska, ale występuje w wersjach IE od 6 do 8. Ale obiecano mi już, że zostanie to zgłoszone do Microsoftu :). Wykres przedstawiający wyniki Eksperymentu dla przeglądarki Safari. Tutaj bardzo prosto - tak samo jak w IE, zapytania osadzone mają bardzo krótki nagłówek Accept ;) Wykres przedstawiający wyniki Eksperymentu dla przeglądarki Mozilla. Ten wykres przedstawia przeglądarki przedstawiające się jako Mozilla, które nie zaklasyfikowały się nigdzie indziej. Wykres jest analogiczny do tego od Firefoksa (tak na prawdę część z przeglądarek na tym wykresie to źle rozpoznane Firefoksy - przyczyny tego zjawiska omawiam dalej). Podobała mi się w tym wszystkim Mozilla, która przedstawiła się jako "ROBOT DO WYKRADANIA KONTENTU" :) . Wykres przedstawiający wyniki Eksperymentu dla przeglądarki Chrome. Google Chrome także nie robi problemów przy rozpoznaniu typu zapytania. Wykres przedstawiający wyniki Eksperymentu dla nie sklasyfikowanych przeglądarek. W przypadku nierozpoznanych przeglądarek sprawa troszkę się zaciemnia, ale wciąż można zidentyfikować przeważające tendencje, które pozwalają rozróżnić rodzaj zapytania. Dla podsumowania, oto zapytania dla wszystkich przeglądarek na raz: Wykres przedstawiający wyniki Eksperymentu zbiorczo dla wszystkich przeglądarek. O samym Eksperymencie Wykres przedstawiający przeglądarki, które wzięły udział w Eksperymencie. Powyższy wykres przedstawia wszystkie główne rodziny przeglądarek zidentyfikowane przez skrypty (proszę nie zwracać uwagi na wartości numeryczne - odnoszą się ilości zapytań wygenerowanych przez daną przeglądarkę). Identyfikacji przeglądarek dokonywała funkcja get_browser() w PHP. Co prawda funkcja ta dość skutecznie rozdzieliła przeglądarki, jednak mimo wszystko pozostawia wiele do życzenia (mówiąc mniej formalnie - jest skopana) - nie radzi sobie z niektórymi wariacjami Firefoksa, Safari czy Chrome na systemach Apple. Dużo lepiej z deszyfrowaniem nagłówka User-Agent zdaje się radzić sobie jedna ze stron w Internecie. Serdecznie dziękuję wszystkim, którzy poświęcili swój czas i wzięli udział. Bardzo miłym akcentem było wrzucenie linku do Eksperymentu na Wykop. Ponadto dziękuję wszystkim tym, którzy zachęcali znajomych do wzięcia udziału. Pozdrawiam też użytkowników Linksa i Lynxa ;). Szczególne podziękowania dla kolegów ze Stosowanej oraz wszystkich gości z Blip'a! Zastosowania Mając możliwość rozpoznania celu zapytania o dany zasób możemy odpowiednio zareagować. Przykładowe zastosowania tej wiedzy to:
  • Lepsze sprawdzanie, czy ktoś nie hotlinkuje naszych zdjęć/obrazków - klasyczne używanie nagłówka Referer jest nieskuteczne i denerwujące dla osób korzystających z Google Images.
  • Serwowanie różnej treści zależnie od rodzaju zapytania - chyba głównie dla zabawy :)
  • Wybiórcze stosowanie przekierowań - serwowanie ramek maskujących adres w przypadku zapytania bezpośredniego oraz używanie np. przekierowania proxy w przypadku zapytań osadzonych.
Proof of concept Miał być, ale nie ma - próbując z Paszczakiem zaktualizować browsercaps.ini na serwerze coś zepsuliśmy ;). Z tego powodu na razie przykładu działania nie będzie - dość powiedzieć, że u mnie lokalnie działa :). Na podstawie zebranych danych wygenerowałem tabelkę w PHP pozwalającą napisać sobie skrypt rozpoznający rodzaj zapytania. Co dalej? Powstają coraz to nowe wersje przeglądarek, a wraz z nimi prawdopodobnie będzie zmieniać się zawartość nagłówka Accept. Można spróbować stworzyć system rozpoznawania zapytania oparty o filtr bayesowski lub wykorzystać inne metody pozwalające na bieżąco aktualizować stan wiedzy na temat używanych wartości nagłówków. Danych, które zebrałem nie było strasznie dużo, ale jeżeli ktoś chce poddać je dalszej analizie to chętnie je udostępnię :) . Edit Dla wytrwałych bajka o zdecydowanie pokręconych stringach User Agent :) Edit 2 Wykresy, o które prosił dr_bonzo: http://temporal.pr0.pl/blog/materialy/posty/eksperyment/odwrocone Czytelniej ? :)zginęły przy zmianie serwera, powinny być gdzieś w backupie.