O início de sessão funciona, o PWD funciona, e depois o LIST fica pendurado até o cliente desistir ou passar para outro modo de dados. Esta separação é a assinatura: a ligação de controlo para a porta 21 está saudável, enquanto a ligação de dados é construída a partir de um endereço ou porto que o outro lado não consegue alcançar. Atrás de um gateway VPN que também faz NAT, o culpado habitual é um comando FTP cuja carga útil indica um endereço de túnel como 10.8.0.6. A tradução dos cabeçalhos nunca toca nesse valor.

O que se segue é de onde vem esse valor, e que caixa tem permissão para o alterar.

O que se parte é a carga útil, não o túnel

O FTP coloca o ponto final dos dados dentro do fluxo de controlo. No modo ativo o cliente envia PORT com o seu próprio endereço e porto, e o servidor liga de volta para esse par. No modo passivo o servidor responde 227 com um par, e o cliente liga a esse par em vez disso.

Ambas as formas transportam o mesmo tipo de afirmação: liga-te a este endereço, neste porto. Um dispositivo que só reescreve cabeçalhos IP e TCP deixa a afirmação intacta, por isso um dos lados continua a tentar alcançar um endereço que só existe do outro lado de um túnel. A ligação de dados pára depois de a ligação de controlo já ter sido declarada saudável.

Três modos, três cargas úteis

A tabela abaixo mostra a que lado se pede que ligue, e o que um NAT que só reescreve cabeçalhos pode fazer quanto a isso.

Leia a última coluna como aquilo que falha primeiro. No modo ativo é o servidor que liga para um endereço privado; no modo passivo é o cliente; com FTPS a carga útil é texto cifrado e a caixa intermédia tem ainda menos com que trabalhar.

ModeValue in the control streamWho dials whomHeader-only NAT leaves
Active (PORT)client address and portserver dials the clienta server dialing an unreachable tunnel address
Passive (227)server address and portclient dials the servera client dialing an address it cannot route to
FTPSthe same values, inside TLSas aboveciphertext, so no rewrite happens at all

Coloque o auxiliar onde acontece a tradução

No Linux a reescrita da carga útil é feita pelo auxiliar nf_conntrack_ftp. Vigia a ligação de controlo, aprende o porto negociado, cria uma expectativa para o fluxo de dados e, numa caixa NAT, reescreve o endereço e o porto dentro da carga útil. Só ajuda no dispositivo que traduz o endereço do cliente. Carregá-lo no cliente, ou num router que apenas reencaminha o fluxo, não altera nada na sessão.

Estes três comandos mostram se o módulo está presente, se está associado e se existe uma expectativa enquanto uma sessão está aberta:

modprobe nf_conntrack_ftp
lsmod | grep nf_conntrack_ftp
conntrack -L expect | grep ftp

Carregar o módulo não é o mesmo que associá-lo. Os kernels desde o 4.7 vêm com net.netfilter.nf_conntrack_helper=0, por isso o auxiliar espera por uma regra explícita, por exemplo iptables -t raw -A PREROUTING -p tcp --dport 21 -j CT --helper ftp. Se a lista de expectativas ficar vazia enquanto se tenta uma transferência, é a associação que deve ser verificada, não o módulo.

Modo passivo: diga ao servidor o que anunciar

O modo passivo é mais fácil de tornar determinístico porque se pode dizer ao servidor o que colocar na resposta 227. No vsftpd isso é pasv_address, juntamente com pasv_min_port e pasv_max_port; o ProFTPD usa MasqueradeAddress e PassivePorts. Defina isso primeiro, porque um endereço anunciado correctamente elimina a necessidade de reescrever o que quer que seja desse lado.

Depois deixe passar exactamente esse intervalo de portos pelo gateway, por exemplo -A FORWARD -i tun0 -p tcp --dport 30000:30100 -j ACCEPT, para que a regra coincida com o que o servidor anuncia.

As duas definições têm de concordar. Um servidor ao qual se diz para anunciar 30000-30100 enquanto o gateway permite 40000-40100 falha da forma menos útil: a conversa de controlo parece saudável e todas as ligações de dados morrem. Compare os números antes de depurar qualquer outra coisa.

Duas assinaturas de falha, e o que o FTPS elimina

Uma pendura no LIST aponta para a primeira ligação de dados da sessão, onde tanto a reescrita do endereço como a expectativa têm de funcionar. Uma pendura no RETR depois de um LIST a funcionar aponta para a transferência em si, ou seja, para o intervalo passivo ou para o MTU do túnel. Essa segunda assinatura não é um problema de carga útil, e as definições do auxiliar não a corrigem.

O FTP sobre TLS elimina a carga útil que o auxiliar lê. Uma caixa intermédia não pode reescrever um valor PORT ou PASV que não consegue decifrar, por isso restam um proxy que termina o TLS, um servidor que anuncia um endereço alcançável dentro de um intervalo limitado, ou um protocolo de transferência diferente.

Uma ordem breve de verificações

Trabalhe do sintoma para fora. Confirme que o LIST falha enquanto o PWD tem sucesso, capture o endereço dentro da carga útil PORT ou 227, e pergunte que dispositivo traduz esse endereço. Associe o auxiliar aí, observe a lista de expectativas durante uma transferência, depois corrija o modo passivo no servidor e reflicta o intervalo na regra do gateway.

Mantenha a falha do caminho de dados separada da falha de transferência massiva, porque levam a definições diferentes.

Artigos relacionados