amazon ec2 - east - vsftpd devuelve 0,0,0,0 en respuesta a PASV
security groups (1)
Parece un error en vsftpd para mí.
Del código que parece, siempre enviará el 0,0,0,0
, si se establece el público pasv_address
, pero el servidor tiene una dirección (local) IPv6.
handle_pasv
en postlogin.c
:
int is_ipv6 = vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr);
...
if (tunable_pasv_address != 0)
{
vsf_sysutil_sockaddr_alloc_ipv4(&s_p_sockaddr);
/* Report passive address as specified in configuration */
if (vsf_sysutil_inet_aton(tunable_pasv_address, s_p_sockaddr) == 0)
{
die("invalid pasv_address");
}
}
else
{
vsf_sysutil_sockaddr_clone(&s_p_sockaddr, p_sess->p_local_addr);
}
str_alloc_text(&s_pasv_res_str, "Entering Passive Mode (");
if (!is_ipv6)
{
str_append_text(&s_pasv_res_str, vsf_sysutil_inet_ntop(s_p_sockaddr));
}
else
{
const void* p_v4addr = vsf_sysutil_sockaddr_ipv6_v4(s_p_sockaddr);
if (p_v4addr)
{
str_append_text(&s_pasv_res_str, vsf_sysutil_inet_ntoa(p_v4addr));
}
else
{
str_append_text(&s_pasv_res_str, "0,0,0,0");
}
}
donde vsf_sysutil_sockaddr_ipv6_v4
devuelve 0, si el s_p_sockaddr
no es IPv6, lo que nunca es, cuando se establece pasv_address
.
sysutil.c
:
const void*
vsf_sysutil_sockaddr_ipv6_v4(const struct vsf_sysutil_sockaddr* p_addr)
{
static unsigned char pattern[12] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
const unsigned char* p_addr_start;
if (p_addr->u.u_sockaddr.sa_family != AF_INET6)
{
return 0;
}
if (vsf_sysutil_memcmp(pattern, &p_addr->u.u_sockaddr_in6.sin6_addr, 12))
{
return 0;
}
p_addr_start = (const unsigned char*)&p_addr->u.u_sockaddr_in6.sin6_addr;
return &p_addr_start[12];
}
Imho, el código está mal. Funciona (y tiene sentido), cuando la dirección IP es "autodetectada" desde p_sess->p_local_addr
, pero falla, cuando se pasv_address
dirección pasv_address
.
Considere reportar esto al autor de vsftpd.
La única solución que veo es eliminar una dirección IPv6 privada, si es posible en EC2.
O use otro servidor FTP, por ejemplo, ProFTPD .
Mantener una explicación original de PASV
contra EPSV
:
Solo para explicar la diferencia entre el PASV
y el EPSV
: El PASV
devuelve una dirección IP en la respuesta. Esa información está en 99.9% redundante. Y comúnmente causa problemas cuando el servidor no tiene conocimiento de su dirección IP externa.
El EPSV
se introdujo más tarde que el PASV
, cuando quedó claro que la presencia de la dirección IP en la respuesta es problemática. Entonces, con el EPSV
, solo se incluye un número de puerto. Y el cliente se conecta a la dirección IP del servidor FTP implícitamente.
Si el servidor realmente devuelve 0,0,0,0
en respuesta al comando PASV
, queda claro por qué el cliente no se puede conectar al servidor cuando se usa PASV
.
Configuré un servidor FTP en AWS EC2 (Ubuntu16.04) con modo pasivo ( PASV
), pero no funciona. Sin embargo, funciona con EPSV
, no sé por qué. Busqué pero no encontré respuestas, ¿algún cuerpo puede ayudarme con esto?
1. configuración de vsftpd
anonymous_enable=NO
local_enable=YES
write_enable=YES
chroot_local_user=YES
pasv_enable=YES
pasv_min_port=13000
pasv_max_port=13100
port_enable=YES
pasv_address=[public ip address of AWS EC2 instance]
allow_writeable_chroot=YES
seccomp_sandbox=NO
2. AWS EC2 Firewall
3. Prueba a través de FireFTP
Con el modo PASV
, no puedo conectarme al servidor FTP, el registro es:
220 (vsFTPd 3.0.3)
USER sensor
331 Please specify the password.
PASS (password not shown)
230 Login successful.
CWD /
250 Directory successfully changed.
TYPE A
200 Switching to ASCII mode.
PASV
QUIT
Sin embargo, con esto funciona con EPSV
(con la casilla de verificación IPV6 seleccionada), el registro de la siguiente manera:
220 (vsFTPd 3.0.3)
USER sensor
331 Please specify the password.
PASS (password not shown)
230 Login successful.
PWD
257 "/" is the current directory
TYPE A
200 Switching to ASCII mode.
EPSV
229 Entering Extended Passive Mode (|||13082|)
LIST
150 Here comes the directory listing.
226 Directory send OK.
4. Prueba a través de Python ftplib
from ftplib import FTP
contents = []
ftp = FTP(host=xxx, timeout=3000)
ftp.login(user=xxx, passwd=xxx)
ftp.set_debuglevel(2)
ftp.retrlines("NLST", contents.append)
ftp.quit()
El registro de la siguiente manera:
*cmd* ''TYPE A''
*put* ''TYPE A/r/n''
*get* ''200 Switching to ASCII mode./n''
*resp* ''200 Switching to ASCII mode.''
*cmd* ''PASV''
*put* ''PASV/r/n''
*get* ''227 Entering Passive Mode (0,0,0,0,50,245)./n''
*resp* ''227 Entering Passive Mode (0,0,0,0,50,245).''
ConnectionRefusedError: [Errno 111] Connection refused