目录
1、tomcat的基本安全加固
1.1、安全加固之隐藏tomcat版本信息
1.2、安全加固之禁用tomcat管理页面
1.3、安全加固之以降权用户启动tomcat
2、tomcat优化
2.1、启动参数优化
2.2、容器内优化
3、总结
1、tomcat的基本安全加固
1.1、安全加固之隐藏tomcat版本信息
随意在互联网上暴露tomcat的版本信息是不安全的,黑客会根据你所部署tomcat版本爆出的漏洞进行攻击,如果你把版本信息通过技术处理后隐藏起来,那黑客就不能获取到详细的版本,也就不能根据此版本爆出的漏洞进行黑客行为。正常情况下你访问一个不存在的页面时,tomcat会报告一些信息,如下:
输出信息就包括了tomcat的版本信息,我们可以让自定义显示这个版本信息,可以如下操作:
[root@nod3 tomcat-7]# pwd /usr/local/tomcat-7 #这是tomcat的安装目录 [root@nod3 tomcat-7]# ls bin conf lib LICENSE logs NOTICE RELEASE-NOTES RUNNING.txt temp webapps work [root@nod3 tomcat-7]# cd lib/ [root@nod3 lib]# mkdir -p org/apache/catalina/util [root@nod3 lib]# cd org/apache/catalina/util/ [root@nod3 util]# vim ServerInfo.properties server.info=version 1.0 #这里填写自定义的版本信息
保存后重新启动tomcat实例,再访问一个不存在的页面时得到的错误信息如下:
这里tomcat的版本信息就被修改了。想隐藏tomcat的版本信息还可以自定义错误页面,让出错信息定义到一个我们自己的页面上,这样也可以达到同样的效果。
1.2、安全加固之禁用tomcat管理页面
默认时tomcat自带了manager的管理接口,通过此接口可以对项目进行管理,管理页面见下图:
但在实际的工作中很少有机会使用此接口,所以应该禁用,不禁用此接口会带来潜在的安全风险。我们只需要删除tomcat安装目录下的webapps目录下的所有内容,即如下操作:
[root@nod3 tomcat-7]# pwd /usr/local/tomcat-7 #tomcat安装目录 [root@nod3 tomcat-7]# ls bin conf lib LICENSE logs NOTICE RELEASE-NOTES RUNNING.txt temp webapps work [root@nod3 tomcat-7]# rm -rf webapps/* #删除webapps目录下的所有内容
注:如果你的环境中有必要使用此管理接口,那也应该把默认的"manager"这个访问路径进行修改成一个不好猜测的路径,并把访问的认证用户名和密码设置得足以复杂。
1.3、安全加固之以降权用户启动tomcat
我见过在生产环境上有些小伙伴是以root权限来运行tomcat实例的,大家都知道root用户是个什么概念,它是一个无所不能的用户,包括“自杀”。所以一个应用程序的是不应该以root用户来运行的,如果应用一旦被攻破,那黑客得到的就是root用户的权限,想想你系统的root权限被别人所掌握了,你还睡得着常见吗?
以一个非root权限的用户运行tomcat实例时,也应该注意这个非root权限的帐号不能登陆系统,即shell为“/sbin/nologin”,而$CATALINA_BASE目录下的所有文件或目录的属主、属组都应该修改成这个用户,在启动tomcat实例时su到这个非root权限的用户启动tomcat实例即可。在http://zhaochj.blog.51cto.com/368705/1663663的“思考和优化tomcat配置流程”的这一节里有这方面的详细介绍。
2、tomcat优化
注意:下边涉及到的所有操作的环境都是基于http://zhaochj.blog.51cto.com/368705/1663663博文中的系统环境。
在讨论tomcat优化前,先来处理tomcat的apr问题。tomcat在处理IO时常见的运行模式有3种,分别为BIO、NIO、APR,默认时tomcat采用BIO模式,这种模式没有通过任何的技术优化,性能非常低下;NIO利用java自带的异步IO处理技术,性能优于BIO;APR从操作系统层面上解决异步IO的问题,会大幅提升性能。在是否启用APR时,在互联网上有些争论,在查找相关资料时有说APR只是对在处理静态文件有性能方面的提升,但如果tomcat不是直接面向用户,而是通过像apache或nginx这样的反向代理工具代理后再连接tomcat,静态文件直接在前端就进行了处理,并还启用的缓存功能,那后端的tomcat就是一个纯粹的web容器,只是处理动态文件,那可以不使用APR这种工作模式。其实这个问题我们可以换一种思路的处理,你前端用了反向代理工具后,先后对启用APR与没有启用APR时都做一次压力测试,选择效果较好的一种方式即可,不用再去纠结APR到底是对静态文件的处理上有性能提升还是会对动态文件的处理也有性能上的提升。
在没有启用APR功能时,启动tomcat会在catalina.out日志发现如下信息:
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
要想让tomcat支持APR功能应该如下操作:
[root@nod3 bin]# pwd /usr/local/tomcat-7/bin [root@nod3 bin]# ls # 我们所要用的包是tomcat-native.tar.gz bootstrap.jar commons-daemon.jar daemon.sh setclasspath.sh startup.sh tool-wrapper.sh catalina.bat commons-daemon-native.tar.gz digest.bat shutdown.bat tomcat-juli.jar version.bat catalina.sh configtest.bat digest.sh shutdown.sh tomcat-native.tar.gz version.sh catalina-tasks.xml configtest.sh setclasspath.bat startup.bat tool-wrapper.bat [root@nod3 bin]# tar xf tomcat-native.tar.gz [root@nod3 bin]# cd tomcat-native-1.1.33-src/jni/native/ [root@nod3 native]# ls build BUILDING configure libtcnative.dsp NMAKEmakefile src tcnative.pc.in buildconf build-outputs.mk configure.in libtcnative.dsw NMAKEmakefile.inc srclib tcnative.spec build.conf config.layout include Makefile.in os tcnative.dsp [root@nod3 native]# ./configure --with-apr=/usr/bin/apr-1-config --with-java-home=/usr/java/latest [root@nod3 native]# make && make install #安装完成后会显示生成的库文件路径在“Libraries have been installed in: /usr/local/apr/lib” [root@nod3 native]# ll /usr/local/apr/lib/ total 2516 -rw-r--r-- 1 root root 1637666 Jun 22 22:32 libtcnative-1.a -rwxr-xr-x 1 root root 1025 Jun 22 22:32 libtcnative-1.la lrwxrwxrwx 1 root root 23 Jun 22 22:32 libtcnative-1.so -> libtcnative-1.so.0.1.33 lrwxrwxrwx 1 root root 23 Jun 22 22:32 libtcnative-1.so.0 -> libtcnative-1.so.0.1.33 -rwxr-xr-x 1 root root 925984 Jun 22 22:32 libtcnative-1.so.0.1.33 drwxr-xr-x 2 root root 4096 Jun 22 22:32 pkgconfig
而“/usr/local/apr/lib”目录不在tomcat启动时所搜索的目录,所以做一个链接即可:
[root@nod3 native]# ln -sv /usr/local/apr/lib/libtcnative-1.so.0.1.33 /usr/lib64/libtcnative-1.so `/usr/lib64/libtcnative-1.so' -> `/usr/local/apr/lib/libtcnative-1.so.0.1.33'
现在再重新启动tomcat观察日志会发现如下信息:
INFO: Loaded APR based Apache Tomcat Native library 1.1.33 using APR version 1.3.9. #APR的版本信息 Jun 22, 2015 10:46:14 PM org.apache.catalina.core.AprLifecycleListener lifecycleEvent INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true]. #APR的功能已启用 Jun 22, 2015 10:48:29 PM org.apache.catalina.core.AprLifecycleListener initializeSSL INFO: OpenSSL successfully initialized (OpenSSL 1.0.1e 11 Feb 2013) Jun 22, 2015 10:48:29 PM org.apache.coyote.AbstractProtocol init INFO: Initializing ProtocolHandler ["http-apr-8080"] #在配置APR之前默认是“http-bio-8080”,只要配置为支持APR后,自动以apr模式工作 Jun 22, 2015 10:48:29 PM org.apache.catalina.startup.Catalina load INFO: Initialization processed in 1379 ms Jun 22, 2015 10:48:29 PM org.apache.catalina.core.StandardService startInternal INFO: Starting service Catalina Jun 22, 2015 10:48:29 PM org.apache.catalina.core.StandardEngine startInternal INFO: Starting Servlet Engine: version 1.0 Jun 22, 2015 10:48:30 PM org.apache.catalina.startup.HostConfig deployDirectory INFO: Deploying web application directory /usr/local/tomcat_instances/nod1.test.com-instance-1/webapps/webpages Jun 22, 2015 10:48:30 PM org.apache.catalina.startup.HostConfig deployDirectory INFO: Deployment of web application directory /usr/local/tomcat_instances/nod1.test.com-instance-1/webapps/webpages has finished in 172 ms Jun 22, 2015 10:48:30 PM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["http-apr-8080"] Jun 22, 2015 10:48:30 PM org.apache.catalina.startup.Catalina start INFO: Server startup in 1369 ms
通过上边的日志输出信息就可得知目前tomcat的工作模式,但为了更为准确的说明tomcat是以APR方式运行的一般会把server.conf中对应的连接器中的protocol的值更换为“org.apache.coyote.http11.Http11AprProtocol”,即如下:
[root@nod3 nod1.test.com-instance-1]# pwd /usr/local/tomcat_instances/nod1.test.com-instance-1 [root@nod3 nod1.test.com-instance-1]# vim conf/server.xml ....... <!--<Connector port="8080" protocol="HTTP/1.1"--> #原有的注释掉 <Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" connectionTimeout="20000" redirectPort="8443" /> .......
并且还会把APR所在的库目录也在tomcat启动参数中指定出来,即在实例的启动脚本中加入JAVA_OPTS="-Djava.library.path=/usr/local/apr/lib"参数,这样在启动tomcat后,日志中就会有这样的信息:“INFO: Command line argument: -Djava.library.path=/usr/local/apr/lib”
至此,tomcat已工作在了APR的工作模式。
2.1、启动参数优化
tomcat的启动参数的调整是在tomcat的安装目录“$CATALINA_HOME/bin/catalina.sh”这个文件里进行设置,直接在文件开头的注释文字的最后一行直接加入启动参数即可,有点下边这样:
[root@nod3 ~]# vim /usr/local/tomcat-7/bin/catalina.sh ...... # CATALINA_PID (Optional) Path of the file which should contains the pid # of the catalina startup java process, when start (fork) is # used # # LOGGING_CONFIG (Optional) Override Tomcat's logging config file # Example (all one line) # LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties" # # LOGGING_MANAGER (Optional) Override Tomcat's logging manager # Example (all one line) # LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" # ----------------------------------------------------------------------------- JAVA_OPTS="-server -Djava.library.path=/usr/local/apr/lib -Xms256M -Xmx256M -XX:PermSize=16M -XX:MaxPermSize=256M" #这一行就是我们增加的启动参数 # OS specific support. $var _must_ be set to either true or false. cygwin=false darwin=false os400=false case "`uname`" in CYGWIN*) cygwin=true;; Darwin*) darwin=true;; OS400*) os400=true;; esac ......
如果tomcat是以多实例的方式运行的,那启动参数直接写入启动脚本中,像下边这样操作:
[root@nod3 nod1.test.com-instance-1]# pwd /usr/local/tomcat_instances/nod1.test.com-instance-1 [root@nod3 nod1.test.com-instance-1]# ls conf logs temp tomcat.sh webapps work [root@nod3 nod1.test.com-instance-1]# vim tomcat.sh #!/bin/bash #Program: manager tomcat instance start or stop #Author: zhaochj #Date: 2015-6-18 #Version 1.0 # source /etc/rc.d/init.d/functions JAVA_HOME=/usr/java/latest #定义tomcat启动参数 ,针对这一个实例的启动参数全部都在这里进行定义 JAVA_OPTS="-server -Djava.library.path=/usr/local/apr/lib -Xms256M -Xmx256M -XX:PermSize=16M -XX:MaxPermSize=256M" CATALINA_HOME=/usr/local/tomcat-7 CATALINA_BASE=$PWD TOMCAT_USER=tomcat export JAVA_HOME JAVA_OPTS CATALINA_HOME CATALINA_BASE #定义函数 start() { su $TOMCAT_USER $CATALINA_HOME/bin/startup.sh } stop() { su $TOMCAT_USER $CATALINA_HOME/bin/shutdown.sh } restart() { stop sleep 3 start } #接受传递的参数做相应的操作 case "$1" in start) $1 ;; stop) $1 ;; restart) $1 ;; *) echo "Usage: $0{start|stop|restart}" && exit 1 ;; esac
在启动参数中“JAVA_OPTS="-server -Djava.library.path=/usr/local/apr/lib -Xms256M -Xmx256M -XX:PermSize=16M -XX:MaxPermSize=256M”,对这些启动参数作一些说明:
-server:只要tomcat运行在生产环境都应该加上此参数,因为tomcat默认是以一种叫java �Cclient的模式来运行的,server即意味着你的tomcat是以真实的production的模式在运行的,这也就意味着你的tomcat以server模式运行时将拥有:更大、更高的并发处理能力,更快更强捷的JVM垃圾回收机制,可以获得更多的负载与吞吐量。
-Djava.library.path=/usr/local/apr/lib:这是显式的指定让tomcat运行为APR模式时APR相关的库文件的路径
-Xms256M -Xmx256M:JVM虚拟机堆内存的大小, -Xms是设置初始堆大小, -Xmx是设置最大堆大小;初始堆大小与最大堆大小建议设置成相同的数值,如果数值设置不相同,系统在刚开始负载较轻时只是开辟了 -Xms的堆大小,但随着访问量的增多,内存不够用时,系统就会去开辟更多的堆内存,直到-Xmx大小,一段时间后访问量又减少,那系统就会调用垃圾回收器回收不用的内存,而调用垃圾回收器会消耗大量的CPU资源,可能会导致网站页面的卡顿现象,所以一开始就把两个数值设置为相同,让系统更能高效的使用内存。那这两个值到底应该设置为多少?这个值受限于系统的物理内存大小、虚拟内存大小、以及系统是32位还是64位,32位系统理论上只能用到2GB的内存,但在实际中这个值还会更小。在生产环境下,可以用“java -Xmx***M -version”来测试系统可支持的最大堆内存大小,如果系统支持你测试的值那会返回java的版本信息,否则系统不支持你所测试的值,下边在我的测试上举个例子。
[root@nod3 ~]# /usr/java/latest/bin/java -Xmx1024M -version java version "1.7.0_09" Java(TM) SE Runtime Environment (build 1.7.0_09-b05) Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode) [root@nod3 ~]# /usr/java/latest/bin/java -Xmx2048M -version java version "1.7.0_09" Java(TM) SE Runtime Environment (build 1.7.0_09-b05) Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)
我这里是64位的操作系统,对堆内存可使用大小是无限制的,所以在生产环境下也建议使用64位的操作系统,有一点需要注意:java -Xmx***M version 命令来测试的最大堆内存是 -Xmx与 -XX:PermSize的和 比如系统支持最大的jvm堆大小事1.5G,那 -Xmx1024m -XX:PermSize=768M 是无法运行的。
-XX:PermSize=16M -XX:MaxPermSize=256M:这两个参数是设置非堆内存(即永生代内存大小)大小的初始值和最大值,默认时 -XX:PermSize是物理内存的1/64,-XX:MaxPermSize是物理内存的1/4
对启动参数进行优化后可以用jmap命令来验证,如下:
[root@nod3 ~]# jps 1796 Jps 1623 Bootstrap #获得实例的进程ID [root@nod3 ~]# /usr/java/latest/bin/jmap -heap 1623 Attaching to process ID 1623, please wait... Debugger attached successfully. Server compiler detected. JVM version is 23.5-b02 using thread-local object allocation. Mark Sweep Compact GC Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 268435456 (256.0MB) #最大堆大小 NewSize = 1310720 (1.25MB) MaxNewSize = 17592186044415 MB OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 16777216 (16.0MB) #永久区的初始化大小 MaxPermSize = 268435456 (256.0MB) #永久区的最大值 G1HeapRegionSize = 0 (0.0MB) Heap Usage: New Generation (Eden + 1 Survivor Space): capacity = 80543744 (76.8125MB) used = 66939240 (63.838233947753906MB) free = 13604504 (12.974266052246094MB) 83.10917356908564% used Eden Space: capacity = 71630848 (68.3125MB) used = 66939240 (63.838233947753906MB) free = 4691608 (4.474266052246094MB) 93.4502967213232% used From Space: capacity = 8912896 (8.5MB) used = 0 (0.0MB) free = 8912896 (8.5MB) 0.0% used To Space: capacity = 8912896 (8.5MB) used = 0 (0.0MB) free = 8912896 (8.5MB) 0.0% used tenured generation: capacity = 178978816 (170.6875MB) used = 0 (0.0MB) free = 178978816 (170.6875MB) 0.0% used Perm Generation: capacity = 16777216 (16.0MB) used = 14283776 (13.6220703125MB) free = 2493440 (2.3779296875MB) 85.137939453125% used 7804 interned Strings occupying 639576 bytes
tomcat的启动参数有许多,这里只是简单介绍几个常用的,如果想了解想多的信息请google或上官方网站去查找。
2.2、容器内优化
在容器内优化中,主要是对http连接器或ajp连接器中做些连接池、并发处理相关的参数定义,下边给出一个在http连接器中已做过优化的配置参数:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" URIEncoding="UTF-8" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" disableUploadTimeout="true" maxThreads="300" acceptCount="300" compression="on" compressionMinSize="2048" compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" connectionTimeout="20000" redirectPort="8443" />
minSpareThreads:表示定义最低数量的进程处于运行中,即表示在tomcat启动后,预先生成这样数量的线程等待用户的接入,有点类似httpd中的prefork模式中预先生成一些进程来等待接受请求
maxSpareThreads:表示如果空闲的进程多于这个值,那就把多余的线程中止来释放资源
enableLookups:true开启域名反解,false关闭域名反解,一般都应该设置为false
maxThreads:表示tomcat所能创建的最大线程数,即tomcat的最大并发能力,tomcat7中默认是200
acceptCount:tomcat的的处理能力达到maxThreads设定的值后,接下来的连接放入acceptCount设定的队列中,tomcat7中默认是100
compression:是否启用压缩功能,on为启用,off为禁用,默认是off。启用压缩功能能节约带宽,但会占用更多的cpu资源,这个视实际情况而定到底是否启用压缩功能,在实际环境中压缩的功能一般放在前端的httpd或nginx上来处理。
connectionTimeout:设置网络连接超时时间,单位为毫秒
网上关于tomcat优化的帖子有许多,有些设置的参数看起就一大坨,但那些设置并不一定适合你的环境,而且还有些是错误的,所以在优化自己的tomcat时,在不确定参数是否有效时,这时你就应该参数官方的文档了。针对tomcat 7关于http连接器的参数设置请求参考这里http://tomcat.apache.org/tomcat-7.0-doc/config/http.html,而关于ajp连接的参数配置请参考这里进行设置http://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html。
3、总结
通过对启动参数和连接器内的参数优化,tomcat会表示出不一样的性能,但不要忘记了系统本身的优化,如果前端部署了nginx或apache做反应代理话,那代理软件也应该做一些优化,优化不可能只是一个部件的调整,最关键的是在优化后应该做压力测试,让实际的测试数据说话,看下你优化的成果怎样。
参考资料:
http://blog.csdn.net/lifetragedy/article/details/7708724
http://nolinux.blog.51cto.com/4824967/1608940
https://blog.linuxeye.com/413.html
http://passover.blog.51cto.com/2431658/732629
http://blog.chinaunix.net/uid-23049797-id-4811130.html
http://blog.chinaunix.net/uid-23049797-id-4811130.html
http://netexr.blog.51cto.com/2480285/1259882
http://feihan21.blog.51cto.com/1364153/1320295
http://www.oschina.net/translate/tomcat-performance-tuning
http://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html
http://tomcat.apache.org/tomcat-7.0-doc/config/http.html