You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2019/04/01 20:42:31 UTC

[commons-vfs] branch trunk updated: [VFS-660] expose workaround for connecting to FTP server from different subnets in PASV mode (#35)

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 6cbadb1  [VFS-660] expose workaround for connecting to FTP server from different subnets in PASV mode (#35)
6cbadb1 is described below

commit 6cbadb1cbf0335ffff982de5a6c70be8b3b03196
Author: Liu Yubao <yu...@gmail.com>
AuthorDate: Tue Apr 2 04:42:26 2019 +0800

    [VFS-660] expose workaround for connecting to FTP server from different subnets in PASV mode (#35)
    
    In PASV mode, the FTP server returns its server IP (eg. pasv_address in vsftpd.conf),
    when clients are from different subnets through NAT, they expect different server IP.
    
    This patch exposes the workaround in commons-ftp into commons-vfs:
    * use EPSV mode instead of PASV mode, EPSV mode returns only server port
    * use PASV mode but overwrite the returned server IP with HostnameResolver
---
 .../vfs2/provider/ftp/FtpClientFactory.java        | 11 +++++
 .../provider/ftp/FtpFileSystemConfigBuilder.java   | 48 ++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftp/FtpClientFactory.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftp/FtpClientFactory.java
index 4b25c51..7da0815 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftp/FtpClientFactory.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftp/FtpClientFactory.java
@@ -26,6 +26,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.net.PrintCommandListener;
 import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.net.ftp.FTPClient.HostnameResolver;
 import org.apache.commons.net.ftp.FTPClientConfig;
 import org.apache.commons.net.ftp.FTPReply;
 import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
@@ -137,6 +138,16 @@ public final class FtpClientFactory {
                     client.setRemoteVerificationEnabled(remoteVerification.booleanValue());
                 }
 
+                final Boolean useEPSVwithIPv4 = builder.getUseEPSVwithIPv4(fileSystemOptions);
+                if (useEPSVwithIPv4 != null) {
+                    client.setUseEPSVwithIPv4(useEPSVwithIPv4.booleanValue());
+                }
+
+                final HostnameResolver resolver = builder.getPassiveNatWorkaroundStrategy(fileSystemOptions);
+                if (resolver != null) {
+                    client.setPassiveNatWorkaroundStrategy(resolver);
+                }
+
                 try {
                     // Set connect timeout
                     final Integer connectTimeout = builder.getConnectTimeout(fileSystemOptions);
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftp/FtpFileSystemConfigBuilder.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftp/FtpFileSystemConfigBuilder.java
index b1809d6..3705c81 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftp/FtpFileSystemConfigBuilder.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftp/FtpFileSystemConfigBuilder.java
@@ -17,7 +17,9 @@
 package org.apache.commons.vfs2.provider.ftp;
 
 import java.net.Proxy;
+import java.net.UnknownHostException;
 
+import org.apache.commons.net.ftp.FTPClient.HostnameResolver;
 import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
 import org.apache.commons.vfs2.FileSystem;
 import org.apache.commons.vfs2.FileSystemConfigBuilder;
@@ -46,6 +48,14 @@ public class FtpFileSystemConfigBuilder extends FileSystemConfigBuilder {
     private static final String SHORT_MONTH_NAMES = _PREFIX + ".SHORT_MONTH_NAMES";
     private static final String SO_TIMEOUT = _PREFIX + ".SO_TIMEOUT";
     private static final String USER_DIR_IS_ROOT = _PREFIX + ".USER_DIR_IS_ROOT";
+    private static final String USE_EPSV_WITH_IPV4 = _PREFIX + ".USE_EPSV_WITH_IPV4";
+    private static final String PASSIVE_NAT_WORKAROUND_STRATEGY = _PREFIX + ".PASSIVE_NAT_WORKAROUND_STRATEGY";
+    private static final HostnameResolver DUMMY_HOSTNAME_RESOLVER = new HostnameResolver() {
+        @Override
+        public String resolve(String hostname) throws UnknownHostException {
+            return hostname;
+        }
+    };
 
     private FtpFileSystemConfigBuilder() {
         super("ftp.");
@@ -154,6 +164,24 @@ public class FtpFileSystemConfigBuilder extends FileSystemConfigBuilder {
     }
 
     /**
+     * @param opts The FileSystemOptions.
+     * @return true if EPSV mode with IPv4 is set.
+     * @see #setUseEPSVwithIPv4
+     */
+    public Boolean getUseEPSVwithIPv4(final FileSystemOptions opts) {
+        return getBoolean(opts, USE_EPSV_WITH_IPV4);
+    }
+
+    /**
+     * @param opts The FileSystemOptions.
+     * @return the passive NAT workaround strategy.
+     * @see #setPassiveNatWorkaroundStrategy
+     */
+    public HostnameResolver getPassiveNatWorkaroundStrategy(final FileSystemOptions opts) {
+        return (HostnameResolver) this.getParam(opts, PASSIVE_NAT_WORKAROUND_STRATEGY);
+    }
+
+    /**
      * Gets the Proxy.
      *
      * @param opts The FileSystemOptions.
@@ -330,6 +358,26 @@ public class FtpFileSystemConfigBuilder extends FileSystemConfigBuilder {
     }
 
     /**
+     * Enter into extended passive mode with IPv4.
+     *
+     * @param opts The FileSystemOptions.
+     * @param useEPSVwithIPv4 true if extended mode with IPv4 should be used.
+     */
+    public void setUseEPSVwithIPv4(final FileSystemOptions opts, final boolean useEPSVwithIPv4) {
+        setParam(opts, USE_EPSV_WITH_IPV4, useEPSVwithIPv4 ? Boolean.TRUE : Boolean.FALSE);
+    }
+
+    /**
+     * Sets the passive NAT workaround strategy.
+     *
+     * @param opts The FileSystemOptions.
+     * @param resolver strategy to replace internal IP in passive mode.
+     */
+    public void setPassiveNatWorkaroundStrategy(final FileSystemOptions opts, final HostnameResolver resolver) {
+        setParam(opts, PASSIVE_NAT_WORKAROUND_STRATEGY, resolver != null ? resolver : DUMMY_HOSTNAME_RESOLVER);
+    }
+
+    /**
      * Sets the Proxy.
      * <p>
      * You might need to make sure that {@link #setPassiveMode(FileSystemOptions, boolean) passive mode} is activated.