目录

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基本安全加固与优化_第1张图片

输出信息就包括了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基本安全加固与优化_第2张图片

这里tomcat的版本信息就被修改了。想隐藏tomcat的版本信息还可以自定义错误页面,让出错信息定义到一个我们自己的页面上,这样也可以达到同样的效果。

1.2、安全加固之禁用tomcat管理页面

    默认时tomcat自带了manager的管理接口,通过此接口可以对项目进行管理,管理页面见下图:

tomcat基本安全加固与优化_第3张图片

但在实际的工作中很少有机会使用此接口,所以应该禁用,不禁用此接口会带来潜在的安全风险。我们只需要删除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
.......
   #原有的注释掉
    
.......


并且还会把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 –client的模式来运行的,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连接器中已做过优化的配置参数:

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