diff --git a/client.go b/client.go index 779cd5e..442872b 100644 --- a/client.go +++ b/client.go @@ -149,6 +149,11 @@ type Config struct { // hung connections. DisableEPSV bool + // Ignores the returned remote host IP for PASV connections. Some FTP Servers are + // behind NAT, and return their internal IPs. This ignores the IP portion of the + // PASV response, using the control connection's IP instead. + IgnoreHost bool + // For testing convenience. stubResponses map[string]stubResponse } diff --git a/persistent_connection.go b/persistent_connection.go index 15f5d74..886dc6d 100644 --- a/persistent_connection.go +++ b/persistent_connection.go @@ -418,6 +418,20 @@ func (pconn *persistentConn) prepareDataConn() (func() (net.Conn, error), error) return nil, err } + // Some FTP servers are behind NAT themselves, and lie about their IP address. + if pconn.config.IgnoreHost { + pconn.debug("Ignoring PASV returned host %s", host) + _, remotePort, err := net.SplitHostPort(host) + if err != nil { + return nil, err + } + remoteHost, _, err := net.SplitHostPort(pconn.host) + if err != nil { + return nil, err + } + host = net.JoinHostPort(remoteHost, remotePort) + } + pconn.debug("opening data connection to %s", host) dc, netErr := net.DialTimeout("tcp", host, pconn.config.Timeout)