[TOC]
修订控制页 版本 |修订日期 |修订人 |修订摘要 —|—|—|— 1.0| 2019年9月10日 09点00分 |WeiyiGeek |初稿
1.引言 1.1 目的 为了更好的指导部署Tomcat应用容器,保证服务的安全稳定高性能的运行,需要对其进行加固和优化; 本次进行Tomcat容器调优加固主要从以下几个部分:
1.2 目标范围 本文档仅供内部使用,禁止外传,帮助研发人员,运维人员对系统长期稳定的运行提供技术文档参考。
1.3 读者对象 1) 项目经理 2) 开发人员 3) 测试人员 4) 运维人员 5) 相关领导
2.参考说明 2.1 帮助参考 Apache Tomcat是美国Apache软件基金会的一款轻量级Web应用服务器,该程序实现了对Servlet和JSP的支持。 目前是Apache开源软件组织的一个软件项目它的官网 :http://tomcat.apache.org , 在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试 JSP 程序的首选,默认端口8080。
Tomcat8配置帮助文档: http://tomcat.apache.org/tomcat-8.0-doc/config/ Security Manage: http://tomcat.apache.org/tomcat-8.0-doc/security-manager-howto.html
Tomcat初始目录结构1 2 3 4 5 6 7 8 9 10 11 12 13 /usr/local /tomcat ├── bin ├── conf ├── lib ├── logs ├── temp ├── webapps │ ├── docs │ ├── examples │ ├── host-manager │ ├── manager │ └── ROOT └── work
Tomcat全局配置目录结构:1 2 3 4 5 6 7 8 9 10 11 [root@master conf] ├── catalina.policy ├── catalina.properties ├── context.xml ├── jaspic-providers.xml ├── jaspic-providers.xsd ├── logging.properties ├── server.xml ├── tomcat-users.xml ├── tomcat-users.xsd └── web.xml
Tomcat的JavaWeb应用的组成结构:1 2 3 4 5 6 7 8 mail--- |---- |---- |---------classes目录 |---------lib目录 |---------conf目录 |---------web.xml
Tomcat默认开发的端口介绍:
8005:用于SHUTDOWN指令来关闭Tomcat时使用;
8009:用于Apache连接Tomcat时候专用端口采用AJP协议;
8080:用于HTTP协议远程访问端口即Web页面访问端口;
3.内核优化 需要进行调整的内核参数1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 cat >> /etc/sysctl.conf << EOF net.core.netdev_max_backlog = 32768 net.core.somaxconn = 32768 net.core.rmem_default = 8388608 net.core.wmem_default = 8388608 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.ip_local_port_range = 1024 65535 net.ipv4.route.gc_timeout = 100 net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_keepalive_time = 1200 net.ipv4.tcp_timestamps = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_syn_retries = 1 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_mem = 94500000 915000000 927000000 net.ipv4.tcp_max_orphans = 3276800 net.ipv4.tcp_max_syn_backlog = 65535 EOF sysctl -p
4.性能优化 描述: 由于Tomcat的运行依赖于JVM,从虚拟机的角度我们把Tomcat的调整分为外部环境调优
和自身调优
两类来描述。
4.1 外部调优 主要调整Tomcat运行环境的操作系统参数和运行Tomcat的java虚拟机参数。
(1)JAVA虚拟机性能优化 Tomcat需要依赖Java虚拟机运行,根据客户选用的主机的操作系统选择对应的JDK的版本建议使用最新的版本。 Tomcat的使用内存配置实质上是JVM的内存配置编辑 catalina.[sh / bat]
配置文件,注意这里区分Windows和Linux;
jvm 优化是我们要去调配置、调代码
,需要充分利用JVM底层的内容进行设置, 注意整个堆heap
大小 = 年轻代大小 + 年老代大小 + 持久代大小
之和。
(1) 尽可能将对象预留在新生代,减少老年代GC的次数(通常老年回收起来比较慢)
(2) 实际工作中,通常将堆的初始值和最大值设置相等,这样可以减少程序运行时进行的垃圾回收次数和空间扩展,从而提高程序性能。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
(3) 年轻代:刚创建完对象放到里面去不用时等待jvm移除(可根据创建时间)。
(4) 年老代:当空间不够时则将创建最早的对象挪过去。当又需要用到这个对象时,又将其挪入年轻但,挪来挪去影响效率。
JVM调优之设置Java虚拟机运行生产环境参数配置:
-server | Server 模式启动应用慢但是极大程度提高运行性能,特别是在稳定期过后。 -client | Cliet 模式启动应用快。
-Xms2g | 堆的初始可用
内存大小,单位 m、g 。如 -Xms2g
-Xmx2g | 堆的最大可用
内存大小,单位 m、g 。如 -Xmx2g
(设置与Xms相同的内存大小 , 为减少程序运行时进行的垃圾回收次数和空间扩展
) -Xmn256m | 设置年轻代内存大小,单位 m、g 。 如 -Xmn256m
(此值对系统性能影响较大,推荐配置为整个堆的 3/8 或 1/4,一般在增大年轻代内存后,也会将会减小年老代大小。
) -Xss128k | 设置每个线程的栈Stack大小,单位 m、g 。如 -Xss128k
(越大我们能递归调用的方法数量越多,但是空间越大创建时间越长
)。 每个线程栈大小为1M以前每个线程栈大小为256K, 更具应用的线程所需内存大小进行调整, 在相同物理内存下,减小这个值能生成更多的线程。 但是操作系统对一个进程内的线程数还是有限制的不能无限生成,经验值在3000~5000左右可以在Linux内核中进行配置。 -XX:NewRatio=4 | 设置年轻代(包括Eden和两个Survivor区
)与年老代的比值(除去持久代
)。如此时则年轻代与年老代所占比值为1:4, 年轻代占整个堆栈的 1/5
。 -XX:SurvivorRatio=4 | 设置年轻代中Eden区与Survivor区的大小比值。如Eden区与两个Survivor区的比值为4:2, 一个Survivor区占整个年轻代的1/6
。 -XX:PermSize=16m | 设置持久代大小为16m, 持久代一般固定的内存大小为64m。 (越大加载的类阅越多
) | support was removed in 8.0 -XX:MaxPermSize=16m | 设置最大持久代大小为16m, 默认是物理内存的1/4最大1024m。| support was removed in 8.0 -XX:MaxTenuringThreshold=0 | 设置垃圾最大年龄存活。 如果设置为0的话则年轻代对象不经过Survivor区,直接进入年老代, 对于年老代比较多的应用可以提高效率。 如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
垃圾回收策略调优
描述: 我们都知道Java虚拟机都有默认的垃圾回收机制,但是不同的垃圾回收机制的效率是不同的,正是因为这点我们才经常对Java虚拟机的垃圾回收策略进行相应的调整。
Tips : Java虚拟机的垃圾回收策略一般分为串行收集器、并行收集器和并发收集器
。
-XX:+UseSerialGc | 代表垃圾回收策略为串行收集器,即在整个扫描和复制过程采用单线程的方式来进行,适用于单CPU、新生代空间较小及对暂停时间要求不是非常高的应用上,是client级别默认的GC方式,主要在JDK1.5之前的垃圾回收方式。 | |
-XX:+UseParallelGC | 代表垃圾回收策略为并行收集器(吞吐量优先)
,即在整个扫描和复制过程采用多线程的方式来进行,适用于多CPU、对暂停时间要求较短的应用上,是server级别默认采用的GC方式。此配置仅对年轻代有效。该配置只能让年轻代使用并发收集,而年老代仍旧使用串行收集。| | -XX:ParallelGCThreads=4 | 配置并行收集器(Gc)的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。 | | -XX:+UseParallelGCThreads=8 | 并行收集器线程数同时有多少个线程进行垃圾回收一般与CPU数量相等 | support was removed in 8.0 -XX:+UseParallelOldGC | 配置年老代垃圾收集方式为并行收集, JDK6.0支持对年老代并行收集。| | -XX:MaxGCPauseMillis=100 | 设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。| | -XX:+UseAdaptiveSizePolicy | 设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例,以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时一直打开。 | |
-XX:+UseConcMarkSweepGC | 代表垃圾回收策略为并发收集器 |
-XX:PrintGC | 每次触发GC的时候打印相关日志 | | -XX:+PrintGCDetails | 更详细的GC日志 | | -XX:+HeapDumpOnOutOfMemoryError| 堆异常报错输出 | | -XX:HeapDumpPath=path | 设置在dump heap时将文件dump到哪里。默认是当前目录下 java_pidpid.hprof这样形式的文件。| | -XX:+UseCMSCompactAtFullCollection | 开启内存空间压缩和整理,防止过多内存碎片 | tomcat 8.0 报警告 Headless=true | windows系统可不用设置,适用于Linux系统与图形操作有关,如生成验证码含义是当前的是无显示器的服务器,应用中如果获取系统显示有关的参数会抛出异常 || -Dfile.encoding=UTF-8 |设置字符集避免日志中出现乱码 | | -Dsun.jnu.encoding=UTF-8 | 设置字符集避免日志中出现乱码 || -Duser.timezone=GMT+08 |时区设置 ||
Tomcat 默认可以使用的内存为128MB,在较大型的应用项目中内存是不够的所以需要调大,一般设置初始化内存为256MB,可以使用的最大内存为512MB
。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $vim /usr/local /tomcat8/bin/catalina.shJAVA_OPTS="-server -Xms1024m -Xmx1024m -Xmn256m -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:+UseParallelOldGC -XX:+UseParallelOldGC " $vim /usr/local /tomcat8/bin/catalina.batset "JAVA_OPTS=%JAVA_OPT% -server -Xms2048m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512m -Djava.awt.headless=true"
weiyigeek.top-
注意事项:
java 8开始PermSize被MetaspaceSize代替
,MetaspaceSize共享heap不会再有java.lang.OutOfMemoryError:PermGen space可以不设置
java8 开始已经移除MaxPermSize/UseParallelGCThreads=8
Java 提供的垃圾回收机制虚拟机的堆大小决定了虚拟机花费在收集垃圾上的时间和频度并且收集垃圾可以接受的速度与应用有关
如果堆(heap)的空间很大,那么完全垃圾收集(FULL GC)就会很慢,但是频度会降低。
如果在客户系统中把堆的大小和内存的需要一致,完全收集就很快,但是会更加频繁。
推荐把-Xms设置为应用所需的最小值,这样会产生高效的垃圾回收
。
(2)Tomcat与web服务器整合 描述: 虽然tomcat也可以作web服务器但其处理静态html的速度比不上Nginx服务,并且为了更好的进行设置负载均衡,还是得和Nginx进行联用;
因此我们可以把 Nginx 和 Tomcat 集成起来, 将html与jsp的功能部分进行明确分工, 让tomcat只处理jsp部分,或者也可以由其它的由 apache, IIS 等这些 web服务器处理,由此大大节省了tomcat有限的工作线程。
4.2 自身调优 (1)Connector元素属性优化 禁用DNS查询
描述: 消除DNS查询对性能的影响我们可以关闭DNS查询
优化: enableLookups="false"
结果: 节省了网络带宽、查询时间和内存,而且更小的流量会使日志数据也会变得更少,显而易见也节省了硬盘空间
调整线程数(需要根据压力测试进行调整)
描述: 可通过应用程序的连接器(Connector)进行性能控制的参数是创建的处理请求的线程数。在Java中线程是程序运行时的路径,是在一个程序中与其它控制线程无关的、能够独立运行的代码段。但是应防止流量不可控制(或者恶意的服务攻击),从而导致超出了虚拟机使用内存的大小;web server允许的最大连接数还受制于操作系统的内核参数设置,通常Windows是2000个左右,Linux是1000个左右。
优化: 修改 minProcessors
和maxProcessors
的值来控制线程数
结果: 它们共享相同的地址空间。多线程帮助程序员写出CPU最大利用率的高效程序,使空闲时间保持最低,从而接受更多的请求。
NIO 配置
描述:NIO (No-blocking I/O)从JDK 1.4起,NIO API作为一个基于缓冲区,并能提供非阻塞I/O操作的API被引入[LD6];TOMCAT可以支持高并发的企业级应用,配置良好的tomcat都会使用APR(Apache Portable Runtime),APR是Apache HTTP Server2.x的核心,它是高度可移植的本地库,它使用高性能的UXIN I/O操作,低性能的java io操作。
优化: protocol="org.apache.coyote.http11.Http11NioProtocol"
结果: NIO使用单线程(单个CPU)或者只使用少量的多线程(多CPU)来接受Socket,而由线程池来处理堵塞在pipe或者队列里的请求。只要OS可以接受TCP的连接,web服务器就可以处理该请求。大大提高了web服务器的可伸缩性。
ARP配置(推荐方式-但是需要安装额外的包):
描述: Tomcat APR 模式也是 Tomcat 在高并发下的首选运行模式
优化: protocol="org.apache.coyote.http11.Http11AprProtocol"
结果: 调用 httpd 核心链接库来读取或文件传输,从而提高 tomcat 对静态文件的处理性能
port|Tomcat启动监听端口| Default 8080 | protocol|Tomcat的3种运行状态协议| Default bio HTTP/1.1| acceptCount|监听端口队列最大数,满了之后客户请求会被拒绝(不能小于maxSpareThreads)| Default 100,建议设置1000| maxThreads|当前可以同时处理的最大用户访问数最大连接数配置(并发能力)| Default 200 ,建议设置1000| minSpareThreads| Tomcat初始化时创建的socket线程数,线程的最小运行数目 | Default 10 ,建议设置1000| maxSpareThreads| Tomcat连接器的最大空闲socket线程数,一旦创建的线程超过这个值将会关闭socket| 建议设置1000| minProcessors| 服务器创建时的最小处理线程数 | 建议设置 100| maxProcessors| 服务器同时最大处理线程数 | 建议设置 1000| enableLookups | 支持域名解析可把ip地址解析为主机名 | 建议设置false 关闭DNS反向查询| compression | 是否打开压缩功能 | on| compressionMinSize | 压缩的最小字节 | 2048| compressableMimeType | 压缩的MImeType类型 | text/html,text/xml,text/javascript,text/css,text/plain| connectionTimeout | 代表连接超时时间,单位为毫秒 | 默认值为60000。通常情况下设置为30000| disableUploadTimeout | 标志允许servlet在一个servlet执行的时候,使用一个不同的更长的连接超时。| 建议设为false| keepAliveTimeout|长连接超时时间 |常常设置-1永不过期| URIEncoding|URL统一编码|utf-8| redirectPort|在需要基于安全通道的场合,把客户请求转发到基于SSL的redirectPort端口|8443| prestartminSpareThreads | 在 Tomcat 初始化的时候就初始化 minSpareThreads 的 maxQueueSize | 最大的等待队列数,超过则拒绝请求 |
描述: 在tomcat中每一个用户请求都是一个线程,所以可以使用线程池提高性能。 修改server.xml文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 $ vim ./conf/server.xml <!‐‐ 将注释打开(注释没打开的情况下默认10 个线程,最小10 ,最大200 )‐‐> <Executor name ="tomcatThreadPool" namePrefix ="catalina‐exec‐" maxThreads ="500" minSpareThreads ="50" prestartminSpareThreads ="true" maxQueueSize ="100" /><Connector port ="8080" #默认BIO /建议采用NIO 或者arp 提高并发处理能力 protocol ="HTTP/1.1" #网络连接超时,单位:毫秒。设置为0 表示永不超时(不推荐)) connectionTimeout ="30000" maxHttpHeaderSize ="32768" redirectPort ="8443" #当前可以同时处理的最大用户访问数最大连接数配置(并发能力) maxThreads ="1000" #Tomcat 初始化时创建的线程数。最小空闲线程连接数用于优化线程池 minSpareThreads ="100" #一旦创建的线程超过这个值,Tomcat 就会关闭不再需要的socket 线程。 maxSpareThreads ="1000" acceptorThreadCount ="2" #当所有的线程以分配,仍然允许连接进来,但是出于等待状态的用户数。 #等待线程数+工作线程数=总的可最大连接数,超过这个数的请求将不予处理。 acceptCount ="2000" minProcessors ="100" maxProcessors ="2000" #为了消除DNS 查询对性能的影响我们可以关闭DNS 查询,关闭该功能在一定程度上提高了Tomcat 服务器的性能; enableLookups ="false" maxKeepAliveRequests ="-1" keepAliveTimeout ="-1" disableUploadTimeout ="false" connectionUploadTimeout ="150000" useSendfile ="false" #Tomcat 压缩配置,建议在前端 nginx 上开启压缩。Tomcat 作为应用服务器本身就很繁忙了。 compression ="on" compressionMinSize ="2048" compressableMimeType ="text/html,text/xml,application/javascript,application/json,text/javascript,text/css,text/plain,image/gif,image/png" URIEncoding ="UTF-8" />
(2)采用用arp模式进行高并发选择 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 cd /usr/local /src/wget http://mirrors.tuna.tsinghua.edu.cn/apache/apr/apr-1.7.0.tar.gz wget http://mirrors.tuna.tsinghua.edu.cn/apache/apr/apr-util-1.6.1.tar.gz tar xf apr-1.7.0.tar.gz && tar xf apr-util-1.6.1.tar.gz cd apr-1.7.0./configure --prefix=/usr/local /apr make -j 2 && make install cd apr-util-1.6.1./configure --prefix=/usr/local /apr-util --with-apr=/usr/local /apr/ make -j2 && make install cp "/opt/tomcat/apache-tomcat-8.5.45/bin/tomcat-native.tar.gz" . tar xf tomcat-native.tar.gz && cd tomcat-native-1.2.23-src/native/ ./configure --prefix=/usr/local /apr --with-java-home=/opt/tomcat/jdk8/ make -j 2 && make install echo "export LD_LIBRARY_PATH=/usr/local/apr/lib" > /etc/profilesource /etc/profile
配置arp模式:1 2 3 4 5 6 7 $ cd /usr/local /tomcat/conf/ $ vim server.xml <Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" connectionTimeout="20000" redirectPort="8443" /> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
weiyigeek.top-
成功后查看启动日志:1 2 3 4 $cat /opt/tomcat/apache-tomcat-8.5.45/logs/catalina.out12-Sep-2019 12:37:47.381 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-apr-10.10.107.222-8080" ] 12-Sep-2019 12:37:47.417 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["https-openssl-apr-443" ] 12-Sep-2019 12:37:47.419 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 891 ms
(3)启用外部连接池 描述:执行器(线程池)在tomcat中每一个用户请求都是一个线程,所以可以使用线程池提高性能。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="300" minSpareThreads="4" /> <Connector executor="tomcatThreadPool" port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="1000" minSpareThreads="100" maxSpareThreads="200" acceptCount="1000" disableUploadTimeout="true" connectionTimeout="30000" URIEncoding="UTF-8" enableLookups="false" compression="on" compressionMinSize="2048" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,image/gif,image/jpg,image/png" redirectPort="8443" />
weiyigeek.top-
(4)禁用自动检测更新加载 Context元素reloadable属性会监视在 web-inf/classes 和 web-inf/lib 目录下class文件的改动,如果监测到有class文件被更新的,服务器会自动重新加载web应用。
在开发和调试阶段,将其改为true但是一般像Eclipse等开发环境都会默认改为true
在正式发布阶段,应将其该为false可以降低Tomcat的运行负荷,提高Tomcat的运行性能1 2 3 $vim conf/server.xml<context path="/bbs" docbase="bbs" reloadable="false" />
(5)增大随机数熵池 描述:当你执行了 ./startup.sh 或者 ./catalina.sh start 后等待时间过长能要几分钟才能正常提供服务。 原因:在apache-tomcat 官方文档:如何让 tomcat 启动更快里面提到了一些启动时的优化项,其中一项是关于随机数生成时,采用的"熵源"(entropy source)的策略
。
使用伪随机函数生成器:
通过修改 Tomcat 启动文件 -Djava.security.egd=file:/dev/urandom
通过修改 JRE 中的 java.security 文件 securerandom.source=file:/dev/urand
1 JAVA_OPTS="-server -Xms1024m -Xmx2048m -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=80 -XX:-PrintGC -XX:-PrintGCDetails -XX:-PrintGCTimeStamps -Djava.security.egd=file:/dev/urandom"
weiyigeek.top-
增大/dev/random的熵池(推荐)1 2 3 4 $yum -y install rng-tools$systemctl start rngd$systemctl enable rngd
启动服务后观察 cat/proc/sys/kernel/random/entropy_avail
基本在三千左右。1 2 $cat /proc/sys/kernel/random/entropy_avail3311
5.安全加固 描述:加固依然分为身份鉴别、访问控制、安全审计、资源控制和入侵防范5个方面; 大部分加固基于xml配置文件进行修改,也应根据实际需求制定方案。1 2 3 4 find /-name *tomcat* ${tomcat_home} /conf/...
5.1 身份鉴别 0.口令复杂度,不同用户不同账号 描述:口令要求:长度至少8位,并包括数字、小写字母、大写字母和特殊符号4类中至少3类。 修改tomcat配置文件/conf/tomcat-users.xml配置文件,要求usr1密码必须满足复杂度要求。1 2 <user username="Tomcat1" password="12345qwe" roles="manager-gui" > <user username="Tomcat2" password="12345qwe" roles="admin-gui" >
1.安全配置manager登录页面并且删除多余账号 描述:Tomcat的主要管理界面被称为Manager应用程序
如果不使用manager来管理部署应用,建议修改tomcat配置文件/conf/tomcat-users.xml配置文件来禁用或者删除manager文件夹
如果使用该功能我们需要进行配置口令以及强密码包括访问控制,删除与工作无关的帐号以及应用。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 $vim tomcat_user.xml<?xml version="1.0" encoding="UTF-8" ?> <tomcat-users xmlns="http://tomcat.apache.org/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd" version="1.0" > <role rolename="manager-gui" /> <role rolename="admin-gui" /> <!--密码复杂度需要满足等保要求--> <user username="admin" password="@weiyigeek@" roles="manager-gui,admin-gui" /> </tomcat-users> $/opt/tomcat/apache-tomcat-8.5.45/webapps/manager/META-INF/ <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
WeiyiGeek
2.Tomcat虚拟主机管理器安全配置并且删除多余账号 描述:与manager管理一样如果使用的话进需要进行安全配置
不使用的话建议删除webapps应用目录下的host-manager
使用需要进行安全配置1 2 3 4 5 6 7 $vim conf/tomcat-users.xml<role rolename="admin-gui" /> <user username="tomcat" password="s3cret" roles="admin-gui" /> <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|10\.\d+\.\d+\.\d+" />
weiyigeek.top-
3.非root启动服务 描述:建议使用专用用户 tomcat 或者 nobody 用户来启动 Tomcat,为了防止 Tomcat 被植入 web shell 程序后,可以修改项目文件。 因此我们要将 Tomcat 和项目的属主做分离
(常常使upload目录可以有上传权限,但是不能有执行的权限))))),他也无法创建和编辑项目文件。1 2 $ps -ef | grep tomcat|grep -v "grep" tomcat 13243 1 0 10:27 pts/0 00:00:02 /opt/tomcat/jdk8/jre/bin/java -Djava.util.logging.config.file=/opt/tomcat//apache-tomcat-8.5.45/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server -Xms1024m -Xmx2048m -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=80 -XX:-PrintGC -XX:-PrintGCDetails -XX:-PrintGCTimeStamps -Xloggc:../logs/gc.log -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /opt/tomcat//apache-tomcat-8.5.45/bin/bootstrap.jar:/opt/tomcat//apache-tomcat-8.5.45/bin/tomcat-juli.jar -Dcatalina.base=/opt/tomcat//apache-tomcat-8.5.45 -Dcatalina.home=/opt/tomcat//apache-tomcat-8.5.45 -Djava.io.tmpdir=/opt/tomcat//apache-tomcat-8.5.45/temp org.apache.catalina.startup.Bootstrap start
5.2 安全审计 0.增加记录日志功能 描述:Tomcat的日志文件存放于logs文件夹,里面包含了多种类型的日志,主要分为两类:
一是运行中的日志,它主要记录运行的一些信息,尤其是一些异常错误日志信息。
二是访问日志信息,它记录的访问的时间,IP,访问的资料等相关信息。
各个日志文件的作用:
localhost.2019-09-10.log:程序异常没有被捕获的时候抛出的地方
catalina.2019-09-10.log:程序的输出,tomcat的运行日志
manager.2019-09-10.log:manager项目专有的
host-manager.2019-09-10.log:manager项目专有的
localhost_access_log.2019-09-10.txt:访问日志记录
编辑tomcat配置文件server.xml配置文件将以下内容的注释标记:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <Valve className ="org.apache.catalina.valves.AccessLogValve" directory ="logs" prefix ="localhost_access_log" suffix =".txt" pattern ="%h %l %u %t "%r" %s %b" />
属性解释:
Directory:日志文件放置的目录,在tomcat下面有个logs文件夹,那里面是专门放置日志文件的,也可以修改为其他路径;
Prefix:这个是日志文件的名称前缀,日志名称为localhost_access_log.2008-10-22.txt,前面的前缀就是这个localhost_access_log。
Suffix: 文件后缀名。
Pattern:common方式时,将记录访问源IP、本地服务器IP、记录日志服务器IP、访问方式、发送字节数、本地接收端口、访问URL地址等相关信息在日志文件中。
resolveHosts:值为true时,tomcat会将这个服务器IP地址通过DNS转换为主机名,如果是false,就直接写服务器IP地址。
Tomcat的运行日志有以下7个级别:
SEVERE > WARNING > INFO > CONFIG > FINE > FINER > FINEST
5.3 资源控制 0.移除默认应用程序 描述:Tomcat可能自带一些默认的web应用程序。如果不是一定需要,必须将它们移除。 移除${tomcat_home}/webapps中所有的默认的web应用程序有:ROOT、Documentation、Examples、Host Manager和Manager
1 2 rm -rf /opt/tomcat/apache-tomcat-8.5.45/webapps/*
1.错误页面重定向 描述:编辑tomcat配置文件/conf/web.xml文件,在最后一行之前加入以下内容,然后需要重新启动tomcat服务;1 2 3 4 5 6 7 8 9 10 <error-page > <error-code > 404</error-code > <location > /noFile.htm</location > </error-page > <error-page > <exception-type > java.lang.NullPointerException</exception-type > <location > /error.jsp</location > </error-page >
当出现NullPointerException异常时tomcat会把网页导入到error.jsp,且会打印出出错信息。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <%@ pageerrorPage="/error.jsp" %> 典型的error.jsp错误页面的程序写法如下: <%@ pagecontentType="text/html;charset=GB2312" %> <%@ pageisErrorPage="true" %> <html> <head> <title>错误页面</title> </head> <body>出错了:</p>错误信息:<%= exception.getMessage() %> <br> Stack Trace is : <pre> <font color="red" ><% java.io.CharArrayWritercw = new java.io.CharArrayWriter(); java.io.PrintWriterpw = new java.io.PrintWriter(cw,true ); exception.printStackTrace(pw); out.println(cw.toString()); %> </font> </pre> </body> </html>
补充事项:
如果Manager应用程序没被移除,必须手动将位于 CATALINA_HOME/webapps/manager/WEB-INF/jsp/
的错误页面里的Tomcat版本信息移除。
3.限制访问Tomcat文件夹
描述:Tomcat文件夹只能由tomcat用户本身访问,尤其是对于目录${tomcat_home}/conf /和${tomcat_home}/webapps
当不需要通过应用程序服务器自动部署时,标准配置就是将所有Tomcat文件的所有者设置为root,并且所属群组设置为Tomcat,然后用chmod 740仅允许root用户编辑文件并允许Tomcat用户读取文件。1 2 3 4 whown root:tomcat /opt/tomcat chmod 740 ${tomcat_home} /conf chmod 740 ${tomcat_home} /webapps
4.会话超时 描述:所有的web应用程序的会话超时必须设置为20分钟可通过编辑 CATALINA_HOME/conf/web.xml 文件并做以下配置来实现:1 2 3 4 <session-config > <session-timeout > 20</session-timeout > </session-config >
4.4 访问控制 描述: Tomcat提供了防止恶意攻击或禁止某些机器访问的设置,限制手段来防止恶意的服务攻击; 可以让你过滤来自请求的主机或IP地址,并允许或拒绝哪些主机/IP。与之类似的在Apache的httpd文件里有对每个目录的允许/拒绝指定。
1.Context.xml访问控制设置 Tomcat提供了两个参数供你配置:RemoteHostValve 和RemoteAddrValve。 例如: 你可以把Admin Web application设置成只允许本地访问设置如下:1 2 3 4 5 <Context path="/path/to/secret_files" > <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="10.0.172.109" deny="" /> </Context>
5.5 入侵防范 0.防止缓慢的http拒绝服务攻击与限制监听网络接口 描述:不要让连接器(connector)监听服务器上所有可用的网络接口和IP地址,而要让连接器监听指定的网络接口和IP地址采用address属性,防止应用程序意外地运行在某个开放的网络接口上。1 2 3 4 5 $vim conf/server.xml<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="10000" redirectPort="8443" address="127.0.0.1" />
1.禁用tomcat的AJP协议(8.5.51之前的版本默认开启后续则禁用) 描述:AJP(Apache JServer Protocol)AJPv13协议是面向包的。 WEB服务器和Servlet容器通过TCP连接来交互, 为了节省SOCKET创建的昂贵代价,WEB服务器会尝试维护一个永久TCP连接到servlet容器,并且在多个请求和响应周期过程会重用连接。
实际上我们一般使用Nginx+Tomcat架构所以用不着Ajp协议可以将其禁用。
1 2 3 $vim conf/server.xml<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
weiyigeek.top-ajp
Tips : 禁用ajp后可以看节省了多少内存以及查询某个pid占用的内存。
2.禁用非法HTTP请求方法 描述:readonly参数默认是true即不允许delete和put操作 编辑web.xml文件查看org.apache.catalina.servlets.DefaultServlet是否存在如下配置1 2 3 4 5 $vim conf/web.xml <init-param > <param-name > readonly</param-name > <param-value > true</param-value > </init-param >
3.禁止目录列出
描述:设置DefaultServlet的listings为false 这不仅仅是因为允许显示目录列表被认为是不安全的,而且还因为生成具有数千个文件的目录列表会消耗大量的CPU资源,相当于被DDoS攻击。 注意:Tomcat8默认是false并且更改后需要重新启动tomcat服务;1 2 3 4 5 6 7 $vim conf/web.xml <servlet-class > org.apache.catalina.servlets.DefaultServlet</servlet-class > <init-param > <param-name > listings</param-name > <param-value > false</param-value > </init-param >
4.防止恶意关闭服务 描述:编辑tomcat配置文件conf/server.xml配置文件,shutdown的值为复杂的字符串:1 2 3 4 5 6 7 8 $cat /dev/urandom | tr -dc '_a-zA-Z0-9' | head -c 12r02BPRnHyq89 <Serverport="8005" shutdown="r02BPRnHyq89" > <Server port="-1" shutdown="SHUTDOWN" >
5.修改Banner掩盖真实信息 描述:修改以掩饰真实版本信息防止攻击者以版本的漏洞进行攻击,影响错误页面和响应头;1 2 3 4 5 6 7 8 $unzip catalina.jar$vim catalina/org/apache/catalina/util/Serverinfo.propertiesserver.info=Nginx server.number=0.0.0.0 server.built=Apr 2 2017 07:25:00 UTC jar uvf catalina.jar org/apache/catalina/util/ServerInfo.properties
weiyigeek.top-
1 2 3 4 5 6 7 <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" useBodyEncodingForURI="true" server="Microsoft-IIS/6.5" />
weiyigeek.top-
6.关闭自动部署 描述:Tomcat允许在Tomcat运行时自动部署应用程序。为了防止被植入木马等恶意程序,因此我们要关闭自动部署。1 2 3 $vim server.xml<Host name="localhost" appBase="webapps" unpackWARs="false" autoDeploy="false" >
补充:在托管环境中Web应用程序可能不受信任,也可以设置deployXML属性为false来忽略context.xml
以防给该web应用程序提高权限。
7.配置HTTPS加密协议 描述:采用HTTPS协议加密可以防止中间人攻击,以及数据的拦截和修改的验证导致攻击无效;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 $JAVA_HOME /bin/keytool -genkey -alias tomcat -keyalg RSA -keystore /tmp/keystoreEnter keystore password: Re-enter new password: What is your first and last name? [Unknown]: Tomcat What is the name of your organizational unit? [Unknown]: CQ What is the name of your organization? [Unknown]: CQ What is the name of your City or Locality? [Unknown]: BEIJING What is the name of your State or Province? [Unknown]: XIZHIMEN What is the two-letter country code for this unit? [Unknown]: 408119 Is CN=Tomcat, OU=CQ, O=CQ, L=BEIJING, ST=XIZHIMEN, C=408119 correct? [no]: Y Enter key password for <tomcat> (RETURN if same as keystore password): Re-enter new password: <Connector classname="org.apache.catalina.http.HttpConnector" port="443" protocol="HTTP/1.1" minProcessors="5" SSLEnabled="true" maxprocessors="100" enableLookups="true" acceptCount="10" debug="0" scheme="https" Factory_classname="org.apache.catalina.SSLServerSocketFactory" secure="true" clientAuth="false" keystoreFile="/tmp/keystore" keystorePass="weiyigeek" sslProtocol="TLS" /> ciphers="SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"
也可以通过 https://10.10.107.222/manager/html/sslConnectorCerts 查看证书情况
weiyigeek.top-
补充:为了使托管在Tomcat上的所有web应用程序强制使用HTTPS,必须在每个 CATALINA_HOME/webapps/$WEBAPP/WEB-INF/web.xml 文件里每个security-constraint标签关闭(标签)之前包含以下内容:1 2 3 <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> <user-data-constraint>
8.HttpOnly标记 描述:对会话cookie自动启用HttpOnly的cookie标记,查看配置以确保该选项为被禁用。1 2 3 4 <Context useHttpOnly='true' > ... <Context>
补充:如果应用程序需要通过JavaScript访问HttpOnly cookie,可以在METAINF/context.xml中一个单独的Context中定义一个异常。
9.CSRF防护(根据实际情况添加) 描述:为保护应用程序必须启用Tomcat的跨站请求伪造防护。Tomcat8~9提供了基本的CSRF防护。可以在 CATALINA_BASE/conf/web.xml 中配置一个全局过滤器。1 2 3 4 5 <filter-mapping> <filter-name>CSRFPreventionFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
补充:使用CSRF防护可能会影响程序功能,必须要牢记这一点,尤其是在应用程序大量使用异步请求的情况下。
5.6 默认设置 描述:以下是常规的默认配置并且默认情况下这些设置被认为是安全的,如有在项目中进行更改的建议进行整改和调整;
1.server.xml中默认安全配置 1 2 3 4 5 $vim $CATALINA_HOME /conf/server.xml<Connector allowTrace="false" />
2.context.xml中默认安全配置 1 2 3 4 5 6 7 8 9 10 11 12 13 $vim $CATALINA_HOME /conf/server.xml<Context privileged="false" crossContext="false" allowLinking="false" />
3.Tomcat启动参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Dorg.apache.catalina.connector.RECYCLE_FACADES = false Dorg.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH = FALSE Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH = FALSE Dorg.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER = false Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH= FALSE Dorg.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER = false
5.7 可选操作 1.Java SecurityManager 描述:可用Java SecurityManager限制单个应用程序的功能。
$CATALINA_HOME/conf/catalina.policy 文件包含了Java SecurityManager使用的安全策略的配置
一旦配置了catalina.policy 文件,便可以使用SecurityManager和–security选项启Tomcat。
注意事项:
因为基本上所有的权限类型(比如访问单个文件和目录或Java包)都应该根据每个应用程序进行单独配置,所以这会大大增加操作成本。另外,限制过于严格的策略文件会影响应用程序的功能。
2.访问Java包控制 描述:Tomcat可限制对某些Java包的访问。如果检测到受限制的包被访问,将抛出安全异常。 对Java包做访问限制,打开 $CATALINA_BASE/conf/catalina.properties 文件并添加不允许访问的包至package.access列表。
分析Java import可以列出哪些应用程序需要哪些包。在Unix系统上,可以使用以下例子来实现:1 grep –R import ${tomcat_home} /webapps/WEBAPP
6.附录说明 (1) 生产配置实例 描述 server.xml
配置文件:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 [root@tomcat1 ~]# vim /usr/local/tomcat8/conf/server.xml <Connector executor ="tomcatThreadPool" port ="8080" protocol ="org.apache.coyote.http11.Http11NioProtocol" address ="127.0.0.1" acceptCount ="1000" connectionTimeout ="20000" compression ="on" compressionMinSize ="2048" compressableMimeType ="text/html,text/xml,text/javascript,text/css,text/plain,image/gif,image/jpg,image/png" disableUploadTimeout ="true" enableLookups ="false" maxThreads ="1000" minSpareThreads ="100" maxSpareThreads ="200" maxKeepAliveRequests ="1" redirectPort ="8443" server ="SecWAF/1.9" URIEncoding ="UTF-8" />
优化参考: https://www.jianshu.com/p/d64b5909ec1b https://www.cnblogs.com/yechanglv/p/6941821.html