一、前言
前段时间,做了一个新项目。在项目打包时,将jdk和tomcat打包到版本包里了,还贴心的附上了在linux环境安装以及配置教程,结果被怼了。
一则是说不需要安装jdk,只需要安装jre,即可让项目跑起来。jdk是java开发工具,jre是java运行环境,jdk是包含jre的。安装过jdk的都知道,在安装jdk的过程中,还会单独让装一个jre的,其实这个地方的jre不用安装,因为jdk里面是包含jre的,在配置环境变量的时候,也通常不会去配置到单独安装的jre的,而是直接指到jdk下的jre。
一则是说这个tomcat不安全,需要给tomcat安全加固和优化。这不就涉及到知识盲点了吗?
二、tomcat安全加固
1.关闭shutdown端口
在server.xml中一般配置有三个端口,一个是shutdown的端口,监听停止tomcat的命令,一个是http的监听端口,再一个是AJP的监听端口。
shutdown的默认配置如下:
<Server port="8005" shutdown="SHUTDOWN">
那么当其他用户能telnet到这个ip的端口,就可以使用SHUTDOWN来停止tomcat服务。
启动tomcat如下:
在windown10中默认telnet服务是不开启的,想要尝试的同学需要先开启telnet服务。
在cmd中telnet命令如下,点击确定,在Telnet新窗口输入SHUTDOWN,即可看到tomcat服务已关闭。
那么就需要修改默认的端口以及关闭tomcat的命令。例子如下:
<Server port="18000" shutdown="STOP123">
2.删除ROOT等预置项目
在webapps下有tomcat预先放置的项目。如下图:
这些项目使得我访问http://127.0.0.1:8080就可以访问tomcat的管理等页面。
删除掉之后,再次访问这个路径,就会显示报错。
3.关闭AJP端口
当用不上ajp端口时,需要将如下代码注释掉。
<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
4.注释tomcat用户配置
这个用户配置在tomcat-users.xml中。如下:
5.开启tomcat的access日志
修改conf/server.xml配置,开启access日志,在logs目录下会生成localhost_access_log.txt,记录每次请求。
如下图:
6.禁止列出目录
修改conf/web.xml的listings为false
其实上述的大多数配置,在tomcat9中已经配置,所以为了安全,请使用高版本tomcat.
7.最小权限
安装使用tomcat时,不要使用root用户。同时bin目录下的sh脚本权限要限制在最小范围。
8.使用https
tomcat默认的使用的是http,需要修改为使用https的connector。
在conf/server.xml中配置https如下:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
minSpareThreads="5" maxSpareThreads="75" enableLookups="true" disableUploadTimeout="true"
acceptCount="100" maxThreads="200" SSLEnabled="true" scheme="https" secure="true"
keystoreFile="conf/test.keystore" keystorePass="123456" keyAlias="ykqtest"
clientAuth="false" sslProtocol="TLS" />
keyAlias为生成证书的时的别名。
keystoreFile为证书路径,我这个文件是放在了conf目录下。
keystorePass为证书密码。
与此同时需要注意http的redirectPort端口为https的端口号,这样访问http的端口就会重定向到https。
附上生成证书的命令:
keytool -genkey -validity 36000 -alias ykqtest -keyalg RSA -keystore d:\test.keystore
36000这个数字是以天为单位,表示证书有效期为100年。
ykqtest是证书的别名。
生成证书后,将keystore文件复制到tomcat的conf目录下即可。
9.强制https访问
还需要修改conf/web.xml,使得必须使用https端口才能访问,配置如下:
<login-config>
·<!-- Authorization setting for SSL -->
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Client Cert Users-only Area</realm-name>
</login-config>
<security-constraint>
<!-- Authorization setting for SSL -->
<web-resource-collection >
<web-resource-name >SSL</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
增加了上面这个配置后,假如关闭了https的connector,只保留http的connector,也无法通过http访问服务,因为这个地方强制必须使用https来访问。
10.禁止不安全的请求方式
下列http的不安全的请求方式配置在web.xml中,禁止使用,只允许GET和POST方式
<security-constraint>
<web-resource-collection>
<url-pattern>/*</url-pattern>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
<http-method>HEAD</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
</web-resource-collection>
<auth-constraint>
</auth-constraint>
</security-constraint>
11.加密证书私钥
上面证书的密钥是以明文的方式存储的,还需要将密钥以加密的方式配置在server.xml文件中。
先建立一个maven项目,来重写org.apache.coyote.http11.Http11NioProtocol(上述Connector配置的http协议类)中设置证书秘钥的方法。
1)pom.xml
<!-- 这两个依赖是Http11NioProtocol类依赖的jar包 -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-juli</artifactId>
<version>9.0.36</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.8</version>
</dependency>
2)重写Http11NioProtocol类
package com.ykq.util;
import java.util.Base64;
import java.util.Base64.Decoder;
import org.apache.coyote.http11.Http11NioProtocol;
/**
* @author YKQ
* 重写Http11NioProtocol类
*/
public class ReSetHttpProtocol extends Http11NioProtocol {
/**
* 重写设置证书密码的方法
*/
public void setKeystorePass(String certificateKeystorePassword) {
// 原先的方法
//super.setKeystorePass(certificateKeystorePassword);
// 这里简单使用一个base64加解密来存储证书密码,实际环境可以使用AES方式加解密
Decoder decoder = Base64.getDecoder();
String password = new String(decoder.decode(certificateKeystorePassword));
super.setKeystorePass(password);
}
}
3)导出jar包,将其放入tomcat的lib目录下
4)重新配置https
<Connector port="8443" protocol="com.ykq.util.ReSetHttpProtocol"
minSpareThreads="5" maxSpareThreads="75" enableLookups="true" disableUploadTimeout="true"
acceptCount="100" maxThreads="200" SSLEnabled="true" scheme="https" secure="true"
keystoreFile="conf/test.keystore" keystorePass="MTIzNDU2" keyAlias="ykqtest"
clientAuth="false" sslProtocol="TLS" />
上面的com.ykq.util.ReSetHttpProtocol,就是重写的Http11NioProtocol。
keystorePass=“MTIzNDU2” 配置的是加密后的证书秘钥.
12.配置sessionId的长度
在公司的红线要求中有一条,sessionId的长度必须是48位以上。那么需要在context.xml中配置如下:
<Manager>
<SessionIdGenerator sessionIdLength = "24"/>
</Manager>
这个地方配置长度24,生成的sessionId,即可达到48位。如下图: