Tomcat 和 Java 未监听 IPv6

Tomcat 和 Java 未监听 IPv6

我们有一个运行 Ubuntu 12.04 LTS、Tomcat 7 和 Oracle Java 的 Web 服务器。到目前为止,我们一直在 IPv4 地址的端口 80 和 443(80 重定向到 443)上提供 Web 应用程序。

我正在尝试让 tomcat 通过 IPv6 在相同端口上为相同应用程序提供服务。操作系统已正确配置 IPv6,它有自己的 IPv6 地址,范围为全局。

不起作用的是 Tomcat/Java 没有监听 IPv6。以下是 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

如您所见,Java 仅监听 tcp 连接,而 postgres 和 ssh 也接受与 IPv4 相同的端口上的 tcp6 连接。

我在 Tomcat 启动脚本中发现了一个属性 java.net.preferIPv4Stack=true,但是当我将其设置为 false 时,tomcat 开始仅在 tcp6 本地端口 8005 上监听。我需要它还监听 :::443 和 :::80。它也从 IPv4 连接中消失了,但我相信 ::: 可以绑定 IP v4 和 v6。

我应该说明一下,我不是 Java 程序员,我的职责只是服务器本身。另外,我不想做太多实验,因为这是一个生产服务器。

非常感谢您的帮助!谢谢

- 编辑 -

以下是完整的 server.xml 文件(删除了默认注释):

<?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>

答案1

经过几个小时的研究,我发现问题出在 authbind 上。它只能将 tomcat 绑定到 IPv4 的 1024 以下端口,而不能用于 IPv6(在较新的内核上应该可以,但这台机器使用的是 3.2 内核)。

当我在 /etc/default/tomcat7 中关闭 authbind 并修改我的 server.xml 以监听 8080,然后重定向到 443 并监听 8443 时,tomcat 开始像它应该的那样监听 IPv6。

通过 iptables 重定向端口也仅适用于 IPv4,因为 ip6tables 仅从内核 3.7 开始支持 nat 和重定向。

然后,我使用名为 xinetd 的守护进程将流量从 80 重定向到 8080,从 443 重定向到 8443。现在一切都正常运行。

相关内容