Wednesday, August 1, 2012

Work Arounds: Windows Firewall Blocking Java 7 FTP


It appears that Windows firewall is blocking IPv6 (JDK7) and not IPv4 (JDK6).

When attempting to FTP using a client recently upgraded to Java 7, your FTP will most likely fail with some error similar to the following:


java.net.SocketException: Permission denied: recv failed


ControlChannelIOException: Connection reset


JDK 7 brings support for IPv6 on Windows. If you are running an app using Java 7, when you attempt to connect to an IPv4 address the new Java 7 JRE will use an IPv4-mapped IPv6 address. This in itself is not a problem.  However, it looks like a Windows firewall bug. The firewall has a filter that examines client sockets to FTP servers in order to keep track of incoming data connections from the server. In the case of connecting to IPv4 destinations through IPv6 sockets, it seems to get confused and rejects the PORT and PASV commands - essentially closing the connection after each command is sent.

For any apps using Java for FTP, this is a HUGE problem.  Oracle has analysed the problem and have found that it seems to be a bug in Windows Firewall and/or the IPv6 stack. They managed to replicate the problem with a native C (i.e. non-Java app), so this is strong evidence that the bug is not in Java. They have informed Microsoft, but there is no telling when or if this will every be addressed.

More details can be found at? http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7077696


Work Arounds:

1) Add a firewall exception for the Java binary.

TESTED: Works with Windows Firewall - but not with Windows Firewall with Advanced Security (Windows 7 Ultimate)

2) Run the application with java vm argumnet -Djava.net.preferIPv4Stack=true (which disables IPv6 and uses AF_INET sockets exclusively)

- In eclipse, modify the run configuration or debug configuration and add the vm argument to the vm arguments

TESTED: This works in eclipse.

- In JNLP, do something like the following:
<j2se version="1.6.10+" href="http://java.sun.com/products/autodl/j2se"
      java-vm-args="-Djava.net.preferIPv4Stack=true"/>

TESTED: Does NOT work. Java WebStart does not support passing this vm argument to the client!!!

3) Disable stateful FTP inspection in the firewall (registry setting or netsh command) by executing the following at a command prompt:

  netsh advfirewall set global StatefulFTP disable

Note: Must be executed with administrator rights.

TESTED: This works!

4) Use a different firewall (Symantec firewall works correctly without any special configuration)

5) Disable Java 7 in your Java Control Panel.  Unfortunately this does not appear to work.  Even if you disable Java 7 in the control panel - apps are still launched using Java 7!

5) Roll back to Java 6 which does not use IPV6. Unfortunately, this is easier said than done. See notes below pertaining to Java Web Start Apps.

6) Switch to using HTTP for file transfers.


Special Note: Java 7 and Web Start Apps:

This is particularly a problem for Web Start apps as there is no way to pass the -Djava.net.preferIPv4Stack=true argument to the client and it is unreasonable to assume every client has admin rights and can run the script to turn off stateful FTP.

Worse, it appears that you can no longer specify the version of Java to use for your Web Start application.  In my testing, specifying an older version of Java (Java 6 release 10 or similar) simply failed to download and install the version.  If you specify a more recent version of Java (Oracle releases) you are informed that you should use the latest version of Java (i.e. 7) and if this doesn't work, you can opt to get the older version.  It doesn't explain how to obtain and enforce usage of the older version.

If anyone has a way to resolve this with Java Web Start apps, please let me know!



10 comments:

  1. Hi,

    j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se" java-vm args="-Djava.net.preferIPv4Stack=true"

    This worked for me on 32-bit Windows 7 with a Webstart-application.

    Thanks,
    You've saved me!

    ReplyDelete
  2. hi..Im student from Informatics engineering, this article is very informative, thanks for sharing :)

    ReplyDelete
  3. netsh advfirewall set global StatefulFTP disable
    just what i need
    thanks a lot

    ReplyDelete
  4. I've been told that this param can now be set for WebStart apps since Java 7 release 6 build 17: (source: http://stackoverflow.com/questions/9809919/how-to-set-preferipv4stack-property-for-jnlp-app)

    With the Java 7 Update 6 (b17) the list of secure properties has been updated. See Bug Report 716069 for further Details.

    You can include this setting by specifying the following line within the resource tag:

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. property name="java.net.preferIPv4Stack" value="true"

    ReplyDelete
  7. You can also try to modify the JNLP file and replace https with http. In my case it worked.

    ReplyDelete
    Replies
    1. Yes, that might resolve this issue - but now you are no longer encrypting your connection. These days it is good practice to have all connections secured - and soon Chrome will start identifying sites not using HTTPS as "insecure", which might frighten your users.

      Delete