Home | 简体中文 | 繁体中文 | 杂文 | 知乎专栏 | Github | OSChina 博客 | 云社区 | 云栖社区 | Facebook | Linkedin | 视频教程 | 打赏(Donations) | About
知乎专栏多维度架构 微信号 netkiller-ebook | QQ群:128659835 请注明“读者”

第 26 章 Server

目录

26.1. Linux 系统安全与优化配置
26.1.1. Openssh 安全配置
26.1.1.1. 禁止root用户登录
26.1.1.2. 限制SSH验证重试次数
26.1.1.3. 禁止证书登陆
26.1.1.4. 使用证书替代密码认证
26.1.1.5. 图形窗口客户端记忆密码的问题
26.1.1.6. 关闭 GSSAPI
26.1.1.7. 禁止SSH端口映射
26.1.1.8. IP地址限制
26.1.1.9. 禁止SSH密码穷举
26.1.2. Shell 安全
26.1.2.1. .history 文件
26.1.2.2. sudo 安全问题
26.1.2.3. 临时文件安全
26.1.2.4. 执行权限
26.1.3. 防火墙
26.1.3.1. 策略
26.1.3.2. 防止成为跳板机
26.1.3.3. 端口安全
26.1.3.4. 封锁特定字符串
26.1.4. Linux 系统资源调配
26.1.4.1. /etc/security/limits.conf
26.1.4.2. 关闭写磁盘I/O功能
26.1.5. PAM 插件认证加固配置
26.1.5.1. pam_tally2.so
26.1.5.2. pam_listfile.so
26.1.5.3. pam_access.so
26.1.5.4. pam_wheel.so
26.2. Tomcat 安全配置与性能优化
26.2.1. JVM
26.2.1.1. 使用 Server JRE 替代JDK。
26.2.1.2. JAVA_OPTS
26.2.1.3. java.security 优化
26.2.2. Tomcat 优化
26.2.2.1. maxThreads 连接数限制
26.2.2.2. 虚拟主机
26.2.2.3. 压缩传输
26.2.3. Tomcat 安全配置
26.2.3.1. 禁用8005端口
26.2.3.2. 安装后初始化配置
26.2.3.2.1. 隐藏版本信息
26.2.3.2.2. 应用程序安全
26.2.3.2.3. JSESSIONID
26.2.3.3. 启动用户与端口
26.2.4. 如何部署应用程序
26.2.5. 延伸阅读
26.3. PHP 安全与性能优化
26.3.1. Apache mod_php / php-fpm
26.3.1.1. 用户权限
26.3.1.1.1. Apache
26.3.1.1.2. Nginx / lighttpd + fastcgi
26.3.1.2. web server 版本信息
26.3.1.3. php_flag / php_admin_flag
26.3.1.4. 防止URL注入
26.3.2. php.ini
26.3.2.1. Magic quotes
26.3.2.2. 危险PHP函数
26.3.2.2.1. chdir()函数安全演示
26.3.2.3. 隐藏PHP版本信息
26.3.2.4. session名字可以泄露你的服务器采用php技术
26.3.2.5. 隐藏PHP出错信息
26.3.2.6. open_basedir 防止操作web环境意外文件目录
26.3.3. 开发于安全
26.3.3.1. 彻底解决目录于文件的安全
26.3.3.2. 目录访问控制
26.3.3.3. Session / Cookie安全
26.3.3.4. 注入安全
26.3.3.4.1. 禁止输出调试信息
26.3.3.4.2. 预防SQL注入攻击
26.3.3.4.3. SHELL 命令注入
26.3.4. 执行效率
26.3.4.1. timeout
26.3.4.1.1. mysql
26.3.4.2. 浏览器上传文件尺寸控制
26.3.5. 服务器版本信息
26.4. 环境安装模板化
26.4.1. 云主机初始化
26.4.2. CentOS 7 初始化
26.4.3. Nginx
26.4.4. Tomcat
26.4.5. Node.js
26.4.6. MongoDB
26.5. 时间同步
26.6. 邮件系统
26.6.1. Mailing List
26.7. TPC
26.8. IOPS (Input/Output Operations Per Second, pronounced i-ops)
26.9. rPerf
26.10. 磁盘规划
26.10.1. 物理隔离
26.10.2. 硬件逻辑卷隔离
26.11. Distributed File System(簇文件系统)
26.11.1. FC 光纤存储
26.11.2. 聚合文件系统
26.11.3. 全局文件系统
26.11.4. 负载均衡文件系统
26.11.5. 网络块设备
26.11.6. Storage 存储
26.11.6.1. 存储种类
26.11.6.1.1. Direct Attached Storage
26.11.6.1.2. Network-attached storage
26.11.6.1.3. Storage area network
26.11.6.2. RAID
26.11.6.2.1. 缓存服务器
26.11.6.2.2. Web 服务器
26.11.6.2.3. 数据库
26.11.6.2.4. 数据备份
26.11.6.3. File System 文件系统
26.11.6.3.1. Distributed File System(DFS)
26.11.6.4. 数据访问协议
26.11.6.5. 数据管理
26.11.6.5.1. Share 共享
26.11.6.5.2. Mirror 远程镜像同步
26.11.6.5.3. 压缩与重复数据消除
26.11.6.5.4. Backup 备份与恢复
26.11.6.5.5. 故障报告
26.11.7. 磁盘快照
26.12. iDRAC / iLO / IMM

26.1. Linux 系统安全与优化配置

26.1.1. Openssh 安全配置

这节主要讲与SSH有关的安全配置

26.1.1.1. 禁止root用户登录

只允许普通用户登陆,然后通过su命令切换到root用过。后面还会将怎样限制su命令

			
PermitRootLogin no
			
			

26.1.1.2. 限制SSH验证重试次数

超过3次socket连接会断开,效果不明显,有一点点用。

			
MaxAuthTries 3
			
			

26.1.1.3. 禁止证书登陆

证书登陆非常安全,但是很有可能正常用户在你不知道情况下,给你安装了一个证书,他随时都可能进入你的系统

任何一个有权限的用户都能很方便的植入一个证书到 .ssh/authorized_keys 文件中

			
PubkeyAuthentication no
AuthorizedKeysFile /dev/null
			
			

26.1.1.4. 使用证书替代密码认证

是不是自相矛盾? 这个跟上面讲的正好相反,这里只允许使用key文件登陆。

			
PasswordAuthentication no
			
			

这种方式比起密码要安全的多,唯一要注意的地方就是证书被拷贝 ,建议你给证书加上 passphrase。

证书的 passphrase 是可以通过openssl工具将其剥离的,SSH证书我没有试过,但是原理都差不多。

26.1.1.5. 图形窗口客户端记忆密码的问题

当你使用XShell, Xftp, WinSCP, SecureCRT, SecureFX ......等等软件登录时,该软件都提供记住密码的功能,使你下次再登陆的时候无须输入密码就可以进入系统。这样做的确非常方便,

但是你是否想过你的电脑一旦丢失或者被其他人进入,那有多么危险。我之前每天背着笔记本电脑上班,上面安装着XShell并且密码全部记忆在里面。这使我意识到一点电脑丢失,有多么可怕。

禁止SSH客户端记住密码,你不要要求别人那么做。你也无法控制,最终我找到了一种解决方案。

			
ChallengeResponseAuthentication yes
			
			

每次登陆都回提示你输入密码。密码保存也无效。

26.1.1.6. 关闭 GSSAPI

			
GSSAPIAuthentication no
#GSSAPIAuthentication yes
#GSSAPICleanupCredentials yes
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
			
			

26.1.1.7. 禁止SSH端口映射

禁止使用SSH映射Socks5翻墙等等

			
AllowTcpForwarding no
			
			

26.1.1.8. IP地址限制

只允许通过192.168.2.1,192.168.2.2 访问本机

			
# vim /etc/hosts.allow
sshd:192.168.2.1,192.168.2.2
			
			

禁止所有人访问本机

			
# vim /etc/hosts.deny
sshd:ALL
			
			

上面使白名单策略,你也可以采用黑名单策略。

26.1.1.9. 禁止SSH密码穷举

骇客常常使用骇客字典穷举你的SSH密码,使用下面脚本可以封杀频繁链接的IP地址

			
#!/bin/bash
########################################
# Homepage: http://netkiller.github.io
# Author: neo <netkiller@msn.com>
########################################
PIPE=/var/tmp/pipe
pidfile=/var/tmp/$0.pid
BLACKLIST=/var/tmp/black.lst
WHITELIST=/var/tmp/white.lst

LOGFILE=/var/log/secure
DAY=5
########################################

if [ -z "$( egrep "CentOS|7." /etc/centos-release)" ]; then
	echo 'Only for CentOS 7.x'
	exit
fi

if [ -f $BLACKLIST ]; then
	find $BLACKLIST -type f -mtime +${DAY} -delete
fi

if [ ! -f ${BLACKLIST} ]; then
    touch ${BLACKLIST}
fi

if [ ! -f ${WHITELIST} ]; then
    touch ${WHITELIST}
fi

for ipaddr in $(grep rhost ${LOGFILE} | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | sort | uniq -c | sort -r -n | head -n 10| awk '{print $2}')
do

    if [ $(grep -c $ipaddr ${WHITELIST}) -gt 0 ]; then
		continue
    fi

    if [ $(grep -c $ipaddr ${BLACKLIST}) -eq 0 ] ; then
		echo $ipaddr >> ${BLACKLIST}
        iptables -I INPUT -p tcp --dport 22 -s $ipaddr -j DROP
        #iptables -I INPUT -s $ipaddr -j DROP
    fi
done			
			
			

26.1.2. Shell 安全

26.1.2.1. .history 文件

SA的操作记录问题

通过~/.bash_history文件记录系统管理员的操作记录,定制.bash_history格式

			
HISTSIZE=1000
HISTFILESIZE=2000
HISTTIMEFORMAT="%Y-%m-%d-%H:%M:%S "
export HISTTIMEFORMAT
			
			

看看实际效果

			
$ history | head
    1  2012-02-27-09:10:45 do-release-upgrade
    2  2012-02-27-09:10:45 vim /etc/network/interfaces
    3  2012-02-27-09:10:45 vi /etc/network/interfaces
    4  2012-02-27-09:10:45 ping www.163.com
			
			

26.1.2.2. sudo 安全问题

/etc/sudoers

			
Cmnd_Alias WEBMASTER = /srv/nginx/sbin/nginx, /srv/php/sbin/php-fpm, !/srv/mysql/bin/*
www localhost = NETWORKING, SERVICES, DELEGATING, PROCESSES, WEBMASTER

Cmnd_Alias Database = /usr/bin/mysqldump, /srv/mysql/bin/mysql, /u01/oracle/10.x.x/bin/sqlplus
mysql localhost = NETWORKING, SERVICES, DELEGATING, PROCESSES, WEBMASTER, Database
			
			

使用www用户测试登录,无误后修改SSH配置文件,禁止root登录。

			
vim /etc/ssh/sshd_config
PermitRootLogin no
			
			

然后在测试从www sudo 执行命令, 可能成功启动nginx 与 php-fpm

26.1.2.3. 临时文件安全

临时文件不应该有执行权限

/tmp

			
/dev/sda3 /tmp ext4 nosuid,noexec,nodev,rw 0 0
			
			

同时使用符号连接将/var/tmp 指向 /tmp

/dev/shm

			
none /dev/shm tmpfs defaults,nosuid,noexec,rw 0 0
			
			

26.1.2.4. 执行权限

以数据库为例,从安全角度考虑我们需要如下更改

			
chown mysql:mysql /usr/bin/mysql*
chmod 700 /usr/bin/mysql*
			
			

mysql用户是DBA专用用户, 其他用户将不能执行mysql等命令。

26.1.3. 防火墙

开启防火墙

		
lokkit --enabled
		
		

26.1.3.1. 策略

默认INPUT,FORWARD,OUTPUT 三个都是ACCEPT

			
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
			
			

从安全的角度出发,INPUT,FORWARD,OUTPUT 三个都是DROP最安全,但配置的时候会给你带来非常多的不可预料的麻烦。

			
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT DROP
			
			

折中的方案,也是打多少硬件防火墙厂商所采用的方案,他们都是采用INPUT默认禁用所有,OUTPUT默认允许所有,你只要关注INPUT规则即可。

			
-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
			
			

26.1.3.2. 防止成为跳板机

跳板机就是用户首先登陆任意一台服务器后,由该服务器在登陆另外一台服务器。

封锁22等端口,避免相互跳转

			
iptables -A OUTPUT -p tcp -m multiport --dports 22,21,873 -j REJECT
/etc/init.d/iptables save
iptables -L -n
			
			

web 服务器禁止使用ssh,作为跳板机

用户将不能使用ssh命令登陆到其他电脑

26.1.3.3. 端口安全

有一种情况,例如你的服务器被植入了木马,木马将开启一个Socket端口给远程骇客接入进来,通常会启动一个类似telnet服务器,怎样防止未经允许的程序监听一个端口呢?

			
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT  
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT 
-A INPUT -m state --state INVALID,NEW -j DROP
			
			

用法

  1. systemctl stop iptables

  2. 启动 httpd / nginx

  3. systemctl start iptables

注意必须按照上面的步骤,如果你试图如下尝试将失败

  1. systemctl start iptables

  2. 启动 httpd / nginx

80端口将无法对外提供服务,因为当 -A INPUT -m state --state INVALID,NEW -j DROP 运行以后,任何试图监听端口的程序将被拒绝。

26.1.3.4. 封锁特定字符串

下面的例子是拒绝爬虫

			
# iptables -A INPUT -p tcp --dport 80 -m string --algo bm --string "Spider" -j DROP
# iptables -A INPUT -p tcp --dport 80 -m string --algo bm --string "Baidu" -j DROP
# iptables -A INPUT -p tcp --dport 80 -m string --algo bm --string "Robat" -j DROP
			
			

26.1.4. Linux 系统资源调配

26.1.4.1. /etc/security/limits.conf

很多资料上是这么写的

			
* soft nofile 65535
* hard nofile 65535
 			
			

这样做是偷懒,会带来很多问题,如果你的服务器被攻击,由于你的设置,系统将耗光你的资源,直到没有任何响应为止,你可能键盘输入都成问题,你不得不重启服务器,但你会发现重启只能维持短暂几分钟,又会陷入无响应状态。

			
nobody soft nofile 4096
nobody hard nofile 8192
			
			

为什么会设置为nobody用户呢?因为root用户启动系统后web 服务器会使用nobody用户创建子进程,socket连接实际上是nobody用户在处理。root 仅仅是守护父进程。

			
mysql soft nofile 2048
mysql hard nofile 2048
			
			

针对 mysql 做限制

[提示]提示

关于 nofile 即打开文件数,这个跟socket有非常紧密的关系,在linux系统中任何设备都被看做是一个文件(字符设备),你连接一个鼠标,键盘,摄像头,硬盘等等都被看作打开一个设备文件,所以默认1024是远远不够的。

26.1.4.2. 关闭写磁盘I/O功能

对于某些文件没必要记录文件的访问时间,由其是在高并发的IO密集操作的环境下,通过两个参数可以实现noatime,nodiratime减少不必要的系统IO资源。

编辑/etc/fstab 添加 noatime,nodiratime 参数

			
/dev/sdb1    /www          ext4    noatime,nodiratime        0 0
			
			

26.1.5. PAM 插件认证加固配置

配置文件

		
ls  /etc/pam.d/
chfn         crond                login    passwd            remote    runuser-l          smtp          ssh-keycat  sudo-i       system-auth-ac
chsh         fingerprint-auth     newrole  password-auth     run_init  smartcard-auth     smtp.postfix  su          su-l
config-util  fingerprint-auth-ac  other    password-auth-ac  runuser   smartcard-auth-ac  sshd          sudo        system-auth
		
		

认证插件

		
ls /lib64/security/
		
		

26.1.5.1. pam_tally2.so

此模块的功能是,登陆错误输入密码3次,5分钟后自动解禁,在未解禁期间输入正确密码也无法登陆。

在配置文件 /etc/pam.d/sshd 顶端加入

			
auth required pam_tally2.so deny=3 onerr=fail unlock_time=300
			
			

查看失败次数

			
# pam_tally2
Login           Failures Latest failure     From
root               14    07/12/13 15:44:37  192.168.6.2
neo                 8    07/12/13 15:45:36  192.168.6.2
			
			

重置计数器

			
# pam_tally2 -r -u root
Login           Failures Latest failure     From
root               14    07/12/13 15:44:37  192.168.6.2

# pam_tally2 -r -u neo
Login           Failures Latest failure     From
neo                 8    07/12/13 15:45:36  192.168.6.2
			
			

pam_tally2 计数器日志保存在 /var/log/tallylog 注意,这是二进制格式的文件

例 26.1. /etc/pam.d/sshd - pam_tally2.so

				
# cat  /etc/pam.d/sshd
#%PAM-1.0
auth required pam_tally2.so deny=3 onerr=fail unlock_time=300

auth	   required	pam_sepermit.so
auth       include      password-auth
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    required     pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session    required     pam_selinux.so open env_params
session    optional     pam_keyinit.so force revoke
session    include      password-auth
				
				

以上配置root用户不受限制, 如果需要限制root用户,参考下面

auth required pam_tally2.so deny=3 unlock_time=5 even_deny_root root_unlock_time=1800
			

26.1.5.2. pam_listfile.so

用户登陆限制

将下面一行添加到 /etc/pam.d/sshd 中,这里采用白名单方式,你也可以采用黑名单方式

auth       required     pam_listfile.so item=user sense=allow file=/etc/ssh/whitelist onerr=fail
			

将允许登陆的用户添加到 /etc/ssh/whitelist,除此之外的用户将不能通过ssh登陆到你的系统

# cat /etc/ssh/whitelist
neo
www
			

例 26.2. /etc/pam.d/sshd - pam_listfile.so

# cat /etc/pam.d/sshd
#%PAM-1.0
auth       required     pam_listfile.so item=user sense=allow file=/etc/ssh/whitelist onerr=fail
auth       required     pam_tally2.so deny=3 onerr=fail unlock_time=300

auth	   required	pam_sepermit.so
auth       include      password-auth
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
# pam_selinux.so close should be the first session rule
session    required     pam_selinux.so close
session    required     pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session    required     pam_selinux.so open env_params
session    optional     pam_keyinit.so force revoke
session    include      password-auth
				

sense=allow 白名单方式, sense=deny 黑名单方式

auth       required     pam_listfile.so item=user sense=deny file=/etc/ssh/blacklist onerr=fail
			

更多细节请查看手册 $ man pam_listfile

26.1.5.3. pam_access.so

编辑 /etc/pam.d/sshd 文件,加入下面一行

account required pam_access.so
			

保存后重启sshd进程

编辑 /etc/security/access.conf 文件

			
cat >>  /etc/security/access.conf << EOF

- : root : ALL EXCEPT 192.168.6.1
EOF
			
			

只能通过 192.168.6.1 登陆, 添加多个IP地址

- : root : ALL EXCEPT 192.168.6.1 192.168.6.2
			

测试是否生效

26.1.5.4. pam_wheel.so

限制普通用户通过su命令提升权限至root. 只有属于wheel组的用户允许通过su切换到root用户

编辑 /etc/pam.d/su 文件,去掉下面的注释

auth		required	pam_wheel.so use_uid
			

修改用户组别,添加到wheel组

# usermod -G wheel www

# id www
uid=501(www) gid=501(www) groups=501(www),10(wheel)
			

没有加入到wheel组的用户使用su时会提示密码不正确。

$ su - root
Password:
su: incorrect password