如何存取 Linux 上的開放和偵聽連接埠?

如何存取 Linux 上的開放和偵聽連接埠?

轉發我希望打開的連接埠後,我似乎無法連接該連接埠或從該連接埠獲取任何資料。我寫的 PHP CLI 軟體正在主動監聽端口烏班圖14.04。部分程式碼如下所示。連接埠作為 AF_INET 打開,腳本每行都不會拋出錯誤,並且 /etc/protocols 將 tcp 定義為“tcp 6 TCP”。

// I have tried $host=gethostbyname(gethostname());$port=8399 (host is 127.0.1.1)
// as well as $host = '0.0.0.0'; $port = 8399; and other addresses

$this->wsRead[0] = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
socket_set_option($this->wsRead[0], SOL_SOCKET, SO_REUSEADDR, 1)
socket_bind($this->wsRead[0], $host, $port) 
socket_listen($this->wsRead[0], 10)
while (isset($this->wsRead[0])) { /* Handshake/Process data, etc. */ }

連接埠已轉發,我的iptables 為空,儘管我已經嘗試專門為該連接埠添加允許規則。我嘗試以超級用戶身份運行腳本。當伺服器正在偵聽時,netstat -tuln 列出了這一行(帶有我的連接埠8399),我注意到apache 也列出了,它工作正常並顯示為來自外部連接埠檢查網站的開放連接埠(在端口8301 上):

Proto Recv-Q Send-Q Local Address      Foreign Address    State
tcp        0      0 0.0.0.0:8399       0.0.0.0:*          LISTEN
tcp6       0      0 :::8301            :::*               LISTEN
tcp6       0      0 :::80              :::*               LISTEN

使用 nmap 連接埠也顯示為開啟。我也嘗試過不同的連接埠。我的客戶端連線腳本是一個 JavaScript websocket 腳本,可在 Windows 上執行 PHP CLI 時進行連線。該腳本太長,無法包含在此處,並且它不從外部網路連接。如果我將 JS 和 PHP 腳本設定為本地位址 127.0.0.1 或 192.168.0.###,那麼它可以工作,但不能從我的 LAN 以外的裝置上工作。

// The JS is basically this, plus some connection events to alert success/fail.
// This external connection request will always time out
Server = new WebSocket('ws://68.215.154.129:8399');

除了 iptables 之外,我是否在 Linux 中缺少一些我沒有繞過的防火牆? Apache 正在正確開啟連接埠以及 PC 上的其他軟體,但我的腳本似乎缺少完全開啟連接埠以供外部使用的必要步驟。

TL,博士;使用 JavaScript 用戶端使用外部 IP 位址連接到在 Windows 上執行但在 Ubuntu 上執行的 PHP 伺服器。連接埠轉送、監聽、不被 iptables 阻止, 還剩下什麼?

答案1

您在概念上和程式碼中遺漏了一些東西。您有 PHP 程式碼偵聽連接,但您必須在使用它之前接受連接。

$ns = socket_accept($this->wsRead[0]);
$some_string = socket_read($ns, 128);

對塊的呼叫socket_accept()。直到某個客戶端程式連線到正在等待連線的程式時,它才會回傳。

呼叫socket_accept()返回您用於與遠端程式通訊的實際套接字。我不認為isset()這真的是你想要的,你應該調查一下socket_select()什麼的。當您完成與遠端的通訊後,您可以調用socket_close($ns),然後循環返回以socket_accept($this->wsRead[0])等待另一個遠端程式連接到您的程式。

當您的 PHP 程式完成處理連線時,它應該呼叫socket_close($this->wsRead[0])關閉套接字,這基本上告訴作業系統核心停止偵聽您指定連接埠的傳入 TCP SYN 封包。

答案2

事實證明,問題出在多個方面,主要源自於我的數據機/路由器。我用一個摩托羅拉SB6580,最近進行了韌體更新,並且已經有10天沒有重新啟動了,導致它變得非常慢,阻止了我想要對其進行太多更改。

韌體更新更改了連接埠轉送頁面包含外部遠端主機位址部分(預設為 0.0.0.0)在這裡沒有問題,但他們所做的其他事情打破了我設定的現有連接埠轉送規則。

我使用了一系列無法轉送的端口,透過將此範圍更改為 8399 - 8399,它再次開始工作。除了提高調變解調器速度之外,重新啟動並沒有影響它,將協定從 Both 變更為 TCP 也沒有影響。

IP Addr|Start Port|End Port|Remote Host Addr|Start Port|End Port|Protocol|Enabled
192.168.0.101|8340|    8399|         0.0.0.0|      8340|    8399|    Both|Checked
192.168.0.101|8399|    8399|         0.0.0.0|      8399|    8399|     TCP|Checked

另外,在 Linux 上使用 PHP 指令 gethostbyname(gethostname()) 時,傳回的位址是本機位址 127.0.1.1,也就是 /etc/hosts 檔案中的第二個項目,這不適用於綁定套接字。 $_SERVER['REMOTE_ADDR'] 也傳回警告:無法尋找主機。經過手動將其更改為家庭(子網路?)位址(我的是 192.168.0.101)或 IPv4 通配符 0.0.0.0,套接字偵聽器已正確綁定並接受外部連接。

我對路由器的使用經驗和對 Linux 的缺乏經驗使我傾向於在 Linux 故障排除方面走上錯誤的道路。在註意到 Windows 7 上的情況也無法正常運作後,我進行了上述 2 項更改,現在一切都可以正常運作。

相關內容