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
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"
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!