我在 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_pasv
在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");
}
}
如果不是 IPv6(当设置 时,它永远不会是 IPv6),则返回vsf_sysutil_sockaddr_ipv6_v4
0 。s_p_sockaddr
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];
}
恕我直言,代码是错误的。当从 中“自动检测” IP 地址时,它会工作(并且有意义)p_sess->p_local_addr
,但当pasv_address
使用该地址时会失败。
考虑将此问题报告给 vsftpd 的作者。
答案2
我在阿里云上托管的服务器上遇到了这个问题。
我通过在配置中禁用 listen_ipv6 并启用 listen 来解决了这个问题。
listen_ipv6=NO
listen=YES
我还使用以下方式指定了我的外部 IPpasv_address=