![Como posso alcançar uma porta aberta e de escuta no Linux?](https://rvso.com/image/76414/Como%20posso%20alcan%C3%A7ar%20uma%20porta%20aberta%20e%20de%20escuta%20no%20Linux%3F.png)
Depois de encaminhar a porta que desejo abrir, não consigo conectar ou obter dados para esta porta. O software PHP CLI que escrevi está escutando ativamente a porta emUbuntu 14.04. Parte do código é mostrada abaixo. A porta é aberta como AF_INET, o script não gera erros para cada linha e /etc/protocols tem tcp definido como '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. */ }
As portas são encaminhadas e meuiptables estão vazios, embora eu tenha tentado adicionar especificamente uma regra de permissão para a porta. Tentei executar o script como superusuário. Quando o servidor está escutando, netstat -tuln lista esta linha (com minha porta 8399), e noto que o apache também está listado, que funciona bem e mostra como uma porta aberta em sites de verificação de portas externas (na porta 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
Usando o nmap, a porta também mostra estar aberta. Eu tentei portas diferentes também. Meu script de conexão do lado do cliente é um script JavaScript websocket que funciona para conectar ao executar o PHP CLI no Windows. O script é muito longo para ser incluído aqui e não se conecta à rede externa. Se eu definir scripts JS e PHP para endereços locais 127.0.0.1 ou 192.168.0.### então ele funcionará, mas não de um dispositivo fora da minha 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');
Estou faltando algum firewall no Linux além do iptables que não estou ignorando? O Apache está abrindo as portas corretamente e outros softwares no PC, mas parece que meu script está faltando uma etapa necessária para abrir totalmente a porta para uso externo.
tl, dr; Conectando-se usando endereço IP externo usando cliente JavaScript ao servidor PHP funcionando no Windows, mas não no Ubuntu.Porta encaminhada, escutando, não bloqueada pelo iptables, o que sobrou?
Responder1
Está faltando algo conceitualmente e no código. Você tem o código PHP escutando conexões, mas precisa aceitar uma conexão antes de usá-la.
$ns = socket_accept($this->wsRead[0]);
$some_string = socket_read($ns, 128);
A chamada para socket_accept()
blocos. Ele não retornará até que algum programa cliente se conecte ao programa que agora aguarda conexão.
Uma chamada para socket_accept()
retorna o soquete real que você usa para se comunicar com o programa remoto. Eu não acho isset()
que seja realmente o que você quer, você deveria investigar socket_select()
ou algo assim. Quando terminar de se comunicar com o controle remoto, você liga socket_close($ns)
e retorna à chamada socket_accept($this->wsRead[0])
para aguardar que outro programa remoto se conecte ao seu programa.
Quando seu programa PHP terminar de lidar com as conexões, ele deverá chamar socket_close($this->wsRead[0])
para fechar o soquete, o que basicamente diz ao kernel do sistema operacional para parar de ouvir os pacotes TCP SYN recebidos para a porta que você especificar.
Responder2
Acontece que o problema era de várias coisas, principalmente decorrente do meu modem/roteador. Eu uso umMotorola SB6580, que recentemente teve uma atualização de firmware e não foi reinicializado por 10 dias, tornando-o bastante lento, impedindo-me de querer fazer muitas alterações nele.
Oatualização de firmware alterou a página de encaminhamento de portaincluir uma seção de endereço de host remoto externo (o padrão é 0.0.0.0) não é problema aqui, mas outra coisa que eles fizeram quebrou as regras de encaminhamento de porta existentes que eu havia definido.
Eu estava usando um intervalo de portas a serem encaminhadas que não estava funcionando e, ao alterar esse intervalo para 8399 - 8399, ele começou a funcionar novamente. A reinicialização não afetou além de aumentar a velocidade do modem, nem a mudança do protocolo de Ambos para 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
Além disso, ao usar o comando gethostbyname(gethostname()) do PHP no Linux, o endereço retornado é um endereço local de 127.0.1.1, a segunda entrada no arquivo /etc/hosts, que não funcionará para vincular um soquete. $_SERVER['REMOTE_ADDR'] também retorna um aviso: não é possível procurar o host. Poralterando manualmente para o endereço inicial (sub-rede?) (o meu é 192.168.0.101) ou o curinga IPv4 0.0.0.0, o ouvinte de soquete será vinculado corretamente e aceitará conexões externas.
Minha experiência com o roteador e inexperiência com Linux me fez seguir o caminho errado para solucionar problemas do Linux. Depois de perceber que as coisas também não estavam funcionando no Windows 7, fiz as 2 alterações acima e agora tudo funciona como deveria.