问题现象:
linux下 yum 方式安装 Tomcat 后配置https,定义端口为 443 后无法正常启动服务
1. 定义端口为默认的 8443 可以正常启动服务和监听端口:
root@centos7 ~ # vim /etc/tomcat/server.xml
protocol="HTTP/1.1"
maxThreads="150"
SSLEnabled="true"
scheme="https"
secure="true"
clientAuth="false"
keystoreFile="/etc/tomcat/test.seekerhcl.cn.jks"
keystorePass="123456"
ciphers="TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
sslProtocol="TLS" />
root@centos7 ~ # rpm -q tomcat
tomcat-7.0.76-3.el7_4.noarch
root@centos7 ~ # systemctl start tomcat.service
root@centos7 ~ # netstat -anpt | grep java
tcp 0 0 0.0.0.0:8443 0.0.0.0:* LISTEN 6168/java
tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 6168/java
tcp 0 0 0.0.0.0:8009 0.0.0.0:* LISTEN 6168/java
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 6168/java
root@centos7 ~ #
2. 定义 https 端口443 不可以正常监听对应端口:
root@centos7 ~ # vim /etc/tomcat/server.xml
protocol="HTTP/1.1"
maxThreads="150"
SSLEnabled="true"
scheme="https"
secure="true"
clientAuth="false"
keystoreFile="/etc/tomcat/test.seekerhcl.cn.jks"
keystorePass="123456"
ciphers="TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
sslProtocol="TLS" />
root@centos7 ~ # systemctl restart tomcat.service
root@centos7 ~ # netstat -anpt | grep java
tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 49091/java
tcp 0 0 0.0.0.0:8009 0.0.0.0:* LISTEN 49091/java
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 49091/java
问题分析:
查看日志文件发现以下错误,原来是权限问题,紧接着我们通过 ps 查看进程信息会发现程序用户是tomcat,因为 linux 下非 root
用户不能打开1024以下的端口,所以问题就比较清楚了
Caused by: java.net.BindException: Permission denied (Bind failed) :443
root@centos7 ~ # cat /var/log/tomcat/catalina.2018-04-07.log
Apr 07, 2018 12:29:48 AM org.apache.catalina.core.StandardService initInternal
SEVERE: Failed to initialize connector [Connector[HTTP/1.1-443]]
org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-443]]
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
at org.apache.catalina.core.StandardService.initInternal(StandardService.java:560)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:840)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
at org.apache.catalina.startup.Catalina.load(Catalina.java:642)
at org.apache.catalina.startup.Catalina.load(Catalina.java:667)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:253)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:427)
Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:980)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
... 12 more
Caused by: java.net.BindException: Permission denied (Bind failed) :443
at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:413)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:715)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:452)
at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:119)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:978)
... 13 more
Caused by: java.net.BindException: Permission denied (Bind failed)
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.(ServerSocket.java:237)
at java.net.ServerSocket.(ServerSocket.java:181)
at javax.net.ssl.SSLServerSocket.(SSLServerSocket.java:136)
at sun.security.ssl.SSLServerSocketImpl.(SSLServerSocketImpl.java:113)
at sun.security.ssl.SSLServerSocketFactoryImpl.createServerSocket(SSLServerSocketFactoryImpl.java:87)
at org.apache.tomcat.util.net.jsse.JSSESocketFactory.createSocket(JSSESocketFactory.java:256)
at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:400)
root@centos7 ~ # ps aux | grep java
tomcat 3921 0.3 3.1 3585548 120932 ? Ssl 00:29 0:02 /usr/lib/jvm/jre/bin/java -classpath /usr/share/tomcat/bin/bootstrap.jar:/usr/share/tomcat/bin/tomcat-juli.jar:/usr/share/java/commons-daemon.jar -Dcatalina.base=/usr/share/tomcat -Dcatalina.home=/usr/share/tomcat -Djava.endorsed.dirs= -Djava.io.tmpdir=/var/cache/tomcat/temp -Djava.util.logging.config.file=/usr/share/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager org.apache.catalina.startup.Bootstrap start
root 5054 0.0 0.0 110376 896 pts/0 S+ 00:40 0:00 grep --color=auto java
解决方案:
tomcat https 端口依旧监听在大于 1024 的端口上,使用 iptables 来做个转换,这样访问 https 时我们就不用手动在域名后面写端口号了
root@centos7 ~ # iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443