vsftpd returns 0,0,0,0 in response to PASV

匿名 (未验证) 提交于 2019-12-03 08:50:26

问题:

I set up an FTP server on AWS EC2 (Ubuntu16.04) with passive mode (PASV), but it doesn't work. However, it works with EPSV, don't know why. I searched around but find no answers, any body can help me with this?

1. vsftpd config

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. Test through FireFTP

With PASV mode, I cannot connect to FTP server, the log is:

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 

However, with it works with EPSV (with IPV6 checkbox selected), the log as below:

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. Test through 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() 

The log as below:

*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 

回答1:

It looks like a bug in vsftpd to me.

From the code it looks like, it will always send the 0,0,0,0, if the public pasv_address is set, but the server has a (local) IPv6 address.

To fix this, make sure the server does not listen on IPv6 address (what is a default behavior, which you are overriding by setting listen_ipv6=YES):

listen_ipv6=NO listen=YES 

The only other solution is removing a private IPv6 address, if it is possible in EC2.

Or use another FTP server, e.g. ProFTPD.


To prove that this is indeed a bug:

handle_pasv in 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");   } } 

where the vsf_sysutil_sockaddr_ipv6_v4 returns 0, if the s_p_sockaddr is not IPv6, what it never is, when the pasv_address is set.

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, the code is wrong. It works (and makes sense), when the IP address is "autodetected" from p_sess->p_local_addr, but fails, when the pasv_address address is used.

Consider reporting this to the author of vsftpd.


Keeping an original explanation of the PASV vs. EPSV:

Just to explain the difference between the PASV and the EPSV: The PASV returns an IP address in the response. That information is in 99.9% redundant. And it commonly causes problems, when the server is not aware of its external IP address.

The EPSV was introduced later than the PASV, when it was clear that the IP address presence in the response is problematic. So with the EPSV, only a port number is included. And the client connects to the FTP server IP address implicitly.

If the server really returns 0,0,0,0 in a response to the PASV command, it's clear why the client cannot connect to the server, when the PASV is used.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!