网站环境
LAMP。啥是 LAMP?它是 Linux + Apache + MySQL + PHP/Perl 的缩写,是一种简洁、强劲、受到广泛支持的网站环境。国内似乎有不少人推荐把 A(Apache) 换成 N(nginx),但是我不推荐这样,因为 nginx 相对 Apache 来说,对 PHP 的支持更差一些,而且缺少 .htaccess 之类目录级配置文件的支持, rewrite 功能也不是很好用。最主要的,LAMP 还是 Ubuntu Server 官方推荐的网站环境,所以,我选择 LAMP!
但是,如果你真的对 nginx 有一些偏爱的话,还是可以加一份 nginx 上去的,这时候可以把 nginx 作为反向代理使用,能一定程度上增强网站的抗压能力,特别是一些静态文件如图片等。
三、连接你的 Ubuntu VPS
Ubuntu Server 采用的是每六个月出一个新版本的政策,但是每两年会有一个「长期支持版」,简称「LTS」,LTS 版的 Ubuntu Server 支持期长达五年,足够用到服务器淘汰、报废……本教程采用的是 Ubuntu Server 12.04 LTS 版,能用到 2017 年 4 月份……你也可以采用非 LTS 的版本如 12.10。
在 VPS 控制面板安装好操作系统之后,即可连接操作了。GNU/Linux 服务器的大部分操作都是通过命令来完成的,而 OpenSSH 是一种远程登录 GNU/Linux 的优秀协议。Windows 用户需要下载 Tunnelier 等软件填入主机、用户名、密码进行连接,OS X 和 GNU/Linux 用户可直接在终端中使用 ssh 命令进行连接。比如 VPS 服务商提供给你的 IP 是 10.0.0.1,用户名是 root,那么连接命令即是:
ssh [email protected]然后按提示输入密码即可。GNU/Linux 的密码输入一般是不回显的,即你看不到你输入了什么,但是你的确输入进去了,输入完成后回车即可开始登录,第一次登录的时候会提示保存公钥,确认即可。
代码如下 | 复制代码 |
wzyboy@vermilion:~$ ssh [email protected] * Documentation: https://help.ubuntu.com/ |
至此你就连上了你的 VPS,以后的命令都将在这个窗口中敲字完成了。如前面所说,GNU/Linux 服务器的维护基本上都是通过命令来完成的,所以本教程中不可避免地涉及到一些命令。先来个简单的吧,更新 Ubuntu 的软件包:
代码如下 | 复制代码 |
root@xehost:~# apt-get update && apt-get upgrade |
该操作会执行一会儿,最后问你是否继续,回答 y 或者直接按回车即可,屏幕上再次跑过大量字符,等它停下来的时候,就说明升级完成了,期间如果包管理器问你问题的话,一般保持默认选择即可。注意:这个命令是不升级内核的,如果你想升级内核的话,请把 upgrade 改成 dist-upgrade,可能需要修改对应的 GRUB 设置以在下次启动时启动到新内核。
刚才的命令中,apt-get 是 Debian / Ubuntu 等发行版的升级管理器,它的使用方法非常简明易懂,比如,我们要安装 Vim 这个非常好用的编辑器的话,执行以下命令即可:
代码如下 | 复制代码 |
root@xehost:~# apt-get install vim Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: libpython2.7 vim-runtime Suggested packages: ctags vim-doc vim-scripts The following NEW packages will be installed: libpython2.7 vim vim-runtime 0 upgraded, 3 newly installed, 0 to remove and 1 not upgraded. Need to get 8,513 kB of archives. After this operation, 28.0 MB of additional disk space will be used. Do you want to continue [Y/n]?回答 y 或者直接回车 |
,即可安装 Vim 编辑器。Vim 默认的颜色主题如果觉得不好看的话,可以使用 echo 'colorscheme evening' > .vimrc 命令将其改成 evening 方案,这在黑色背景下看得比较清楚。
如果要删除某个软件包,也是比较容易的,用 remove 或者 purge 即可,后者会连配置文件一起清除,比如要清除掉 cryptsetup 这个软件包,就是 apt-get purge cryptsetup。
Debian / Ubuntu 的包管理器是 dpkg,有一些 dpkg 开头的命令。比如要更改时区,就是 dpkg-reconfigure tzdata,会有很亲民的选择界面出现,选择 Asia/Shanghai 即可改成 UTC+8 时区。
Ubuntu VPS 的基本操作讲解完毕,下面开始装网站环境。
四、安装 LAMP + nginx
安装 LAMP
我说啥来着的?Ubuntu Server 是个非常好用的发行版,用在服务器上是很方便很爽的。在某些落后还自称「行业标准」的发行版上,安装 LAMP 要许多条复杂的命令,不少部件还因为太老要自己花费大量 CPU 和硬盘去编译,但是在 Ubuntu 下,只要简单的一条命令:www.111com.net
tasksel install lamp-server接下来就是全自动化的操作了,期间会提示你设定一个 MySQL 的 root 密码,其他都不需要人工干预,整个过程两分钟内即可完成。该命令中 tasksel 是 Ubuntu 的一个套件安装工具,可以很方便地安装一些预定义的套件。如果有的 VPS 提示没有 tasksel 命令的话,apt-get install tasksel 装一个即可。如果还想装一个 phpMyAdmin 怎么办? apt-get install phpmyadmin 即可!期间会让你选择你的网站环境,按空格选中 apache2 然后 Ok 就行了,还会让你输入两个密码,一个是 MySQL 的 root 密码,这就是刚才你在安装 LAMP 的时候设定的,希望你没有忘记哈。另一个是设置 phpMyAdmin 在 MySQL 里的程序密码,这个可以直接回车,让它随机生成一个复杂的密码,反正这个也不要人类记忆的……
配置 Apache
如果需要把 nginx 作为 Apache 的反向代理的话,Apache 是需要配置一下的,如果你只想直接用 Apache 的话,请跳过此段及下段。
需要说明的是,Debian / Ubuntu 的 Apache 是经过高度修改过的,与上游有较大区别,特别是在配置文件结构上,增加了许多方便的命令、脚本。这些便民的东西在别的发行版上是没有的。
由于要把 nginx 作为 Apache 的反向代理,所以要让 nginx 监听 80 端口而让 Apache 监听一个别的,比如 8080 端口。需要对 /etc/apache2/ports.conf 做一下修改。用 Vim 打开这个文件,定位到 Listen 80 这一行,改成 Listen 127.0.0.1:8080,另外上面的 NameVirtualHost 的端口也要改成 8080。111com.net
啥,Vim 怎么用?在 Vim 里有两种基本模式,一种是「普通」,一种是「编辑」,要进入「编辑」的话需要按 i,要回到「普通」的话按 Esc 即可,Vim 新手的话可以先用方向键定位到相应的位置,然后再按 i 进入「编辑」,进行相应的修改后按 Esc 回到「普通」,再用 :wq 回车命令保存退出。
改完后重启 Apache 服务: service apache2 restart。Ubuntu 里重启某服务基本都是这样的格式。
安装和配置 nginx
怎么在 Ubuntu Server 里装 nginx?如果你认真地看了上面的内容,已经能猜到了吧:
apt-get install nginx一条命令,搞定。配置起来的话,在 /etc/nginx/sites-enabled/ 里建立与 Apache 的 /etc/apache2/sites-enabled/ 中对应的配置文件然后重启 nginx 即可。配置文件示例:
代码如下 | 复制代码 |
server { access_log /var/log/nginx/access.log; location / { } |
如果需要真实 IP 模块的话,可以安装 libapache2-mod-rpaf 软件包并将 /etc/apache2/mods-enabled/rpaf.conf 改成如下内容:
代码如下 | 复制代码 |
RPAFenable On |
现在我们再来做一些安全配置
基本安装配置
1. 不显示svn的版本号
vi /usr/local/nginx/conf/nginx.conf
server_tokens off;
2. 过滤.svn中的所有文件
location ~ ^(.*)/.svn/
{
deny all;
}
从svn中直接签出的代码中含有.svn和其中的一些文件。
2. 过滤phpinfo.php文件
location ~ ^(.*)/phpinfo.php
{
deny all;
}
3. nginx_status限制IP访问
location /nginx_status {
stub_status on;
access_log off;
allow x.x.x.x;
deny all;
}
5. 限制对工具目录的访问
location ~ ^(.*)/tools/
{
allow x.x.x.x;
deny all;
fastcgi_pass 192.168.2.11:9000;
fastcgi_index index.php;
include fcgi.conf;
}
PHP:
6. expose_php=off
阻止PHP发送 X-Powered-By
PHP/5.3.6-13ubuntu3.3 类似信息
Nginx
7. server_tokens off;
阻止发送Nginx的详细版本号
8.去掉 fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; 中的$nginx_version
阻止向cgi发送Nginx的版本号
9. fastcgi 中添加
set $fastcgi_sf $document_root$fastcgi_script_name;
if (!-e $fastcgi_sf) {
return 403;
}
Nginx默认配置文件和默认端口
◆ /usr/local/nginx/conf/ – Nginx服务器配置目录,/usr/local/nginx/conf/nginx.conf 是主配置文件
◆ /usr/local/nginx/html/ – 默认文档位置
◆ /usr/local/nginx/logs/ – 默认日志文件位置
◆ Nginx HTTP默认端口:TCP 80
◆ Nginx HTTPS默认端口:TCP 443
可以使用下面的命令测试Nginx的配置是否正确:
# /usr/local/nginx/sbin/nginx –t
输出示例:
the configuration file /usr/local/nginx/conf/nginx.conf syntax is okconfiguration file /usr/local/nginx/conf/nginx.conf test is successful
要让修改后的配置生效,执行下面的命令:
# /usr/local/nginx/sbin/nginx -s reload
如果要停止服务器,运行:
# /usr/local/nginx/sbin/nginx -s stop
1、开启SELinux
SELinux(安全增强的Linux)是一个Linux内核功能,它提供了一个机制支持访问控制安全策略,提供了巨大的安全保护能力,它可以防止大多数系统root级攻击,请参考“如何在CentOS/Red Hat系统上开启SELinux”(http://www.cyberciti.biz/faq/rhel-fedora-redhat-selinux-protection/)。
运行getsebool –a命令查看SELinux设置项:
getsebool -a | lessgetsebool -a | grep offgetsebool -a | grep o
然后使用setsebool命令开启需要的配置项,注意:开启SELinux后,在RHEL或CentOS上通常会增加2-8%的系统开销。
2、通过mount参数提供最低权限
为你的/html/php文件创建独立的分区,例如,创建一个/dev/sda5分区挂载在/ngnix上,确定/ngnix使用了noexec,nodev和nosetuid权限挂载。下面是我的一个挂载实例:
LABEL=/nginx /nginx ext3 defaults,nosuid,noexec,nodev 1 2
注意你需要使用fdisk和mkfs.ext3命令创建一个新分区。
3、通过/etc/sysctl.conf加固
可以通过/etc/sysctl.conf控制和配置Linux内核及网络设置。
另外,请参考:
# 避免放大攻击net.ipv4.icmp_echo_ignore_broadcasts = 1# 开启恶意icmp错误消息保护net.ipv4.icmp_ignore_bogus_error_responses = 1# 开启SYN洪水攻击保护net.ipv4.tcp_syncookies = 1# 开启并记录欺骗,源路由和重定向包net.ipv4.conf.all.log_martians = 1net.ipv4.conf.default.log_martians = 1# 处理无源路由的包net.ipv4.conf.all.accept_source_route = 0net.ipv4.conf.default.accept_source_route = 0# 开启反向路径过滤
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# 确保无人能修改路由表
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
# 不充当路由器
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# 开启execshild
kernel.exec-shield = 1
kernel.randomize_va_space = 1
# IPv6设置
net.ipv6.conf.default.router_solicitations = 0
net.ipv6.conf.default.accept_ra_rtr_pref = 0
net.ipv6.conf.default.accept_ra_pinfo = 0
net.ipv6.conf.default.accept_ra_defrtr = 0
net.ipv6.conf.default.autoconf = 0
net.ipv6.conf.default.dad_transmits = 0
net.ipv6.conf.default.max_addresses = 1
# 优化LB使用的端口
# 增加系统文件描述符限制
fs.file-max = 65535
# 允许更多的PIDs (减少滚动翻转问题); may break some programs 32768
kernel.pid_max = 65536
# 增加系统IP端口限制
net.ipv4.ip_local_port_range = 2000 65000
# 增加TCP最大缓冲区大小
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 87380 8388608
# 增加Linux自动调整TCP缓冲区限制
# 最小,默认和最大可使用的字节数
# 最大值不低于4MB,如果你使用非常高的BDP路径可以设置得更高
# Tcp窗口等
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_window_scaling = 1
4、移除所有不需要的Nginx模块
你需要最大限度地将Nginx加载的模块最小化,我的意思是满足Web服务器需要就可以了,多余的模块一个不留,例如,禁用SSI和autoindex模块的命令如下:
# ./configure --without-http_autoindex_module --without-http_ssi_module# make# make install
在编译Nginx服务器时,使用下面的命令查看哪些模块应该启用,哪些模块应该禁用:
# ./configure --help | less
禁用你不需要的Nginx模块。
修改Nginx版本头信息(可选),编辑src/http/ngx_http_header_filter_module.c:
# vi +48 src/http/ngx_http_header_filter_module.c
找到下面两行:
static char ngx_http_server_string[] = "Server: nginx" CRLF;static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
将其修改为:
static char ngx_http_server_string[] = "Server: Ninja Web Server" CRLF;static char ngx_http_server_full_string[] = "Server: Ninja Web Server" CRLF;
保存并关闭文件。现在可以开始编译服务器了,将下面的配置代码添加到nginx.conf中,禁止在所有自动产生的错误页面中显示Nginx版本号:
server_tokens off
5、使用mod_security(仅适用于后端Apache服务器)
Mod_security为Apache提供了一个应用程序级防火墙,为所有后端Apache Web服务器安装mod_security模块,可以阻止许多注入攻击。
6、配置SELinux策略加固Nginx
默认情况下,SELinux没有保护Nginx Web服务器,可以手动配置进行保护,首先安装SELinux编译时需要的支持包:
# yum -y install selinux-policy-targeted selinux-policy-devel
从项目主页(http://sourceforge.net/projects/selinuxnginx/)下载SELinux策略:
# cd /opt# wget 'http://downloads.sourceforge.net/project/selinuxnginx/se-ngix_1_0_10.tar.gz?use_mirror=nchc'
解压:
# tar -zxvf se-ngix_1_0_10.tar.gz
编译:
# cd se-ngix_1_0_10/nginx# make
输出示例:
Compiling targeted nginx module/usr/bin/checkmodule: loading policy configuration from tmp/nginx.tmp/usr/bin/checkmodule: policy configuration loaded/usr/bin/checkmodule: writing binary representation (version 6) to tmp/nginx.modCreating targeted nginx.pp policy packagerm tmp/nginx.mod.fc tmp/nginx.mod
安装生成的nginx.pp SELinux模块:
# /usr/sbin/semodule -i nginx.pp
7、通过iptables防火墙设置限制
下面的防火墙脚本可以阻止一切请求,只允许:
◆ 入站HTTP请求(TCP 80端口)
◆ 入站ICMP ping请求
◆ 出站NTP请求(端口123)
◆ 出站SMTP请求(TCP端口25)
#!/bin/bashIPT="/sbin/iptables"#### IPS ####### 获得服务器公共IPSERVER_IP=$(ifconfig eth0 | grep 'inet addr:' | awk -F'inet addr:' '{ print $2}' | awk '{ print $1}')LB1_IP="204.54.1.1"LB2_IP="204.54.1.2"# 实现某些智能逻辑,以便我们可以在LB2上使用damm脚本OTHER_LB=""SERVER_IP=""[[ "$SERVER_IP" == "$LB1_IP" ]] && OTHER_LB="$LB2_IP" || OTHER_LB="$LB1_IP"[[ "$OTHER_LB" =="$LB2_IP" ]] && OPP_LB="$LB1_IP" || OPP_LB="$LB2_IP"### IPs ###PUB_SSH_ONLY="122.xx.yy.zz/29" #### 文件 #####
BLOCKED_IP_TDB=/root/.fw/blocked.ip.txt
SPOOFIP="127.0.0.0/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 169.254.0.0/16 0.0.0.0/8 240.0.0.0/4 255.255.255.255/32 168.254.0.0/16 224.0.0.0/4 240.0.0.0/5 248.0.0.0/5 192.0.2.0/24"
BADIPS=$( [[ -f ${BLOCKED_IP_TDB} ]] && egrep -v "^#|^$" ${BLOCKED_IP_TDB})
### 接口 ###
PUB_IF="eth0" # public interface
LO_IF="lo" # loopback
VPN_IF="eth1" # vpn / private net
### 启动防火墙 ###
echo "Setting LB1 $(hostname) Firewall…"
# 删除和关闭一切
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
# 不受限制的lo访问
$IPT -A INPUT -i ${LO_IF} -j ACCEPT
$IPT -A OUTPUT -o ${LO_IF} -j ACCEPT
# 不受限制的vpn/pnet访问
$IPT -A INPUT -i ${VPN_IF} -j ACCEPT
$IPT -A OUTPUT -o ${VPN_IF} -j ACCEPT
# 删除sync
$IPT -A INPUT -i ${PUB_IF} -p tcp ! –syn -m state –state NEW -j DROP
# 删除碎片
$IPT -A INPUT -i ${PUB_IF} -f -j DROP
$IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags ALL FIN,URG,PSH -j DROP
$IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags ALL ALL -j DROP
# 删除空包
$IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags ALL NONE -m limit –limit 5/m –limit-burst 7 -j LOG –log-prefix " NULL Packets "
$IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags ALL NONE -j DROP
$IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags SYN,RST SYN,RST -j DROP
# 删除XMAS
$IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags SYN,FIN SYN,FIN -m limit –limit 5/m –limit-burst 7 -j LOG –log-prefix " XMAS Packets "
$IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags SYN,FIN SYN,FIN -j DROP
# 删除FIN包扫描
$IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags FIN,ACK FIN -m limit –limit 5/m –limit-burst 7 -j LOG –log-prefix " Fin Packets Scan "
$IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags FIN,ACK FIN -j DROP
$IPT -A INPUT -i ${PUB_IF} -p tcp –tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
# 记录并放弃广播/多播和无效数据包
$IPT -A INPUT -i ${PUB_IF} -m pkttype –pkt-type broadcast -j LOG –log-prefix " Broadcast "
$IPT -A INPUT -i ${PUB_IF} -m pkttype –pkt-type broadcast -j DROP
$IPT -A INPUT -i ${PUB_IF} -m pkttype –pkt-type multicast -j LOG –log-prefix " Multicast "
$IPT -A INPUT -i ${PUB_IF} -m pkttype –pkt-type multicast -j DROP
$IPT -A INPUT -i ${PUB_IF} -m state –state INVALID -j LOG –log-prefix " Invalid "
$IPT -A INPUT -i ${PUB_IF} -m state –state INVALID -j DROP
# 记录和阻止欺骗IP
$IPT -N spooflist
for ipblock in $SPOOFIP
do
$IPT -A spooflist -i ${PUB_IF} -s $ipblock -j LOG –log-prefix " SPOOF List Block "
$IPT -A spooflist -i ${PUB_IF} -s $ipblock -j DROP
done
$IPT -I INPUT -j spooflist
$IPT -I OUTPUT -j spooflist
$IPT -I FORWARD -j spooflist
# 只允许从选定的公共IP使用SSH
for ip in ${PUB_SSH_ONLY}
do $IPT -A INPUT -i ${PUB_IF} -s ${ip} -p tcp -d ${SERVER_IP} –destination-port 22 -j ACCEPT
$IPT -A OUTPUT -o ${PUB_IF} -d ${ip} -p tcp -s ${SERVER_IP} –sport 22 -j ACCEPT
done
# 允许入站ICMP ping
$IPT -A INPUT -i ${PUB_IF} -p icmp –icmp-type 8 -s 0/0 -m state –state NEW,ESTABLISHED,RELATED -m limit –limit 30/sec -j ACCEPT
$IPT -A OUTPUT -o ${PUB_IF} -p icmp –icmp-type 0 -d 0/0 -m state –state ESTABLISHED,RELATED -j ACCEPT
# 允许入站HTTP端口80
$IPT -A INPUT -i ${PUB_IF} -p tcp -s 0/0 –sport 1024:65535 –dport 80 -m state –state NEW,ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -o ${PUB_IF} -p tcp –sport 80 -d 0/0 –dport 1024:65535 -m state –state ESTABLISHED -j ACCEPT
# 允许出站NTP
$IPT -A OUTPUT -o ${PUB_IF} -p udp –dport 123 -m state –state NEW,ESTABLISHED -j ACCEPT
$IPT -A INPUT -i ${PUB_IF} -p udp –sport 123 -m state –state ESTABLISHED -j ACCEPT
# 允许出站SMTP
$IPT -A OUTPUT -o ${PUB_IF} -p tcp –dport 25 -m state –state NEW,ESTABLISHED -j ACCEPT
$IPT -A INPUT -i ${PUB_IF} -p tcp –sport 25 -m state –state ESTABLISHED -j ACCEPT
### 在这里添加其他规则 ####
#######################www.111cn.Net
# 删除并记录其它数据包
$IPT -A INPUT -m limit –limit 5/m –limit-burst 7 -j LOG –log-prefix " DEFAULT DROP "
$IPT -A INPUT -j DROP
exit 0
8、控制缓冲区溢出攻击
编辑nginx.conf设置所有客户端可用的缓冲区大小限制:
# vi /usr/local/nginx/conf/nginx.conf
具体设置如下:
## Start: Size Limits & Buffer Overflows ## client_body_buffer_size 1K;client_header_buffer_size 1k; client_max_body_size 1k; large_client_header_buffers 2 1k; ## END: Size Limits & Buffer Overflows ##
说明:
client_body_buffer_size 1k:默认是8k或16k,指定客户端请求主体缓冲区大小。
client_header_buffer_size 1k:指定来自客户端请求头的headerbuffer大小,对于大多数请求,1k的缓冲区大小已经足够,如果你自定义了消息头或有更大的Cookie,你可以增加其大小。
client_max_body_size 1k:客户端请求中可接受的主体最大大小,由请求头中的Content-Length表示,如果大小大于给定的尺寸,客户端将会收到一条“Request Entity Too Large(413)”的错误,如果你要通过POST方法上传文件,可以将该值设大一些。
large_client_header_buffers 2 1k:为客户端请求中较大的消息头指定的缓存最大数量和大小,默认情况下,一个缓冲区的大小等于页面的大小,根据平台的不同可能是4K或8K,如果在请求 连接的末尾状态转换为保持活动(keep-alive),这些缓冲区就被释放,2x1K将可以接收2KB数据的URI,这样有助于打击机器人攻击