1

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>

  • could you add your server.xml conf and the startup logs? – Cédric Couralet Jun 18 '14 at 7:05
  • I've edited my question with a server.xml file. Where can I find startup logs? There is only access log in /var/lib/tomcat7/logs. Thank you! – j0hny Jun 18 '14 at 8:09
  • Did you try -Djava.net.preferIPv6Addresses=true (default is false) or setting ::1 to the adress attribute on the connector ? – Cédric Couralet Jun 18 '14 at 8:24
  • 1
    Try it on a test server that is a duplicate configuration of the production server. – Michael Hampton Jun 18 '14 at 13:18
  • @CédricC - I've tried suggested solutions on a test server (which doesn't have IPv6 connectivity to outside world, but that should not matter in this case, just for testing purposes). If I set preferIPv6Addresses to true, the result is the same as with only removing preferIPv4Addresses. When I set ::1 as an address in connector, the server stops listening on ports 80 and 443 and starts listening only on 8005 over IPv4. – j0hny Jun 20 '14 at 6:58
2

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.

  • As I mentioned in your other duplicate question, now you have no way to determine anyone's IP address. In this scenario it's best to use an actual web server such as apache httpd or nginx as a reverse proxy to tomcat. – Michael Hampton Jul 1 '14 at 12:33
  • First, sorry for duplicating the question, but i rather divided those two issues than making one question hard to read. As I stated it the other question's comment, it seems to me that making tomcat listen on 80 via IPv6 is impossible, so I had to come up with this workaroud, because it is a production server and messing around with apache would be hihghly risky. Also, xinetd listens on 80 and forwards request to 8080, so it will be possible to determine the IP address on this level. – j0hny Jul 4 '14 at 11:51
  • Sure, xinetd can tell you an IP address, but you can't easily correlate the IP address with an HTTP request. I think you have a serious misunderstanding of the risks involved, as this is far more risky than simply setting up httpd or nginx in front of Tomcat, both of which are easy and pretty painless. – Michael Hampton Jul 6 '14 at 13:54

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.