![如何存取 Linux 上的開放和偵聽連接埠?](https://rvso.com/image/76414/%E5%A6%82%E4%BD%95%E5%AD%98%E5%8F%96%20Linux%20%E4%B8%8A%E7%9A%84%E9%96%8B%E6%94%BE%E5%92%8C%E5%81%B5%E8%81%BD%E9%80%A3%E6%8E%A5%E5%9F%A0%EF%BC%9F.png)
轉發我希望打開的連接埠後,我似乎無法連接該連接埠或從該連接埠獲取任何資料。我寫的 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 項更改,現在一切都可以正常運作。