In Unity 3.0, the webplayer implements a security model very similar to the one used by the Adobe Flash player™. This security restrictions apply only to the webplayer, and to the editor when the active build target is WebPlayer. The security model has several parts:
현재는 보안 모델의 처음 두 부분만 Unity 에디터에서 에뮬레이트합니다.
Unity에 빌트인된 멀티플레이어 네트워킹 기능(UnityEngine.Network
, UnityEngine.NetworkView
클래스 등)은 영향을 받지 않습니다.
WWW 클래스와 소켓은 동일한 정책 스키마를 사용하지만 이를 제외하면 둘은 완전히 별개의 시스템입니다. WWW 정책은 호스트된 웹 서비스에 대한 허용만 정의하지만 소켓 정책은 모든 TCP/UDP 소켓 연결에 적용됩니다.
The Unity editor comes with an “Emulate Web Security” feature, that imposes the webplayer’s security model. This makes it easy to detect problems from the comfort of the editor. You can find this setting in Edit->Project Settings->Editor. See also the Editor settings.
The Unity webplayer expects a http served policy file named crossdomain.xml
to be available on the domain you want to access with the WWW class,
(although this is not needed if it is the same domain that is hosting the unity3d file).
For example, imagine a tetris game, hosted at the following url:
http://gamecompany.com/games/tetris.unity3d
needs to access a highscore list from the following url:
http://highscoreprovider.net/gethighscore.php
In this case, you would need to place a crossdomain.xml
file at the root of the highscoreprovider.net domain like this: http://highscoreprovider.net/crossdomain.xml
The contents of the crossdomain.xml
file are in the format used by the Flash player. It is very likely that you’ll
find the crossdomain.xml
file already in place. The policy in the file look like this:
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
When this file is placed at http://highscoreprovider.net/crossdomain.xml, the owner of that domain declares that the contents of the webserver may be accessed by any webplayer coming from any domain.
The Unity webplayer does not support the <allow-http-request-headers-from domain> and <site-control permitted-cross-domain-policies> tags. Note that crossdomain.xml
should be an ASCII file.
Setting an environment variable ENABLE_CROSSDOMAIN_LOGGING
to 1
will cause console messages to be generated as the Unity runtime fetches and decodes the crossdomain.xml
file. On a Mac you can set global environment variables in /etc/launchd.conf
. On a PC use Control Panel->System And Security->System->Advanced system settings->Environment Variables…
Here is an example output with this environment variable set, when the webplayer attempts to fetch an image from a remote server:
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
When running in the Editor these messages are written to the Editor.log. Attempting to read a crossdomain.xml
file incorrectly stored as utf16
with a BOM
will result in a failure to parse the xml:
BuildFlashPolicy caught an exception while parsing http://www.remoteserver.com/crossdomain.xml: Expected element
This is because the BOM
is not expected. Using an unsupported utf16
file with no BOM
will result in:
BuildFlashPolicy caught an exception while parsing http://www.remoteserver.com/crossdomain.xml: Policy can't be constructed from empty stream.
This is because the first byte in the file is zero, which causes the parser to think it’s reached the end of the file. Crossdomain.xml
must be an ASCII file.
A Unity webplayer needs a socket served policy in order to connect to a particular host. This policy is by default hosted by the target host on port 843 but it can be hosted on other ports as well. The functional difference with a non-default port is that it must be manually fetched with Security.PrefetchSocketPolicy() API call and if it is hosted on a port higher than 1024 the policy can only give access to other ports higher than 1024.
When using the default port it works like this: A Unity webplayer tries to make a TCP socket connection to a host, it first checks that the host server will accept the connection. It does this by opening a TCP socket on port 843, issues a request, and expects to receive a socket policy over the new connection. The Unity webplayer then checks that the host’s policy permits the connection to go ahead and it will proceed without error if so. This process happens transparently to the user’s code, which does not need to be modified to use this security model. An example of a socket policy look like this:
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" to-ports="1200-1220"/>
</cross-domain-policy>"
This policy effectively says “Content from any domain is free to make socket connections at ports 1200–1220”. The Unity webplayer will respect this, and reject any attempted socket connection using a port outside that range (a SecurityException will be thrown).
UDP 연결 사용 시 TCP와 유사한 방식으로 적용해야 할 때 정책을 자동으로 가져올 수 있습니다. 차이점이 있다면 TCP에서 자동으로 가져오기 기능은 무언가에 연결했을 때 발생하는(서버 연결이 허용되는지 확인) 반면 UDP는 비연결형이기 때문에 데이터를 송수신하는 어떤 API 호출 지점에서라도 발생한다는 것입니다(서버에서/서버로 트래픽을 송수신할 수 있는지 확인).
The format used for the socket policy is the same as that used by the Flash player except some tags are not supported. The Unity webplayer only supports “*” as a valid value for the domain setting and the “to-ports” setting is mandatory.
<?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 연결 타입에 모두 적용되므로 UDP와 TCP 트래픽을 하나의 정책 서버에서 제어할 수 있습니다.
편의를 위해 843 포트에서 대기하는 간단한 프로그램이 제공됩니다. 연결되면 요청 문자열을 받고 유효한 소켓 정책으로 응답합니다. 서버 코드는 Unity 설치 폴더에 있습니다. Windows에서는 Data/Tools/SocketPolicyServer에서, OS X에서는 /Unity.app/Contents/Tools/SocketPolicyServer에서 찾을 수 있습니다. 사전에 빌드된 실행 파일은 Mono로 실행 가능하기 때문에 Mac에서만 실행될 수 있으니 참고하십시오. “mono sockpol.exe”만 입력하면 실행됩니다. 이 예제 코드는 소켓 정책 서버의 올바른 동작을 보여줍니다. 구체적으로 서버는 <policy-file-request/>를 포함한 zero-terminated 문자열의 수신을 기다립니다. 정확하게 이 문자열을 수신할 때만 클라이언트에 소켓 정책 xml 문서를 전송합니다. 또한 xml 헤더와 xml 바디는 단일 소켓 쓰기로 전송해야만 합니다. 헤더와 바디를 별도 소켓 쓰기 작업으로 분리하면 Unity가 불완전한 정책을 받는 것이므로 보안 예외를 일으킬 수 있습니다. 서버에서 문제가 발생하면 제공된 예제를 사용해 보시기 바랍니다. 서버의 문제인지 네트워크의 문제인지 진단하는 데 도움됩니다.
일반적으로 멀티 플레이어 게임 네트워킹에 사용되는 서드파티 네트워킹 라이브러리는 P2P 기능(아래 참조)에만 종속하지 않고 전용 서버를 사용하는 한 이러한 요구 사항을 처리할 수 있어야 합니다. 때로는 호스팅 정책의 지원으로 즉시 가능하기도 합니다.
Note: Whilst the crossdomain.xml
and socket policy files are both xml documents and are broadly similar, the way that these documents are served are very different. Crossdomain.xml
(which applied to http requests) is fetched using http on port 80, where-as the socket policy is fetched from port 843 using a trivial server that implements the <policy-file-request/>. You cannot use an http server to issue the socket policy file, nor set up a server that simply sends the socket policy file in response to a socket connection on port 843. Note also that each server you connect to requires its own socket policy server.
소켓 정책 서버에 연결하기 위해 텔넷
을 사용할 수 있습니다. 세션의 예제는 아래와 같습니다.
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$
이 예제에서 텔넷은 포트 843의 localhost에 연결하는 데 사용됐습니다. 텔넷은 첫 번째 세 줄로 응답하며 사용자가 입력하기까지 대기합니다. 사용자가 정책 요청 문자열 <policy-file-request/> 를 입력하면 소켓 정책 서버가 받아서 소켓 정책으로 응답합니다. 그런 다음 서버는 연결을 해제하고 텔넷은 연결이 종료되었음을 보고합니다.
You cannot create listening sockets in the webplayer, it cannot act as a server. Therefore webplayers cannot communicate with each other directly (peer 2 peer). When using TCP sockets you can only connect to remote endpoints provided it is allowed through the socket policy system. For UDP it works the same but the concept is a little bit different as it is a connectionless protocol, you don’t have to connect/listen to send/receive packets. It works by enforcing that you can only receive packets from a server if he has responded first with a valid policy with the allow-access-from domain
tag.
The socket and WWW security features exist to protect people who install the Unity Web Player. Without these restrictions, an attack such as the following would be possible:
With the WWW and socket security features, this attack will fail, because before downloading the pdf, unity checks http://internal.whitehouse.gov/crossdomain.xml, with the intent to ask that server: “is the data you have on your server available for public usage?”. Placing a crossdomain.xml on a webserver can be seen as the response to that question. In the case of this example, the system operator of internal.whitehouse.gov will not place a crossdomain.xml on its server, which will lead Unity to not download the pdf.
Unfortunately, in order to protect the people who install the Unity Web Player, people who develop in Unity need to take these security measures into account when developing content. The same restrictions are present in all major plugin technologies. (Flash, Silverlight, Shockwave)
In order to find the right balance between protecting Web Player users and making life of content developers easy, we have implemented an exception to the security mechanism described above:
You are allowed to download images from servers that do not have a crossdomain.xml file. However, the only thing you are allowed to do with these images is use them as textures in your scene. You are not allowed to use GetPixel() on them. You are also not allowed to read back from the screen. Both attempts will result in a SecurityException being thrown:
SecurityException: No read access to the texture data:
at (wrapper managed-to-native) UnityEngine.Texture2D:GetPixel (int,int)
The reasoning is here is that it’s okay to download the image, as long as the content developer gets no access to it. So you can display it to the user, but you cannot send the bytes of the image back to some other server. If you need access to the pixel data then place an crossdomain.xml
file on the server where the images are fetched from.