Web运维之安全配置指导手册

一、【背景】

网站运维目前已是作为运维工作中的主要场景,每个企业都有各种业务及网站需要管理,其中安全作为企业业务上线前和生命周期中的持续监测和加固,更是运维工作者面对的主要工作,如何做好安全,为企业安全保驾护航,为业务稳定健康运行,至关重要,本期针对此目的,将手机整理相关网站运维安全知识,为安全运维提供参考。

特别鸣谢:https://blog.csdn.net/lmseo5hy/article/details/85048213

二、【网站运维】

2.1、【Tomcat】之安全观

Tomcat服务器是由一系列可以配置的组件构成,其中核心组件是Catalina Servlet,它是最顶层组件,Tomcat各组件是在server.xml(CATALINA_HOME\conf\server.xml)配置的。
Catalina Servlet,是作为Tomcat项目中所有其他Tomcat组件的顶层容器,代码中每个元素都代表一种 Tomcat 组件。这些元素可分为4类,如下所示:

1、顶层类元素: 包括元素和元素,Server是server.xml的最外层元素,Server可以包含多个Service组件,其中className—指定实现org.apache.catalina. Service接口的类,默认值为org.apache.catalina.core.StandardServicename—Service的名字它们位于 整个配置文件的顶层Server表示整个的Catalina Servlet容器

2、连接器类元素: 代表了介于客户与服务之间的通信接口,负责将客户的请求发送给服务器,并将服务器的响应结果传递给客户。

3、容器类元素: 代表处理客户请求并生成响应结果的组件,有3种容器类元素,它们是Engine、Host和Context。Engine组件为特定的 Service组件处理所有的客户请求,Host组件为特定的虚拟主机处理所有客户请求,Context组件为特定的Web应用处理所有客户请求。

4、嵌套类元素: 代表了可以加入到容器中的组件,如元素、元素和 元素。

Tomcat处理请求的流程图如下:
在这里插入图片描述
Tomcat各组件关系:
在这里插入图片描述
上图中:
1)Engine负责处理Service内的所有请求。它接收来自Connector的请求,并决定传给哪个Host来处理,Host处理完请求后,将结果返回给Engine,Engine再将结果返回给Connector。
2)Host负责管理一个或多个Web项目
3)Context代表一个运行在Host上的Web项目。一个Host上可以有多个Context。
注:Tomcat配置文件一些其他解释,参见https://blog.csdn.net/GuangRong1/article/details/81015014

Tomcat各组件类图(Tomcat提供各组件的接口和实现)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
【Tomcat文件说明:】

bin: 二进制可执行文件,存放Tomcat的命令,很多环境变量也在此处设置,例如startup.bat和shutdown.bat
conf: 存放tomcat服务器全局配置的各种文件,例如:server.xml(是主要配置文件)、context.xml、web.xml、tomcatusers.xml,其下catalina目录下可以设置默认加载的项目。而catalina文件可以设置tomcat服务器内存大小。context.xml可以用来配置数据源之类的东西。logging文件记录tomcat服务器运行的日志记录。server.xml可以设置域名、端口号、IP、请求的编码、默认加载的项目。web.xml可以设置tomcat服务器支持的文件类型。
lib: 存放Tomcat服务器所需要的所有Jar包
logs: 存放Tomcat执行时的日志文件。清除此文件不会对Tomcat服务器产生影响,只有运行了Tomcat才会在此目录下生成日志文件。
temp: 存放tomcat运行时产生的临时文件,当tomcat关闭后,这个目录中的文件可以删除
webapps: 这个目录下的每个文件夹对应一个JavaWeb应用程序,我们常用的网站类资源项目会放在改目录下。Tomcat启动时会加载webapps目录下的应用程序。项目文件以war包、Jar包、普通文件夹三种形式发布应用。也可把应用程序存放在任意一个位置,在配置文件中配置好映射就行。
work: webapps下的应用程序在运行时会自动生成文件,就在work目录下。work目录删除了也没问题,但再次运行应用程序还要再生成work目录和文件。其下还存放Tomcat运行时编译后的文件。清空work目录,重启Tomcat,可以达到清除Tomcat服务器缓存的目的。

下图是我的项目文件的目录:
在这里插入图片描述

安全配置方案一:

1.1、开启 Tomcat 的访问日志
/home/apache-tomcat-8.5.47/conf//server.xml 文件,取消注释下列代码:

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"   
prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>

在这里插入图片描述
如上所示,启用访问日志功能,重启 Tomcat 服务后,在 /home/apache-tomcat-8.5.47/logs 文件夹中就可以看到访问日志,如下:
在这里插入图片描述
1.2 、修改默认访问端口
修改 conf/server.xml 文件把默认的 8080 访问端口改成其它端口。
在这里插入图片描述
1.3、 禁止列出目录
防止外部直接访问目录时由于找不到默认页面,而列出目录下的文件的情况,编辑conf/web.xml 文件:
将listings改成false或值改为false,如下:在这里插入图片描述
1.4、删除文档和示例程序
删除 webapps 目录下的 docs、examples、manager、ROOT、host-manager 文件夹
1.5、修改运行内存大小
编辑配置文件 /home/apache-tomcat-8.5.47/bin/catalina.sh
JAVA_OPTS=‘-Xms512m -Xmx512m’
说明:按需更改 -Xms【初始化内存大小】 -Xmx【可以使用的最大内存】

2.2、【Nginx】之安全观

2.1、隐藏nginx版本信息

vim nginx/conf/nginx.conf

worker_processes  1;
events {worker_connections  1024;
}
http {include       mime.types;default_type  application/octet-stream;sendfile        off;keepalive_timeout  65;log_format  main  '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';server {listen       80;server_name  www.oldboyedu.com;server_tokens off;   ###配置为off,默认为onlocation / {root   html/www;index  index.html index.htm;}access_log  logs/access_www.log  main;}
}

配置完测试验证:curl -I http://你的IP/,输出结果应该不在显示nginx版本信息。
在这里插入图片描述

2.2、修改nginx版本及头部、错误页信息

修改版本信息需要在Nginx编译安装前,修改程序源文件信息:
1) vim /nginx-1.14.2/src/core/nginx.h
在这里插入图片描述
文件信息如下:

在这里插入图片描述
修改上述信息为你想误导的版本,记得做好记录,便于自己管理版本。

2)修改Http头部信息

vim  /nginx-1.14.2/src/http/ngx_http_header_filter_module.c

在这里插入图片描述
修改下列内容为你想要对外显示的信息:

在这里插入图片描述
3)修改错误页显示

vim  /nginx-1.14.2/src/http/ngx_http_special_response.c

在这里插入图片描述
4)以上修改完成后重新编译

./configure  --prefix=/nginx-1.14.2/ --user=www --group=www --with-http_stub_status_module --with-http_ssl_module

编译完成重启服务:/etc/init.d/nginx restart

2.3 修改worker进程的用户(共有2种方式)

第一种:编译时利用安装配置参数,设定nginx默认worker进程用户为指定用户

添加用户非系统登录用户:useradd -s /sbin/nologin -M www
编译安装时指定用户:./configure –user=www –group=www

第二种:编写nginx服务配置文件,设定nginx默认worker进程用户

在这里插入图片描述
修改上图中的用户为你指定创建的用户,注意语法为:user nobody(用户) nobody;(组),默认为nobody。然后验证,执行:ps -ef|grep nginx

[root@~ nginx]# ps aux|grep nginx  ##比如修改为www
root     10740  0.0  0.0 103260   896 pts/1    S+   14:35   0:00 grep nginx
www    26256  0.0  0.0  23316  2120 ?        S    Oct17   0:57 nginx: worker process 

2.4 修改上传文件大小的限制(动态生效)

编辑nginx配置文件,修改client_max_body_size 10m,即设置上传文件最大值10M:
在这里插入图片描述
配置示例:

http {sendfile        on;keepalive_timeout  65;client_max_body_size 10m;    # 设置上传文件最大值10M,默认值是1m,可在http,server,location这三个标签内其中一处配置该该字段
}

2.5 Nginx站点目录及文件URL访问控制配置

1)根据目录或扩展名,禁止用户访问指定数据信息
编辑Nginx配置文件conf/Nginx.conf,配置示例如下:

location ~ ^/images/.*\.(php|php5|sh|pl|py|html)$   ##这里配置文件类型{ deny all;} 
location ~ ^/static/.*\.(php|php5|sh|pl|py)$ { deny all;} 
location ~* ^/data/(attachment|avatar)/.*\.(php|php5)${ deny all;}

2)访问禁止的数据信息时,进行页面跳转,即重定向,配置示例:

location ~* \.(txt|doc)$ {if (-f $request_filename){root /data/www/www;#rewrite …..可以重定向到某个URLbreak;}
}
location ~* \.(txt|doc)${root /data/www/www;denyall;
}

3)根据IP地址或网络进行访问策略控制,配置示例:

location / { deny 192.168.1.1;allow 192.168.1.0/24;allow 10.1.1.0/16;deny all;
}

4)采用if判断方式,进行访问控制

if ($remote_addr = 10.0.0.7 ){return 403;}

2.6 配置Nginx,禁止非法域名解析访问企业网站

第一种方式:配置一个server虚拟主机区块,放置在所有server区块最前面,示例:

server {listen 80;server_name - ;return 501;
}

第二种方式:通过非法域名访问时,自动跳转到正确的域名上,示例:

server {listen 80 default_server;server_name _;rewrite ^(.*) http://www.oldboyedu.com/$1 permanent;
}
if ($host !~ ^www\.oldboyedu\.com$)
{rewrite ^(.*) http://www.oldboyedu.com/$1 permanent;
}

2.7 Nginx图片及目录防盗链处理

资源盗链 :简单理解,就是某些不法网站未经许可,通过在其自身网站程序里非法调用其他网站的资源,然后在自己的网站上显示这些调用的资源,达到填充自身网站的效果。

1)根据HTTP referer实现防盗链

其原理是利用referer,并且针对扩展名rewrite重定向,下面的代码为利用referer且针对扩展名rewrite重定向,即实现防盗链的Nginx配置。

#Preventing hot linking of images and other file types
location ~* /\.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {root  html/www;valid_referers none blocked *.oldboyedu.com oldboyedu.com;  ##指定合法链接if ($invalid_referer){ rewrite ^/  http://www.oldboyedu.com/img/nolink.jpg; ##重定向反盗链} access_log off;root html/www;expires 1d;break;}

2)根据cookie防盗链
3) 通过加密变换访问路径实现防盗链
4) 在所有网站资源上添加网站信息,让盗链人员帮你做推广宣传

2.8 、NGINX错误页面友好显示配置

示例1:对错误代码403实行本地页面跳转,命令如下:

###wwwserver {listen       80;server_name  www.oldboyedu.com;location / {root   html/www;index  index.html index.htm;}error_page  403  /403.html;    #<==当出现403错误时,会跳转到403.html页面,403.html是相对于站点根目录html/www的}

示例2:50x页面放到本地单独目录下,进行优雅显示。

# redirect server error pages to the static page /50x.html
error_page   500 502 503 504  /50x.html;
location = /50x.html {root   /data0/www/html;
}

示例3:改变状态码为新的状态码,并显示指定的文件内容,如下所示:

error_page 404 =200 /empty.gif;server {listen       80;server_name www.oldboyedu.com;location / {root   /data0/www/bbs;index  index.html index.htmfastcgi_intercept_errors on;error_page  404 =200    /ta.jpg;access_log  /app/logs/bbs_access.log  commonlog;}
}

示例4:错误状态码URL重定向,命令如下:

server {listen       80;server_name www.oldboyedu.com;location / {root   html/www;index  index.html index.htm;error_page   404  https://oldboy.cnblogs.com;
#<==当出现404错误时,会跳转到指定的URL https://oldboy.cnblogs.com页面显示给用户,这个URL一般是企业另外的可用地址access_log  /app/logs/bbs_access.log  commonlog;}
}

2.9、Nginx站点目录文件及目录权限优化

1) 加强网站目录权限:

为防止黑客越过后门拿到权限提升,建议网站目录属主和属组配置为root,目录权限为755,文件权限644,即nginx用户或非系统用户对网站文件和目录只具有:读和访问(cd而不能mkdir和touch)目录资源的权限,从而基本消除木马上传及网站页面恶意修改;
对于正常用户的文件上传下载,执行,可为nginx所配置用户设置专门的,最好按资源类型分类创建对应文件夹来存储不同资源,各类资源目录属主和属组配置为指定用户,权限为755,文件权限可配置ACl,视实际确保有效且权限最小化。

在这里插入图片描述
2)Nginx目录以列表(directory listing)形式显示

借助向Nginx配置文件开启autoindex on; 来实现。autoindex可以放在location中,只对当前location的目录起作用。你也可以将它放在server指令块则对整个站点都起作用。或者放到http指令块,则对所有站点都生效。

示例:

server {listen   8023;server_name   www.cucc.com;access_log  /tmp/nginx/log.;root   /usr/local/nginx;location / {index  index.php index.html index.htm;}location /somedir {autoindex on;}
}

3) nginx禁止访问某个目录

借助配置文件中开启deny all;来实现。

示例1:禁止对webapp/user-list目录的访问并返回403 Forbidden

location /usr/local/webapp/user-list/^~ {deny all;return 403;
}

对多个文件的访问限制,可按如下配置:

location ~ ^/(static|date)/ {    ##目录用()标出并用“或”标识符指定nginx下的多个目录
deny all;
reture 403或404;     ## 禁止访问目录并返回指定的http状态码
}

附:nginx location语法:

location [=|*或^~] /uri(统一资源描述符,是urL后跟的具体资源)/ {
对资源目录的一些配置 ##中括号为可选项

}

= 严格匹配。如果这个查询匹配,那么将停止搜索并立即处理此请求。~ 为区分大小写匹配(可用正则表达式)
!~为区分大小写不匹配
~ 为不区分大小写匹配(可用正则表达式)
!~*为不区分大小写不匹配
^~ 如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那么不测试正则表达式。可以这样理解,^~ 开头表示uri以某个常规字符串开头而非正则表达式,^~代表非正则匹配,理解为匹配 url路径即可。nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)
############------------------------示例如下-----------------########
location = /app {   ##=严格匹配
# 只匹配 /app 查询。请求URL:http://你的ip地址/app/  访问时匹配的是:=/app/,也就是花括号里root参数,即nginx的location根目录下的/app资源,比如root=/usr/local,那么上述url实际请求的就是/usr/local/app的资源;当路径相同时,精准匹配优先,必须是满足/uri/或者uri,要么uri两边都加/,要么uri两边都不加斜杆的情况,只单边有/属于一般匹配。
}
注意:当多个location后跟路径(uri)有共同目录时,但location的root目录不通,比如location后跟/images/,,另一个跟/images/b,且两者root目录不同,当访问URL时,http://你的ip/images/b/test.jpg,这时url访问nginx既能匹配/images/又能匹配/images/b,但这时以最长uri匹配优先,匹配的是:/images/b/目录下的资源。如果imagin前加上^~,因其代表非正则匹配,对不满足字符串的停止搜索,比如: http://你的ip/images/b/test.jpg,匹配不含^~的location中配置的一般匹配。当访问 http://你的ip/images/可匹配到^~images 的location资源。另外url资源会按配置文件中的location顺序匹配,优先匹配前面定义的location。
location / {
# 匹配任何查询,因为所有请求都以 / 开头,故任何请求都会匹配到。但是正则表达式规则和长的块规则将被优先和查询匹配。
}
location ^~ /pkg/download/ {
# 匹配任何以 /pkg/download/ 开头的任何查询并且停止搜索。任何正则表达式将不会被测试。
}
location ~*.(gif|jpg|jpeg)$ {  ##$匹配以啥结尾
# 匹配任何已 gif、jpg 或 jpeg 结尾的请求。
}
location ~*.(gif|jpg|swf)$ {
valid_referers none blocked start.igrow.cn sta.igrow.cn;
if ($invalid_referer) {
#防盗链
rewrite ^/ http://$host/logo.png;
}
}

示例2:错误页面自定义

 server {
……
#error_page  404              /404.html;  ##页面放在站点的根目录下,即server容器中# redirect server error pages to the static page /50x.html#error_page   500 502 503 504  @fallback;location = @fallback{root   html;proxy_pass http://www.baidu.com;  ##@开头的,如果请求的 URI 存在,则本 nginx 返回对应的页面;如果不存在,则把请求代理到baidu.com 上去做个弥补,其实就是做了一个容错,把找不到的url全部转发到fallback的反向代理服务器去proxy_redirect default;}

4)nginx配置禁止访问上传目录下的php,shell,python等程序文件,减少木马风险
原理:通过配置location区块。进行访问限制。

location ~ ^/images/.*\.(php|php5|sh|pl|py)$
{
deny all;
}
location ~ ^/static/ .*\.(php|php5|sh|pl|py)$
{
deny all;
}
location ~ ^/data/(attachment|avatar)/ .*\.(php|php5)$
{
deny all;
}
location ~ .*\.(php|php5)?$   ##php放在最后
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fcgi.conf;
}

5)限制网站来源ip访问

原理:使用ngx_http_access_module 限制网站来源ip访问。

案例1: 禁止某目录让外界访问,但允许某ip访问,且支持php解析:

location ~ ^/date/ {
deny 139.142.35.1;    ##放在最前,拒绝指定ip
allow 202.111.20.112;  ##允许指定ip访问
allow 10.1.5.0/16;  ##开放指定网段
deny all;
}
location ~ .*\.(php|php5)? {    ##允许php解析
fastcgi_pass 127.0.0.1:9200;
fastcgi_index index.php;
inculde fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

案例2: nginx做反向代理可以限制客户端ip访问

location / {
root html/blog;
index index.php index.html index.htm;
deny 11.0.0.7;     ##只拒绝某些ip访问,如果是网络段的话加/掩码后缀
allow 11.0.0.7;    ##只允许ip访问
allow all ;
}##或者在server模块里插入条件判断:
if ( $remote_addr = 11.0.0.7){
return 403;
}
if ( $remote_addr = 118.30.34.25 ){
set $allow_access_root 'ture';
}

6)禁止非法域名解析或直接ip访问企业网站

方法1:用户访问ip时,或者恶意解析域名时,收到501错误,

server {
listen 80 default_server;
server_name _;
reture 501;   ##直接报501错误
}

方法2;通过301永久跳转到主页

server {
listen 80 default_server;
server_name _;
rewrite ^(.*) http://www.baidu.com/$1 permanent;
}

方法3:发现某域名恶意解析到公司服务器ip,在server字段中添加以下

if ($host !~ ^www/.bule/.com$){  ##如果header信息的host主机名字段中非www.blue.com就301跳转到www.baidu.com
rewirte ^(.*) http://www.baidu.com$1 permanent;
}

7)密码认证限制目录/路径访问

其实,nginx 提供了 ngx_http_auth_basic_module 模块实现了让用户只要输入正确的用户名密码才允许访问web内容。默认情况下,nginx 已经安装了该模块。我们只需要借助第三方工具设置用户名、密码(其中密码已经加过密),然后保存到文件中,接着在 nginx 配置文件中根据之前事先保存的文件开启访问验证即可。这里借助常用的apache2-utils(Debian,Ubuntu)或httpd-tools(RHEL / CentOS / Oracle Linux);

yum  -y install httpd-tools
htpasswd -mc /usr/local/nginx/conf/pwfile admin  //如下所示,默认采用MD5加密方式,后续创建用户直接跟用户名即可
New password: 
Re-type new password: 
Adding password for user Fadmin
#配置nginx
server {listen       80;server_name  localhost;auth_basic "Please input password"; #这里是验证时的提示信息,这里对整个网站加密auth_basic_user_file /usr/local/nginx/conf/pwfile; #新增密码文件location ^~ nfs/{alias  /home/yang/;autoindex on;}}
#nginx -s reload报错
[emerg] getpwnam("nginx") failed  //这是因为nginx更新是制定nginx用户运行,而系统没有nginx
#执行创建nginx用户即可
useradd nginx -s /bin/nologin
## ip+身份验证共同认证
location ^~ nfs/.* {  #location ~ ^/nfs/.* {…} 保护nfs目录下的所有文件。如果你只设了/admin/ 那么直接输入/admin/index.php还是可以访问并且运行的。 ^/nfs/.* 意为保护该目录下所有文件#...satisfy all;    //表同时满足以下条件才可;deny  192.168.1.2;allow 192.168.1.1/24;allow 127.0.0.1;deny  all;stub_status on;  //启用StubStatus的工作访问状态 access_log on;access_log    logs/Nginxstatus.log;  //指定StubStaus模块的访问日志文件auth_basic           "Administrator’s Area";  #对该路径加密auth_basic_user_file conf/htpasswd;
}
location / {auth_basic off; //不继承上层,这样这里不受上面限制root   html;index  index.html index.htm;}

效果如下:
在这里插入图片描述
单击取消后,报401错误:
在这里插入图片描述

还有一种perl脚本生产密码的方法,示例如下:

#! /usr/bin/perl -w  #filename: add_ftp_user.pl  use strict;  #  print "#example: user:passwd\n";  while (<STDIN>) {  exit if ($_ =~/^\n/);  chomp;  (my $user, my $pass) = split /:/, $_, 2;  my $crypt = crypt $pass, '$1$' . gensalt(8);  print "$user:$crypt\n";  }  sub gensalt {  my $count = shift;  my @salt = ('.', '/', 0 .. 9, 'A' .. 'Z', 'a' .. 'z');  my $s;  $s .= $salt[rand @salt] for (1 .. $count);  return $s;  } 

完成后执行:
chmod o+x add_user.pl
./add_user.pl >/usr/local/nginx/conf/vhost/fdfs_passwd //把生成的密码写到密码文件

2.10、Nginx防爬虫优化

爬虫工作原理,主要是利用Robots协议,即Robots Exclusion Protocol(网络爬虫排除协议),网站通过Robots协议来告诉搜索引擎哪些页面数据可以抓取,哪些页面不能抓取。
eg:浏览器http://www.taobao.com/robots.txt查看淘宝的防爬虫优化:
在这里插入图片描述
方法1:通过客户端的user-agent信息,轻松的阻止指定的爬虫爬取我们的网站,阻止下载协议代理:

if ($http_user_agent ~* LWP::Simple|BBBike|Wget) {
return 403;
}

方法2:通过$http_user_agent 获取客户端agent然后判断是否进行返回错误值

if ($http_user_agent ~* “qihoobot|baiduspider|Googlebot-Mobile|Googlebot=Image|Adsbot-Google|sougou spider|Sogou web spider”) {
return 403;
}

方法3:测试禁止不同的浏览器软件访问

if ( $http_user_agent ~* "Firefox|MSIE"){
##如果浏览器为Firefox或者IE,就会永久跳转到 http://www.baidu.com
rewirte ^(.*) http://www.baidu.com/$1 permanent;
}

方法4:通过nginx进行限制http的请求

if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 501;
}

2.11 Nginx HTTPS隐藏版本号:

之前我们隐藏http版本号,只需在http模块里加入server_tokens off; 即可;那走HTTPS怎么处理呢?我们只需将server_tokens off; 加入到虚拟主机里,及server段尾即可,完成后nginx -s reload,使用curl -Ik https://uri 验证即可。效果如下所示

在这里插入图片描述

……

Published by

风君子

独自遨游何稽首 揭天掀地慰生平