Ubuntu – Tomcat & Java not listening on IPv6

ipv6javanetworkingtomcatUbuntu

We've got a webserver running Ubuntu 12.04 LTS, Tomcat 7 and Oracle Java. So far, we have been serving a web app on IPv4 address on ports 80 and 443 (80 redirects to 443).

I'm trying to make the tomcat serve same app on same ports also via IPv6. OS is configured for IPv6 correctly, it has its own IPv6 addresses with scope global.

What doesn't work is Tomcat/Java not listening on IPv6. Here is the output of netstat -tlpn:

tcp        0      0 0.0.0.0:2222            0.0.0.0:*               LISTEN      957/sshd
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      2686/java
tcp        0      0 0.0.0.0:5432            0.0.0.0:*               LISTEN      1058/postgres
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1243/master
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      2686/java
tcp        0      0 127.0.0.1:8005          0.0.0.0:*               LISTEN      2686/java
tcp6       0      0 :::2222                 :::*                    LISTEN      957/sshd
tcp6       0      0 :::5432                 :::*                    LISTEN      1058/postgres
tcp6       0      0 ::1:25                  :::*                    LISTEN      1243/master

As you can see, Java is listening only on tcp connections, while postgres and ssh accept also tcp6 connections on same ports as they do with IPv4.

I've found a property java.net.preferIPv4Stack=true in Tomcat startup script, but when I set this to false, tomcat started listening ONLY on tcp6 local, port 8005. I need it to also listen on :::443 and :::80. Also it disappeared from IPv4 connections, but i believe that ::: can bind both IP v4 and v6.

I should mention that I'm not a Java programmer, my responsibility is only the server itself. Also i don't want to do much experimenting, since this is a production server.

Any help is greatly appreciated! Cheers

–EDIT–

Here is the complete server.xml file, stripped of default comments:

<?xml version='1.0' encoding='utf-8'?>

<Server port="8005" shutdown="SHUTDOWN">

  <Listener className="org.apache.catalina.core.JasperListener" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>

    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  <Service name="Catalina">
    <Connector port="80" protocol="HTTP/1.1"
           connectionTimeout="20000"
           URIEncoding="UTF-8"
           redirectPort="443" />

<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true"
           maxThreads="150" scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS"
       keystoreFile="/etc/tomcat7/ssl/tomcat.keystore" 
       keystorePass="secretpass"/>

<Engine name="Catalina" defaultHost="localhost">

  <Realm className="org.apache.catalina.realm.LockOutRealm">

    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
           resourceName="UserDatabase"/>
  </Realm>

  <Host name="localhost"  appBase="webapps"
        unpackWARs="true" autoDeploy="true">

    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="localhost_access_log." suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />

  </Host>
</Engine>

Best Answer

After hours of research, I've found out that the problem is authbind. It can bind tomcat to ports lower than 1024 only for IPv4 and doesn't work for IPv6 (it should on newer kernels, but on this machine the 3.2 kernel is used).

When I turned of authbind in /etc/default/tomcat7 and modified my server.xml to listen on 8080, then redirect to 443 and listen on 8443, tomcat started listening on IPv6 like it should.

Redirecting the ports via iptables is also possible only for IPv4, since the ip6tables comes with support for nat and redirect only from kernel 3.7.

I then used a daemon called xinetd to redirect traffic from 80 to 8080 and from 443 to 8443. Now everything works as it should.