В различного рода работе (партнерки, лендинги и т.п.) нередко возникает вопрос - как переадресовать пользователя на другую веб-страницу, при этом чтобы его браузер не передавал HTTP Referer. В Интернете существует множество сервисов, которые просто заменяют Referer на свой собственный адрес, но это тоже не всегда желаемо. Так как же получить пустой Referer?
Есть один самый надежный путь:
1. Переадресовываем пользователя на HTTPS-адрес.
2. Далее, если целевой адрес HTTP, то переадресовываем туда.
3. Иначе, переадресовываем на наш HTTP-адрес, а оттуда уже на целевой.
Эта схема гарантированно очистит Referer, однако, она достаточно муторная и иногда требует нескольких редиректов.
Если же у вас нет возможности организовывать такую схему, или вы просто не хотите слишком париться на этот счет, или даже просто интересуетесь, какие есть еще способы, то эта заметка для вас. Я расскажу, как получить максимально кроссбраузерное решение, которое переадресует пользователя на целевую страницу с пустым реферером.
Разумеется, совершить редирект, отослав браузеру заголовок (с кодом 301 или 302, например) не получится, так как браузер в этом случае удержит реферер, но не обнулит его, и даже не изменит. Придется делать решение, совмещающее в себе различные подходы. Итак, сначала я приведу код, а потом - пояснения по нему.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
<?php //Ваша ссылка, на которую осуществляется редирект $target_link = 'http://google.com'; if(!isset($_SERVER['HTTP_REFERER'])) { //Если нам никто реферер не передал, то достаточно //просто совершить 301 редирект - браузер при этом реферера навешивать //не будет //Неплохо бы еще проверить, если у нас редирект с HTTPS на HTTP, то также //осуществляем 301 редирект через header(), так как браузер //в таком случае не передаст реферер, но эту простую задачку //я оставлю вам. header('Referrer-Policy: no-referrer'); //По поводу этого хедера - ниже. header('Location: ' . $target_link, true, 301); exit(); } //А иначе всё не так просто $target_link = htmlspecialchars($target_link); //Будем делать редирект через тег <meta>. //Это срабатывает в Firefox и IE, однако, в других браузерах не работает. //В то же время, браузеры на движке WebKit //(Safari, Chrome, новая Opera) поддерживают //атрибут rel="noreferrer" у тегов <a> $is_webkit = isset($_SERVER['HTTP_USER_AGENT']) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'webkit') !== false; if($is_webkit) { //Ставим таймаут редиректа через тег <meta> в 3 секунды //(на тот случай, если в браузере выключен JavaScript). //Это, конечно, не удалит реферера, зато заменит его //на URL этого скрипта и переадресует пользователя //на целевую страницу. $meta_timeout = 3; //Пробуем осуществить редирект с помощью JavaScript. //(Это очищает Referer). $onload = 'onload="redirect();"'; } else { //Firefox и IE и так не шлют реферер при редиректе через //тег <meta>, поэтому нам не нужны извращения через JavaScript. $meta_timeout = 0; $onload = ''; } echo <<<HERE <!doctype html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="cache-control" content="max-age=0" /> <meta http-equiv="cache-control" content="no-cache" /> <meta http-equiv="expires" content="0" /> <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" /> <meta http-equiv="pragma" content="no-cache" /> <meta http-equiv="refresh" content="$meta_timeout;url=$target_link"> <title></title> <script type="text/javascript"> <!-- var redirect = function() { document.getElementById("link").click(); } --> </script> </head> <body $onload> <a href="$target_link" rel="noreferrer" id="link"></a> </body> </html> HERE; |
Много комментариев дано прямо в коде, но я поясню поподробнее. В скрипте скомбинировано два разных подхода к переадресации в зависимости от браузера:
1. META-редирект. Хорошо работает в Firefox и IE, очищая поле Referer.
2. Редирект через JavaScript методом программного клика по ссылке с атрибутом rel="nofollow". Это работает в последних версиях браузеров, основанных на движке WebKit (Chrome, Safari, новая Opera). На случай, если JavaScript отключен, через 3 секунды будет осуществлен META-редирект. Это не очистит поле Referer в перечисленных браузерах, но, как минимум, заменит его и в любом случае осуществит переадресацию.
Вот и все пояснения по этому решению. Надеюсь, кому-то будет полезно.
Обновление от октября 2017 года: в этом году появился новый серверный заголовок, который позволяет выключить передачу реферера даже при редиректе с HTTP-ресурса на другой HTTP-ресурс, либо при редиректе с HTTPS на HTTPS. Это Referrer-Policy, который, впрочем, пока что поддерживается малым количеством браузеров. Однако, для профилактики можно отсылать этот хедер из PHP-скрипта перед отсылкой заголовка Location
. Я добавил его отправку в скрипт-пример, который опубликован выше по тексту.
Очень интересная статья, вообще ваш сайт один не из многих где есть полезная информация и в понятном виде для любого читателя, жаль что только редко пополняется сайт статьями.
Ещё такой вопрос, может вы могли-бы написать статью с примерами уникальной многофункциональной клоаке.
С Функциями: фильтрация поисковых ботов по списку IP адресов, определения ботов в реальном времени, возможность фильтровать по юзер-агенту.
С Ув. Алекс.
Спасибо за рабочую информацию!
Только вот..., а можно как нибудь изменить referer?
Изменить реферер на произвольный - сомнительно. Если только использовать какие-то уязвимости браузеров (но такие сложно обнаружить, да и не стоит оно того).
А как сделать, чтобы перебрасывая через редирект, передать через него 1 или несколько нужных мне GET параметров?
Пример:
Пользователи с рекламной площадки(условно назовем его сайт http://САЙТ1.ru/ переходит по ссылке вида http://САЙТ2.ru/?param1=643213¶m2=sj2823¶m3=546_sq87 (значения param1, param2 и param3 для каждого пользователя задаются динамически)
Мне нужно что бы редирект, размещенный на http://САЙТ2.ru/ переадресовывал пользователя на конечный сайт партнерки (http://САЙТ3.ru/), при этом "на ходу" подставлял в конец ссылки текущие значения GET. Т.е. пользователь уходил по ссылке вида:
http://САЙТ3.ru/?SubID=%5Bparam3%5D&refIP=%5Bparam1%5D
Взять и немного дописать предложенный скрипт, чтобы пробрасывал нужные параметры
Чем плохо повесить такую функцию на onclick?
w = window.open();
w.document.write('');
w.document.close();
return false;
Упс, подъелось.
Вот код -- pastebin.com/77CKyYct
а как поменять рефер?
Без использования каких-либо уязвимостей браузеров, скорее всего, никак.
Спасибо за ред с коммами внутри.
А если вставить ред в ссылку на которую осуществляется редирект типа
$target_link = 'http://anonimus.to?ссылка';
По сути реферер должен быть anonimus.to!?
Не уверен, нужно проверять. Думаю, может зависеть еще от того, как этот anonymous.to редиректит.
С https не совсем ясно. Можно просто использовать header Location php? И как он работает? Например при переходе на мой https сайт, а потом с моего куда либо, какой будет реферер? Разве с помощью php поменяется реферер?
Фишка в том, что при переходе с HTTPS-сайта на HTTP реферер должен очищаться по стандарту: A user agent MUST NOT send a Referer header field in an unsecured HTTP request if the referring page was received with a secure protocol. (https://tools.ietf.org/html/rfc7231#section-5.5.2)
Очень ценная инфа!
Но что то не получается умну реализовать http -> https -> http, реферер не стирается :(
dx, подскажи пжлст, какой именно редирект должен быть на промежуточном сайте с https
Пробовал php редирект, через htaccess, но не получается, реферер остается прежним :( вторые сутки сижу с этой проблемой. Сертификат установлен корректно.
При редиректе с HTTPS на HTTP браузер должен по требованиям RFC не передавать реферер. Это указано вот здесь: https://tools.ietf.org/html/rfc7231#section-5.5.2 : A user agent MUST NOT send a Referer header field in an unsecured HTTP request if the referring page was received with a secure protocol. Если все сделано правильно, то реферер с HTTPS на HTTP-сайт передаваться не должен. Советую попробовать в другом браузере, возможно, это проблема конкретного браузера.
dx, поделитесь пжлст Вашим кодом редиректа. Думаю, что то я не правильно делаю с этим редиректом...(
Так в статье же код выложен. Я ничего нового с тех пор не придумывал. Редирект нужно делать отправкой заголовка Location от веб-сервера.
Вот я написал код:
Залил на https://kaimi.io/, перешел по адресу, реферера нет.
Сейчас нашел еще появившийся недавно заголовок Referrer-Policy, который позволяет осуществить редирект без реферера даже на http-сайт. Вот полный пример:
Первая ссылка будет редиректить на google с передачей реферера, а вторая и третья - без. Нужно учесть, что хедер Referrer-policy поддерживают далеко не все браузеры (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#Browser_compatibility), поэтому пока что редирект с HTTPS на HTTP остается самым надежным вариантом.
пробовал на разных браузерах
Если перейти по ссылке расположенной на сайте https на сайт с http, реферер будет пустой, этто да. Но при редиректе, когда ссылка стоит на сайте с http, с нее переход на сайт с https, оттуда редирект header('Location: на сайт http, реферер сохраняется ведь :(
Действительно, Firefox, например, в таком сценарии реферер передает. Нужно в таком случае комбинировать методы. Например, по HTTPS-адресу размещаем такую страницу:
При переходе на такую страницу с HTTP сайта нас перекинет на http://google.com, при этом Firefox и IE реферер сбросят. Я это даже проверил. Для других браузеров можно применить технику с тегом
<A>
, у которого выставлен атрибутrel="noreferrer"
, как описано в статье. Думаю, тоже должно сработать.В реферерах такое появилось android-app://org.telegram.messenger
Не убрать?
Попробуй через https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer
А есть ли какая-то возможность сделать
$target_link = 'http://google.com';
Так, чтобы можно было указать 2 сайта = http://google.com и http://yahoo.com , и чтобы редиректило случайным выбором.
Для Chrome и Firefox можно уже вообще не заморачиваться и использовать штатный заголовок Referrer-Policy (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy)
Есть возможность, нужно написать
$target_link = array_rand(['http://google.com', 'http://yahoo.com']);