Потихоньку видяшки из моих мультосайтов начали гулять по инету… Простая защита от дурака, предоставляемая флеш-плеером uppod.ru, отсеивала большинство школьников, а против мало-мальски подготовленного кулхацкера, конечно, не спасла. Ведь на уровне заголовков все обращения к файлам сервера видны как на ладони, и ничто не мешает стырить прямой линк на файл. Пришлось лазить по разным сайтам и собирать инфу по защите моих файлов от хотлинкинга (эт када пиздят линки, ага).

Буквально за минуту я наткнулся на простое решение, связка nginx+простой_скрипт_на_php. Суть в том, что в ссылку на файл добавлялся хэш ИПа клиента + некий пароль, при обращении к nginx клиент редиректился на пхп-скрипт, который проверял ИП клиента и пароль, и в случае когда ИП и пароль совпадал, редиректил запрос обратно nginx’у, который выдавал файл на скачку. В случае, когда либо ИП не подходил (это когда юзер получил ссылку и пытается ее открыть на машине с другим ИПом ), либо пароль (а это когда уже кто-то прямо пытается подобрать пароль к расшифровке..), в этих случаях в конфиге nginx’а можно задать действие — либо нах слать (403, 404), либо подсовывать заглушку (fuck_you.flv).

На такой вариант я наткнулся тут, и наверняка бы сделал его, будь у меня на серверах PHP :) Дело в том, что все видяшки у меня лежат на разных серверах, на которых крутится только правильно настроенный nginx. И ставить туда PHP ради одного маленького скриптика мне не хотелось, и я продолжил поиски.

Спустя еще минут 10 поковыряв архивы конференций по nginx, а также блоги, вылезевшие из серпа по запросу «Защита видеоконтента», я обнаружил, что в самом nginx’е есть нативный модуль, который позволяет делать все тоже самое! И даже больше, чем пример с ПХПой :) Называется он Http_Secure_Link_Module. Он позволяет во1, генерировать для каждого IP уникальную ссылку, во2, задавать пароль, предотвращающий создание базы из ссылок для всех возможных IP-адресов, и в3х, задавать время жизни такой ссылки. Все эти плюшки доступны для nginx версии с 0.8.50, и, как говорится в документации, этот модуль по дефолту не ставится вместе с nginx, так что надо его дополнительно указать при сборке. Тем не менее, у меня nginx установился вместе с этим модулем (видимо, подцепился собственный репозитарий хостера, где своя сборка nginx). Чтобы посмотреть, есть ли у вас этот модуль, надо набрать:

nginx -V

В документации все расписано, но для наглядности я покажу что получилось у меня. В директиве server файла nginx.conf (конечно, все кастомные названия изменены):

    location /video/ {
        rewrite /video/([a-zA-Z0-9_\-]*)/([0-9]*)/(.*)\.flv$ /realvideo/$3.flv?secl=$1&sect=$2;
    }
    location /realvideo/ {
        secure_link $arg_secl,$arg_sect;
        secure_link_md5 mysecretword$uri$arg_sect$remote_addr;
        if ($secure_link = "") { return 403; }
        if ($secure_link = "0") { return 404; }
        rewrite ^/realvideo/(.*)$ /realvideo/$1 break;
        root /var/www/;
        flv;
    }
}

Первый локейшн просто переписывает ссылки вида:

http://site.ru/video/98gh12b9v7g112su6755f/198267424/mult.flv 

на:

http://site.ru/realvideo/mult.flv?secl=98gh12b9v7g112su6755f&sect=198267424 

Вся магия происходит во втором локейшене, директиве secure_link мы указываем наш хэш (secl) и время жизни ссылки (sect), которые были заданы клиентом при загрузки страницы (код см.ниже). Директива secure_link_md5 вычисляет хэш и сверяет время уже на стороне сервера. И если все гуд, то переменной $secure_link присваивается значение 1 и выдается нужная видяшка. Если скажем время вышло, тогда $secure_link=0 и клиенту возвращается 404 ошибка. Если хэш неправильный — возвращается 403 ошибка.

А вот как генерируются ссылки вида, который я упомянул чуть выше (http://site.ru/video/98gh12b9v7g112su6755f/198267424/mult.flv ):

$name = "mult.flv";
$secret = 'mysecretword';
$time = time() + 10800; //ссылка будет рабочей три часа
$key = str_replace("=", "", strtr(base64_encode(md5($secret.'/realvideo/'.$name.$time.getenv("REMOTE_ADDR"), TRUE)), "+/", "-_"));
$encoded_url = "http://site.ru/video/$key/$time/$name";

Тут кодируется урл, секретное слово, время жизни ссылки, и IP. Вроде должно быть понятно.

Думая, что вот оно щастье, я зафигачил это все дело у себя. И оно нифига не заработало :) Дело в том, что вышеприведенным PHP-кодом ссылки надо кодировать непосредственно перед выводом их посетителю. А я их кодировал прямо в БД, тем самым прописав свой IP во все ссылки :) Так что пришлось в БД оставить прямые ссылки и сделать небольшой плагин для WordPress, который содержит вышеприведенный код и перехватывает вывод содержания поста, меняет прямую линку на кодированную. А потом уже выдает это все посетителю.

Проверка работоспособности защиты:
1) попробовать с разных IP запустить видяшки (должны проигрываться)
2) отловить перехватчиком заголовков урлы, по которым обращается браузер для запуска видяхи и попробовать открыть их в системе с другим IP (должна 403 ошибка показываца)
3) открыть этот урл на этом же компе спустя 3 часа после его получения (должна 404 ошибка показываца).

Ура, я прошел проверки! :)