Version: 5.3 (switch to 5.4b)
Using the Chain of Trust system in the Web Player
Решение проблем при использовании веб-плеера

Песочница (безопасность) вебплеера.

Веб плеер в Unity 3.0 реализует модель безопасности очень похожую на используемую в Adobe Flash player™. Эти ограничения безопасности применяются только к веб плееру и редактору (если в bild settings текущей платформой является WebPlayer). Модель безопасности разбита на несколько частей:

  • Ограничения на доступ к данным на домене, отличном от домена вашего .unity3d файла.
  • Ограничения на использование сокетов.
  • Запрет вызова любого метода считается недоступным (например, File.Delete).
  • Запрет на использование System.Reflection.* для вызова приватных/внутренних методов в классах, которые написаны не вами.

В настоящий момент только первые две части модели безопасности эмулируются в редакторе.

Встроенный в Unity функционал мультиплеера (классы UnityEngine.Network, UnityEngine.NetworkView и т.п.) не влияют на модель безопасности.

Этот документ описывает то, как убедится что ваш контент продолжает работать с версией 3.0 веб плеера Unity.

WWW класс и сокеты используют схожую схему, но совершенно разные системы. WWW только определяет права доступа на веб сервис, где политика состоялась, но сокеты применяются ко всем TCP/UDP соединениям.

Unity поставляется с “Эмуляцией Web Security”, что полагает модель безопасности веб плеера. Это облегчает обнаружение проблем в редакторе. Подробные настройки в Edit->Project Settings->Editor. Также см. Editor settings.

Смысл использования WWW класса

Веб плеер Unity ожидает http файл сервера политики под названием crossdomain.xml, чтобы быть доступным на домене, к которому вы пытаетесь получить доступ с WWW классом (хотя это не потребуется, если домен тот же, на котором размещен unity3d файл)

Например, представьте тетрис, размещенный по следующему адресу:

http://gamecompany.com/games/tetris.unity3d

нужно получить доступ к листу highscore, размещенному по адресу:

http://highscoreprovider.net/gethighscore.php

В этом случае вам нужно разместить crossdomain.xml файл в корень highscoreprovider.net, вот так например: http://highscoreprovider.net/crossdomain.xml

Содержимое из файла crossdomain.xml имеет формат используемый Flash плеером. Очень вероятно что вы обнаружите файл crossdomain.xml уже на месте. Установки файла выглядят примерно так:

<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>


Когда этот файл размещен в http://highscoreprovider.net/crossdomain.xml, владелец домена объявляет что контент вебсервера может быть доступен любому вебплееру, пришедшему из любого домена.

Веб плеер Unity не поддерживает <allow-http-request-headers-from domain> и <site-control permitted-cross-domain-policies> теги. Обратите внимание, что crossdomain.xml должен быть ASCII файлом.

Отладка

Установка переменной окружения ENABLE_CROSSDOMAIN_LOGGING в 1, позволит контролировать сообщения, сгенерированные в рантайме и декодировать файл crossdomain.xml. На Mac вы можете установить глобальные переменные окружения в /etc/launchd.conf. На PC используйте Control Panel->System And Security->System->Advanced system settings->Environment Variables…

Пример выхода с этой переменной окружения, когда веб плеер пытается получить изображение с удаленного сервера:

Determining crossdomain.xml location for request: http://www.remoteserver.com/image.jpg
About to parse url: http://www.remoteserver.com/image.jpg
Determining crossdomain.xml location for request: http://www.remoteserver.com/image.jpg
About to parse url: http://www.remoteserver.com/crossdomain.xml
About to parse url: http://www.remoteserver.com/image.jpg
Determining crossdomain.xml location for request: http://www.remoteserver.com/image.jpg
Download had OK statuscode
Received the following crossdomain.xml
--------------------------------------
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
----------------------
received policy
Parsing: cross-domain-policy
cross-domain-policy
Parsing: allow-access-from
allow-access-from
  domain: *
done parsing policy
crossdomain.xml was succesfully parsed
About to parse url: http://www.remoteserver.com/image.jpg
Checking if http://www.remoteserver.com/image.jpg is a valid domain
Checking request-host: www.remoteserver.com against valid domain: *
All requirements met, the request is approved


Во время работы редактора, сообщения записываются в Editor.log. Попытка прочитать crossdomain.xml, некорректно сохраненный как utf16, с BOM, выдаст ошибку парсинга xml:

BuildFlashPolicy caught an exception while parsing http://www.remoteserver.com/crossdomain.xml: Expected element


Это потому что BOM не ожидается. Использование не поддерживаемого utf16 файла без BOM вернет:

BuildFlashPolicy caught an exception while parsing http://www.remoteserver.com/crossdomain.xml: Policy can't be constructed from empty stream.


Это потому что первый байт в этом файле нуль и парсер думает что он достиг конца файла. Crossdomain.xml должен быть ASCII файлом.

Последствия использования Сокетов:

Для подключения к конкретному хосту, веб плееру Unity необходима сокет политика. Это политика по умолчанию присваивается целевому хосту порта 843, но она может быть назначена и другим портам. Единственное различие - то что его нужно назначить вручную Security.PrefetchSocketPolicy(). Если вызываемое API размещено на порту выше 1024, политика может получить доступ только к таким портам.

Когда используется порт по умолчанию, это работает примерно так: веб плеер Unity пытается установить TCP сокет соединение к хосту, он сначала проверяет что хост-сервер будет проверять соединение. Он делает это путем открытия сокета TCP на порт 843, выдает запрос и ожидает получить политику сокета над новым соединением. Затем веб плеер Unity проверяет, позволяет ли политика сокета идти дальше, нет ли ошибок. Этот процесс происходит незаметно для пользовательского кода, который не нужно изменять для использования этой модели безопасности. Например, политика сокета может выглядеть примерно так:

<?xml version="1.0"?>
<cross-domain-policy>
   <allow-access-from domain="*" to-ports="1200-1220"/> 
</cross-domain-policy>"


Эта политика эффективно говорит: “Контент под любым доменом может свободно сделать сокет соединения в хостах 1200–1220”. Веб плеер Unity будет соблюдать это и отклонять любые попытки сокет соединения, используемые порт вне этого диапазона (будет выброшено исключение SecurityException).

Когда используется UDP соединения, политика может быть автоматически получена таким же образом, как и при TCP. Разница лишь в том, что при TCP автоматическое получение происходит когда вы подключаетесь к чему то (гарантирует вам разрешение подключатся к серверу), а при UDP, т.к. нет установления соединения, это случается когда вы вызываете метод любого API, который отправляет или получает данные (гарантирует разрешение отправлять/принимать траффик в сервер и из сервера).

Формат, используемый для политики сокетов такой же, как и у Flash плеера, кроме некоторых не поддерживаемых тегов. Веб плеер Unity поддерживает “*” как валидное значение для настроек домена и настройки “to-ports” являются обязательными.

<?xml version="1.0" encoding="ISO-8859-1"?>

<!ELEMENT cross-domain-policy (allow-access-from*)>

<!ELEMENT allow-access-from EMPTY>
<!ATTLIST allow-access-from domain CDATA #REQUIRED>
<!ATTLIST allow-access-from to-ports CDATA #REQUIRED>


Политика сокетов, применяемая и к TCP и к UDP соединениям, может контролироваться одним сервером.

Для вашего удобства мы предоставляем небольшую программу, которая просто прослушивает порт 843. Во время соединения она получает строку запроса и будет отвечать только с валидным файлом политики сокета. Код сервера находится в корневой папке Unity, в Data/Tools/SocketPolicyServer на Windows или /Unity.app/Contents/Tools/SocketPolicyServer на OS X. Следует заметить, что предварительно настроенный, он может быть запущен на Mac, т.к. у него среда Mono. Для запуска просто введите “mono sockpol.exe”. Этот пример кода показывает корректное поведение сервера политики сокета. В частности, сервер ожидает получить заканчивающуюся нулем строку, содержащую <policy-file-request/>. При получении этой строки, он отсылает клиенту сокет политики xml документ. Кроме того, требуется запись в сокет заголовка и тела xml. Разделение операций записи в сокет заголовка и тела может быть причиной исключений безопасности, всвязи с получением Unity неполной политики. Если у вас возникли проблемы со своим собственным сервером, используйте данный пример. Он позволит вам определить, в чем именно проблема.

Треть сетевых библиотек, используемых для многопользовательских игр, должна быть способна работать с этими требованиями до тех пор, пока они не зависят от функционала peer 2 peer (см. ниже), но использовать выделенные серверы. Они даже иногда приходят из коробки с поддержкой хостинг политики.

Примечание: Несмотря на то, что crossdomain.xml и файлы политики сокетов являются xml документами и вообщем аналогичны, их назначения очень разные. Crossdomain.xml (применяемый для http запросов) выбирается в порту 80, где как для политики сокетов извлекается из порта 843 используя тривиальный сервер, что реализует <policy-file-request/>. Вы не можете использовать http сервер для выдачи файла политики сокетов, ни настроить сервер что просто посылает файл политики сокетов в ответ на сокет соединение порта 843. Отметим также, что каждый подключаемый сервер требует собственный сервер политики сокетов.

Отладка

Можете использовать telnet для подключения к серверу политики сокетов. Пример приведен ниже:

host$ telnet localhost 843
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
<policy-file-request/>
<?xml version='1.0'?>
<cross-domain-policy>
        <allow-access-from domain="*" to-ports="*" />
</cross-domain-policy>Connection closed by foreign host.
host$

В этом примере, telnet используется для соединения к локальному хосту на порту 843. Telnet отвечает с тремя линиями и ожидает от пользователя ввода данных. Пользователь вводит строку запрос политики <policy-file-request/>, которую сокет сервер политики получает и отвечает с политикой сокета. Затем сервер разрывает соединение, сообщая telnet что соединение было закрыто.

Слушающие сокеты

Вы не можете создавать слушающие сокеты в веб плеере, в таком случае не будет работать сервер. Поэтому веб плеер не может контактировать с каждым направлением (peer 2 peer). При использовании TCP сокетов, вы можете подключится к удаленным точкам только при условии что сокет политика системы позволяет это сделать. Для UDP это работает также, только концепт немного отличается, т.к. это протокол без установления соединения, вы не можете подключится/прослушивать и отправлять/принимать пакеты. Вы можете принимать пакеты только с сервера если он ответил с валидной политикой с позволяющим доступ с домена тегом.

Это все так раздражает, так почему же эти вещи существуют?

Сокеты и функции безопасности WWW существуют для защиты людей, установивших Unity Web Player. Без этих ограничений могут быть возможны подобные атаки:

  • Боб работает в белом доме.
  • Френк - злодей. Он пишет на unity веб игру, которая незаметно делает WWW запрос к http://internal.whitehouse.gov/LocationOfNuclearBombs.pdf. internal.whitehouse.gov - это сервер, который недоступен из интернета, но доступен для личного компьютера Боба, потому что тот работает в белом доме.
  • Френк отправляет те байты в http://frank.com/secretDataUploader.php
  • Френк размещает эту игру на http://www.frank.com/coolgame.unity3d
  • Френк убеждает Боба поиграть в игру.
  • Боб играет в игру.
  • Игра незаметно скачивает секретные документы и отправляет их Френку.

Благодаря WWW и сокет безопасности, эта атака провалится, потому что перед скачиванием pdf файла, unity проверит http://internal.whitehouse.gov/crossdomain.xml и спросит сервер “данные, хранящиеся на вашем сервере доступны для публичного использования?”. Размещение crossdomain.xml на вебсервере можно считать ответом на этот вопрос. В этом примере системный оператор из internal.whitehouse.gov не разместит crossdomain.xml на сервере, что приведет к тому, что Unity не будет скачивать pdf.

К сожалению, в связи с защитой людей, установивших Unity Web Player, люди, разрабатывающие игры в Unity, должны учитывать эти меры безопасности. Подобные ограничения присутствуют во всех основных плагинах (Flash, Silverlight, Shockwave).

Исключения

В связи с поиском баланса между защитой пользователей веб плеера и облегчением жизни разработчиков, мы реализовали исключения в механизме безопасности:

Вы можете позволить скачивать изображения с сервера не имеющего файл crossdomain.xml. Однако, единственная вещь, которую вы можете сделать с этими изображениями - использовать их в качестве текстур в сцене. На них нельзя использовать GetPixel(). Также запрещено читать обратно с экрана. Обе попытки приведут к SecurityException:

SecurityException: No read access to the texture data: 
  at (wrapper managed-to-native) UnityEngine.Texture2D:GetPixel (int,int)


Скачивать изображение, так долго, как разработчик не получает к нему доступ, это нормально. Вы можете отображать это для пользователя, но не можете отправить байты изображения обратно серверу. Если вам нужен доступ к пиксельным данным, разместите файл crossdomain.xml на сервер, из которого извлекается изображение.

Using the Chain of Trust system in the Web Player
Решение проблем при использовании веб-плеера