4

I have the following config in vsftpd

listen_ipv6=YES
allow_writeable_chroot=YES
seccomp_sandbox=NO
pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES
pasv_enable=YES
pasv_min_port=1024
pasv_max_port=1048
pasv_address=<Elastic ip from amazon aws ec2 instance>
pasv_promiscuous=YES

However, when trying to connect to server using FTP I get this following warning,

Status: Retrieving directory listing...
Command: PWD
Response: 257 "/"
Command: TYPE I
Response: 200 Switching to Binary mode.
Command: PASV
Response: 227 Entering Passive Mode (0,0,0,0,4,1).
Status: Server sent passive reply with unroutable address. Using server address instead.
Command: LIST
Response: 150 Here comes the directory listing.
Response: 226 Directory send OK.
Directory listing of "/" successful

If you see it enters the passive mode with this

Entering Passive Mode (0,0,0,0,4,1)

I have no idea where is this coming from (or even what is it). I have SELinux enforcing as well.

What am I doing wrong here ?

Kind Regards, V

0

2 Answers 2

11

It looks like a bug in vsftpd to me.

From the code, it looks like, vsftpd always sends the 0,0,0,0, if the public pasv_address is set, and the server has a (local) IPv6 address.

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

listen_ipv6=NO
listen=YES

The only other solution is removing the 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.

5
  • I don't know if this answer is right or not, but you should get credit for even caring enough to look. It's ftp and no longer the 90s.
    – user143703
    Dec 16, 2016 at 8:16
  • 1
    This saved me after 4 hours of research. Thanks!!
    – paqash
    Jan 21, 2019 at 16:57
  • 1
    Thank you so much. Trying to figure this out was driving me mad setting up GitHub FTP Action to EC2 instance. This should be the accepted answer. Oct 7, 2020 at 20:51
  • This seems like something they should have fixed years ago. Oct 8, 2020 at 15:19
  • It can be silly mistake like I was doing (new to linux). We need to Restart service after making changes to config file! So make changes as suggested by Martin Prikry and then restart service: sudo service vsftpd restart Jun 16 at 15:55
3

I had this problem with a server hosted on Aliyun.

I solved it by disabling listen_ipv6 and enabling listen in the config.

listen_ipv6=NO
listen=YES

I also specified my external IP using pasv_address=

1
  • I think the main key of this solution is pasv_address attribute without this it will not works btw thanks for sharing this.
    – asmath
    May 16, 2021 at 4:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.