Linux에서 개방형 및 수신 대기 포트에 어떻게 접근할 수 있나요?

Linux에서 개방형 및 수신 대기 포트에 어떻게 접근할 수 있나요?

열려는 포트를 전달한 후 이 포트에 연결하거나 데이터를 가져올 수 없는 것 같습니다. 내가 작성한 PHP CLI 소프트웨어는 포트를 적극적으로 수신하고 있습니다.우분투 14.04. 코드의 일부가 아래에 나와 있습니다. 포트는 AF_INET으로 열리고 스크립트는 각 행에 대해 오류를 발생시키지 않으며 /etc/protocols에는 'tcp 6 TCP'로 정의된 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을 사용하면 포트도 열려 있는 것으로 표시됩니다. 다른 포트도 사용해 보았습니다. 내 클라이언트 측 연결 스크립트는 Windows에서 PHP CLI를 실행할 때 연결하는 데 작동하는 JavaScript websocket 스크립트입니다. 스크립트가 너무 길어 여기에 포함할 수 없으며 외부 네트워크에서 연결되지 않습니다. 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,dr; 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])소켓을 닫도록 호출해야 합니다. 이는 기본적으로 OS 커널에 사용자가 지정한 포트에 대해 들어오는 TCP SYN 패킷 수신을 중단하도록 지시합니다.

답변2

문제는 주로 모뎀/라우터에서 비롯된 여러 가지 것으로 나타났습니다. 나는모토로라 SB6580, 최근에 펌웨어 업데이트가 있었고 10일 동안 재부팅하지 않았기 때문에 속도가 상당히 느려져서 너무 많은 변경을 하고 싶지 않게 되었습니다.

그만큼펌웨어 업데이트로 인해 포트 전달 페이지가 변경되었습니다.외부 원격 호스트 주소 섹션(기본값은 0.0.0.0)을 포함하려면 여기서는 문제가 없지만 다른 문제로 인해 내가 설정한 기존 포트 전달 규칙을 위반했습니다.

작동하지 않는 전달 대상 포트 범위를 사용하고 있었는데 이 범위를 8399 - 8399로 변경하면 다시 작동하기 시작했습니다. 재시작은 모뎀 속도를 높이는 것 외에 영향을 미치지 않았으며 프로토콜을 모두에서 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())을 사용할 때 반환되는 주소는 /etc/hosts 파일의 두 번째 항목인 로컬 주소 127.0.1.1이므로 소켓 바인딩에는 작동하지 않습니다. $_SERVER['REMOTE_ADDR']도 경고를 반환합니다. 호스트를 조회할 수 없습니다. 에 의해이를 집(서브넷?) 주소(내 주소는 192.168.0.101) 또는 IPv4 와일드카드 0.0.0.0으로 수동으로 변경합니다., 소켓 수신기가 올바르게 바인딩되고 외부 연결을 허용합니다.

라우터에 대한 경험과 Linux에 대한 경험이 부족하여 Linux 문제 해결에 있어 잘못된 방향으로 기울게 되었습니다. Windows 7에서도 작동하지 않는 것을 발견한 후 위의 두 가지 사항을 변경했고 이제 모든 것이 정상적으로 작동합니다.

관련 정보