2012-12-27 27 views
6

我使用https://github.com/lemmingzshadow/php-websocket/我的websocket的服務器源檢查安全嗎?

我可以允許一些領域,我已經允許localhost並指向我的本地服務器的域。但我想知道是否有其他人在他的計算機上有一臺服務器可以通過他的本地主機服務器中的腳本連接到我的websocket(通過我的域)。

下面是相關的代碼:

- >服務器/ server.php

$server->setAllowedOrigin('localhost'); 
$server->setAllowedOrigin('mydomain.com'); 

- >服務器/ LIB /網頁套接字/ Connection.php

// check origin: 
if($this->server->getCheckOrigin() === true) 
{ 
    $origin = (isset($headers['Sec-WebSocket-Origin'])) ? $headers['Sec-WebSocket-Origin'] : false; 
    $origin = (isset($headers['Origin'])) ? $headers['Origin'] : $origin; 
    if($origin === false) 
    { 
     $this->log('No origin provided.'); 
     $this->sendHttpResponse(401); 
     stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR); 
     $this->server->removeClientOnError($this); 
     return false; 
    } 

    if(empty($origin)) 
    { 
     $this->log('Empty origin provided.'); 
     $this->sendHttpResponse(401); 
     stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR); 
     $this->server->removeClientOnError($this); 
     return false; 
    } 

    if($this->server->checkOrigin($origin) === false) 
    { 
     $this->log('Invalid origin provided.'); 
     $this->sendHttpResponse(401); 
     stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR); 
     $this->server->removeClientOnError($this); 
     return false; 
    } 
} 

- >服務器/ lib/WebSocket/Server.php

public function checkOrigin($domain) 
{ 
    $domain = str_replace('http://', '', $domain); 
    $domain = str_replace('https://', '', $domain); 
    $domain = str_replace('www.', '', $domain); 
    $domain = str_replace('/', '', $domain); 

    return isset($this->_allowedOrigins[$domain]); 
} 

public function setAllowedOrigin($domain) 
{ 
    $domain = str_replace('http://', '', $domain); 
    $domain = str_replace('www.', '', $domain); 
    $domain = (strpos($domain, '/') !== false) ? substr($domain, 0, strpos($domain, '/')) : $domain; 
    if(empty($domain)) 
    { 
     return false; 
    } 
    $this->_allowedOrigins[$domain] = true;  
    return true; 
} 

編輯:

也許我不夠清楚。我希望每個人都可以連接到websocket,但只有當他們在我的域名(或我的本地主機)時,就像AJAX中的Same Origin Policy一樣。

我的擔心是,如果我允許本地主機,也許其他計算機中的其他本地主機也將被允許。

+0

_maybe其他計算機中的所有其他本地主機都將被允許。不,這不是問題。 IP由您的服務器轉換爲名稱,'localhost'僅用於連接來自'127.0.0.1'的環回地址。 – Barmar

+0

謝謝,這就是我想知道的。但是起源是由一個頭文件提供的,如果我不告訴它這麼做,我的服務器不應該分析我的頭文件來嘗試轉換IP和域名,不是嗎? – Oriol

+0

它來自IP數據包的頭部,用於實現TCP/IP傳輸。如果您在允許列表中使用主機名稱,則必須使用DNS將這些名稱轉換爲IP。 – Barmar

回答

1

雖然我很擔心,允許所有本地主機連接時,我想只允許我的本地主機,我發現,在another questionkanaka說:

爲了澄清,Javascript語言,一個無與倫比的和運行良好表現爲 瀏覽器不會影響Sec-WebSocket-Origin的值,該值保存從加載頁面的原始站點的值(允許您的 服務器僅允許某些始發點)的值。但是,如果您有作爲WebSocket客戶端在Node.js中運行的Javascript,它可以將 原始值設置爲任何想要的值。 CORS安全性是針對瀏覽器用戶的安全 ,而不是針對您的服務器。你需要其他機制來保護你的服務器。

然後,我的原點檢查代碼根本不安全;如果所有的本地主機都允許,因爲如果有人有足夠的知識使用他自己的本地主機連接到我的websocket,那麼他可能會修改Origin頭部。

+0

沒有「別人的本地主機」這樣的東西 –

+0

@ MahmoudAl-Qudsi嗯,我的意思是「別人的本地服務器」,這是使用本地主機(在他的機器)訪問。 – Oriol

+0

這就是我的意思。 *每個*服務器都是「本地主機」。 –

1

如果你想確定,你應該添加一個IP檢查,分析$_SERVER["REMOTE_ADDR"]。被檢查的來源是客戶提供的文本值,可以很容易僞造。

if (!in_array($_SERVER["REMOTE_ADDR"], array("127.0.0.1", "ip.of.dom.ain")) exit; 

如果你不想硬編碼的IP地址,或者如果經常更改,您可以使用gethostbyname爲這樣的域名獲取IP地址。請注意,當必須爲域名查詢DNS時,這會爲每個請求添加一個延遲,並且這種方式會在DNS關閉時導致超時。 (下面的代碼可以優化,當然)

$allowed_origins = array('localhost', 'mydomain.com'); 
$allowed_ips = array(); 
foreach ($allowed_origins as $domain) { 
    $server->setAllowedOrigin($domain); 
    $allowed_ips[] = gethostbyname($domain); 
} 
if (!in_array($_SERVER["REMOTE_ADDR"], $allowed_ips)) exit; 

也許是正確的方式做,這是通過您的Web服務器來保護您的資源,使其只接受請求從IP地址要允許(見deny in Apachedeny in nginx)。

+0

但我不能做一個IP檢查,因爲我想每個人都可以連接到websocket,但只有當他們在我的域名......並且使用$ _SERVER [「REMOTE_ADDR」](或Apache中的「deny」)時,我可以檢查客戶的IP,而不是域名,不是嗎? – Oriol

+0

哦,我明白了,我只是假設你是以某種方式代理的。那麼,任何人都可以連接到你的websocket,就像這是想法。這個人是否在他的機器上有一臺服務器並不重要。他可以使用任何程序,比如'curl'來連接你的服務器。你試圖避免什麼情況? (你爲什麼要說服某個服務器的人?) – akirk

+0

我說的是有人用服務器,因爲我將localhost添加到了允許的源列表中,然後我認爲有人用服務器(他的計算機上的本地主機)連接到我的WebSocket的腳本;而且他可以這樣做,因爲腳本在本地主機中執行,與本地主機匹配,即使它們不相同。所以,我想要的是像AJAX中的同源策略,只允許來自我的域和我的本地主機的連接。 – Oriol

0

如果您正在檢查Origin標題,那足以執行類似於相同來源策略的內容。 Origin標題可以在自定義應用程序(如節點WebSocket客戶端)中在瀏覽器外部進行欺騙,但這並不重要,對於普通的HTTP請求也是如此。 SOP只是關於瀏覽器。

因此,檢查Origin標題不是關於訪問保護,而是關於CSRF保護。如果用戶當前登錄,不受信任的第三方站點將不被允許連接到您的WebSocket端點(憑證自動發送)。