我在 Ubuntu 18.04 上使用 pure-ftpd 1.0.46 作为服务器,使用 TLS 和 Let's Encrypt 签名的证书。我通过 WAN 连接和传输时没有遇到任何问题。我使用的是被动模式,端口已正确转发,并且我已将 pure-ftpd 配置为以其 WAN IP 进行响应。
但是,我无法通过 LAN 建立连接,因为它抱怨 TLS 连接终止。我尝试了几个客户端,它们都出现了某种超时错误。我怀疑问题的一部分可能是我的 DNS 设置。我有一个指向我的 WAN 的域名,我通常使用它来连接服务器。但是我的本地 DNS 服务器使用 ftp 机器的 LAN IP 进行响应。所以当我在家时,我的笔记本电脑与 192.168.1.2 建立 ftp 连接,但 PASV 响应是我的 WAN IP 74.xxx 理论上,我的路由器应该支持 NAT 环回,它将源自 LAN 并发往 WAN IP 的流量发送回其转发到的本地 IP。这似乎对 http 工作正常,并且我认为由于客户端启动了被动模式数据 tcp 连接,所以它也应该适用于它。但也许我遗漏了一些路由细节。这可能是问题所在吗?
客户端日志:
Status: Connecting to 192.168.1.2:21...
Status: Connection established, waiting for welcome message...
Trace: CFtpControlSocket::OnReceive()
Response: 220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
Response: 220-You are user number 9 of 50 allowed.
Response: 220-Local time is now 16:01. Server port: 21.
Response: 220-This is a private system - No anonymous login
Response: 220-IPv6 connections are also welcome on this server.
Response: 220 You will be disconnected after 15 minutes of inactivity.
Trace: CFtpLogonOpData::ParseResponse() in state 1
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 2
Command: AUTH TLS
Trace: CFtpControlSocket::OnReceive()
Response: 234 AUTH TLS OK.
Trace: CFtpLogonOpData::ParseResponse() in state 2
Status: Initializing TLS...
Trace: CTlsSocketImpl::Handshake()
Trace: CTlsSocketImpl::ContinueHandshake()
Trace: TLS handshake: About to send CLIENT HELLO
Trace: TLS handshake: Sent CLIENT HELLO
Trace: CTlsSocketImpl::OnSend()
Trace: CTlsSocketImpl::OnRead()
Trace: CTlsSocketImpl::ContinueHandshake()
Trace: CTlsSocketImpl::OnRead()
Trace: CTlsSocketImpl::ContinueHandshake()
Trace: TLS handshake: Received SERVER HELLO
Trace: TLS handshake: Processed SERVER HELLO
Trace: CTlsSocketImpl::OnRead()
Trace: CTlsSocketImpl::ContinueHandshake()
Trace: TLS handshake: Received CERTIFICATE
Trace: TLS handshake: Processed CERTIFICATE
Trace: TLS handshake: Received SERVER KEY EXCHANGE
Trace: TLS handshake: Processed SERVER KEY EXCHANGE
Trace: TLS handshake: Received SERVER HELLO DONE
Trace: TLS handshake: Processed SERVER HELLO DONE
Trace: TLS handshake: About to send CLIENT KEY EXCHANGE
Trace: TLS handshake: Sent CLIENT KEY EXCHANGE
Trace: TLS handshake: About to send FINISHED
Trace: TLS handshake: Sent FINISHED
Trace: CTlsSocketImpl::OnRead()
Trace: CTlsSocketImpl::ContinueHandshake()
Trace: TLS handshake: Received NEW SESSION TICKET
Trace: TLS handshake: Processed NEW SESSION TICKET
Trace: TLS handshake: Received FINISHED
Trace: TLS handshake: Processed FINISHED
Trace: TLS Handshake successful
Trace: Protocol: TLS1.2, Key exchange: ECDHE-RSA, Cipher: AES-256-GCM, MAC: AEAD
Status: Verifying certificate...
Status: TLS connection established.
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 5
Command: USER *****
Trace: CTlsSocketImpl::OnRead()
Trace: CFtpControlSocket::OnReceive()
Response: 331 User ******* OK. Password required
Trace: CFtpLogonOpData::ParseResponse() in state 5
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 5
Command: PASS **********
Trace: CTlsSocketImpl::OnRead()
Trace: CFtpControlSocket::OnReceive()
Response: 230 OK. Current directory is /
Trace: CFtpLogonOpData::ParseResponse() in state 5
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 9
Command: OPTS UTF8 ON
Trace: CTlsSocketImpl::OnRead()
Trace: CFtpControlSocket::OnReceive()
Response: 200 OK, UTF-8 enabled
Trace: CFtpLogonOpData::ParseResponse() in state 9
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 10
Command: PBSZ 0
Trace: CTlsSocketImpl::OnRead()
Trace: CFtpControlSocket::OnReceive()
Response: 200 PBSZ=0
Trace: CFtpLogonOpData::ParseResponse() in state 10
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 11
Command: PROT P
Trace: CTlsSocketImpl::OnRead()
Trace: CFtpControlSocket::OnReceive()
Response: 200 Data protection level set to "private"
Trace: CFtpLogonOpData::ParseResponse() in state 11
Status: Logged in
Trace: Measured latency of 3 ms
Trace: CFtpControlSocket::ResetOperation(0)
Trace: CControlSocket::ResetOperation(0)
Trace: CFtpLogonOpData::Reset(0) in state 14
Trace: CFileZillaEnginePrivate::ResetOperation(0)
Status: Retrieving directory listing...
Trace: CControlSocket::SendNextCommand()
Trace: CFtpListOpData::Send() in state 0
Trace: CFtpChangeDirOpData::Send() in state 0
Trace: CFtpChangeDirOpData::Send() in state 1
Command: PWD
Trace: CTlsSocketImpl::OnRead()
Trace: CFtpControlSocket::OnReceive()
Response: 257 "/" is your current location
Trace: CFtpChangeDirOpData::ParseResponse() in state 1
Trace: CFtpControlSocket::ResetOperation(0)
Trace: CControlSocket::ResetOperation(0)
Trace: CFtpChangeDirOpData::Reset(0) in state 1
Trace: CFtpListOpData::SubcommandResult(0) in state 1
Trace: CControlSocket::SendNextCommand()
Trace: CFtpListOpData::Send() in state 2
Trace: CFtpRawTransferOpData::Send() in state 1
Command: TYPE I
Trace: CTlsSocketImpl::OnRead()
Trace: CFtpControlSocket::OnReceive()
Response: 200 TYPE is now 8-bit binary
Trace: CFtpRawTransferOpData::ParseResponse() in state 1
Trace: CControlSocket::SendNextCommand()
Trace: CFtpRawTransferOpData::Send() in state 2
Command: PASV
Trace: CTlsSocketImpl::OnRead()
Trace: CFtpControlSocket::OnReceive()
Response: 227 Entering Passive Mode (75,85,*,*,46,161)
Trace: CFtpRawTransferOpData::ParseResponse() in state 2
Trace: CControlSocket::SendNextCommand()
Trace: CFtpRawTransferOpData::Send() in state 4
Trace: Destination IP of data connection does not match peer IP of control connection. Not binding source address of data connection.
Command: MLSD
Trace: CTransferSocket::OnConnect
Trace: CTlsSocketImpl::Handshake()
Trace: Trying to resume existing TLS session.
Trace: CTlsSocketImpl::ContinueHandshake()
Trace: TLS handshake: About to send CLIENT HELLO
Trace: TLS handshake: Sent CLIENT HELLO
Trace: CTlsSocketImpl::OnSend()
Trace: CTlsSocketImpl::OnSend()
Trace: CTlsSocketImpl::OnRead()
Trace: CTlsSocketImpl::ContinueHandshake()
Trace: CTlsSocketImpl::OnRead()
Trace: CTlsSocketImpl::ContinueHandshake()
Trace: CTlsSocketImpl::Failure(-110)
Error: GnuTLS error -110: The TLS connection was non-properly terminated.
Status: Server did not properly shut down TLS connection
Trace: CTlsSocketImpl::OnSocketEvent(): close event received
Trace: CTransferSocket::OnClose(106)
Error: Transfer connection interrupted: ECONNABORTED - Connection aborted
Trace: CTransferSocket::TransferEnd(3)
Trace: CFtpControlSocket::TransferEnd()
Trace: CFtpControlSocket::ResetOperation(10)
Trace: CControlSocket::ResetOperation(10)
Trace: CFtpRawTransferOpData::Reset(10) in state 6
Trace: CFtpControlSocket::ResetOperation(10)
Trace: CControlSocket::ResetOperation(10)
Trace: CFtpListOpData::Reset(10) in state 3
Error: Directory listing aborted by user
Trace: CFileZillaEnginePrivate::ResetOperation(10)
Status: Disconnected from server
Trace: CRealControlSocket::DoClose(66)
Trace: CControlSocket::DoClose(66)
Trace: CFtpControlSocket::ResetOperation(66)
Trace: CControlSocket::ResetOperation(66)
Trace: CFileZillaEnginePrivate::ResetOperation(66)
Trace: CRealControlSocket::DoClose(66)
Trace: CControlSocket::DoClose(66)
Trace: CControlSocket::DoClose(66)
Trace: CFileZillaEnginePrivate::ResetOperation(0)
答案1
Destination IP of data connection does not match peer IP of control connection. Not binding source address of data connection.
这是非常明确的。客户端不会接受通过本地 IP 建立的控制连接和通过其他 IP 建立的数据连接。
最好的解决方案应该是只更改本地 DNS 以提供公共 IP 地址。如果可行,那应该不会有任何损害。