即使 pasv_address 正确,Vsftpd 也会使用 0,0,0,0 地址进行被动回复

即使 pasv_address 正确,Vsftpd 也会使用 0,0,0,0 地址进行被动回复

我在 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

但是,当我尝试使用 FTP 连接到服务器时,我收到以下警告,

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

如果你看到它进入被动模式

进入被动模式 (0,0,0,0,4,1)

我不知道这是从哪里来的(甚至不知道它是什么)。我也强制执行了 SELinux。

我在这里做错了什么?

谨致问候,V

答案1

在我看来,这看起来像是 vsftpd 中的一个错误。

从代码来看,0,0,0,0如果设置了公共pasv_address,并且服务器具有(本地)IPv6 地址,则 vsftpd 始终发送。

要解决此问题,请确保服务器不监听 IPv6 地址(这是默认行为,您可以通过设置来覆盖它listen_ipv6=YES):

listen_ipv6=NO
listen=YES

如果在 EC2 中可行,唯一的其他解决方案是删除私有 IPv6 地址。

或者使用另一个 FTP 服务器,例如FTPD软件


为了证明这确实是一个错误:

handle_pasvpostlogin.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");
  }
}

如果不是 IPv6(当设置 时,它永远不会是 IPv6),则返回vsf_sysutil_sockaddr_ipv6_v40 。s_p_sockaddrpasv_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];
}

恕我直言,代码是错误的。当从 中“自动检测” IP 地址时,它会工作(并且有意义)p_sess->p_local_addr,但当pasv_address使用该地址时会失败。

考虑将此问题报告给 vsftpd 的作者。

答案2

我在阿里云上托管的服务器上遇到了这个问题。

我通过在配置中禁用 listen_ipv6 并启用 listen 来解决了这个问题。

listen_ipv6=NO
listen=YES

我还使用以下方式指定了我的外部 IPpasv_address=

相关内容