apache安全配置

apache运行原理

Apache是基于模块化设计的,它的核心代码并不多,大多数的功能都被分散到各个模块中,各个模块在系统启动的时候按需载入。从配置文件中可以看到加载的各个模块。

apache在启动阶段采用root权限来获取更多的资源使用权限,这个时候会加载配置文件,模块,资源文件等,在下一个运行阶段,Apache为了获得系统资源最大的使用权限,将以特权用户root完成启动。分11个阶段处理用户的请求。

apache的两种工作模式

Apache通过MPM(多路处理模块)来使用操作系统的资源,对进程和线程池进行管理。Apache为了能够获得更好的运行性能,针对不同的平台 (Unix/Linux、Window)提供了不同的MPM,用户可以根据实际情况进行选择,其中最常使用的MPM有 prefork和worker两种。

  • prefork

    一个单独的控制进程(父进程)负责产生子进程,这些子进程用于监听请求并作出应答。Apache总是试图保持一些备用的 (spare)或是空闲的子进程用于迎接即将到来的请求。这样客户端就无需在得到服务前等候子进程的产生。在Unix系统中,父进程通常以root身份运行以便邦定80端口,而 Apache产生的子进程通常以一个低特权的用户运行。User和Group指令用于配置子进程的低特权用户。

  • worker

    每个进程能够拥有的线程数量是固定的。服务器会根据负载情况增加或减少进程数量。一个单独的控制进程(父进程)负责子进程的建立。每个子进程能够建立 ThreadsPerChild数量的服务线程和一个监听线程,该监听线程监听接入请求并将其传递给服务线程处理和应答。Apache总是试图维持一个备 用(spare)或是空闲的服务线程池。这样,客户端无须等待新线程或新进程的建立即可得到处理。在Unix中,为了能够绑定80端口,父进程一般都是以 root身份启动,随后,Apache以较低权限的用户建立子进程和线程。User和Group指令用于配置Apache子进程的权限。

apache 在centos下配置

apache配置文件,默认文件在/etc/httpd/conf/httpd.conf路径下

那么简单理解一下,配置参数的含义和使用,Allow和Deny可以用于apache的conf文件或者.htaccess文件中(配合Directory, Location, Files等),用来控制目录和文件的访问授权。
所以,最常用的是:
Order Deny,Allow
Allow from All

注意“Deny,Allow”中间只有一个逗号,也只能有一个逗号,有空格都会出错;单词的大小写不限。上面设定的含义是先设定“先检查禁止设定,没有禁止的全部允许”,而第二句没有Deny,也就是没有禁止访问的设定,直接就是允许所有访问了。

但是如果想限制IP访问,如下写

Order Deny,Allow
Deny from 192.168.1.1
Allow from all

这时候限制不起作用,Order取规则为最后一个Allow规则,首先限制IP访问,但是会继续查看Allow规定指定的信息,IP又在all中,所以限制不起作用。所以可以如下写:

Order Deny,Allow
Deny from 192.168.1.1
或者
Order Allow,Deny
Allow from all
Deny from 192.168.1.1

比如:如下的常用配置

1、在配置文件开始部分和下部有两个配置项,用来隐藏banner信息:

ServerTokens OS  修改为:ServerTokens Prod

(在出现错误页的时候不显示服务器操作系统的名称)
ServerSignature On 修改为:ServerSignature Off

(不回显apache版本信息)

2、apache在一些系统的默认配置中,开启目录浏览,所以可以使用以下关闭设置。

Options Indexes FollowSymLinks 改为 Options -Indexes FollowSymLinks

3、取消部分目录的php执行权限

<Directory "/var/www/html/upload">     
    <FilesMatch "\.(?i:php|php3|php5)$">     
        Deny from all     
    </FilesMatch> 
</Directory> 
//在upload目录下,尽可能多匹配后缀php|php3|php5的文件,不分大小写。

还可以在主机配置文件中增加php_flag engine off指令即可,配置如下:

Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all 
php_flag engine off

5、配置httpd.conf限制一些特殊目录的特定ip访问,如内部接口等。

<Directory "/var/www/html/aaa">     
    Order Deny,Allow
    Deny from all
    Allow from 192.168.1.111    
</Directory> 

6、配置httpd.conf限制一些文件类型的访问,如txt的日志

<Files ~ ".txt$"> 
    Order allow,deny 
    Deny from all 
</Files>

7、针对URL相对路径的禁止访问:

<Location /dir/>
Order allow,deny
Deny from all
</Location>

Nginx 安全配置

nginx 工作原理

Nginx由内核和模块组成,nginx核心模块包括:HTTP模块、EVENT模块和MAIL模块。nginx仅仅通过查找配置文件将客户端请求映射到一个location block(location是Nginx配置中的一个指令,用于URL匹配),而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。nginx架构类似于Apache的Worker工作状态,Nginx的每一个Worker进程都管理着大量的线程,真正处理请求的是Worker之下的线程。

nginx本身不能处理PHP,它只是个web服务器,当接收到请求后,如果是php请求,则发给php解释器处理,并把结果返回给客户端。nginx一般是把请求发fastcgi管理进程处理,fastcgi管理进程选择cgi子进程处理结果并返回被nginx。

nginx涉及到两个账户,一个是nginx的运行账户,一个是php-fpm的运行账户。如果访问的是一个静态文件,则只需要nginx的运行账户对文件具有读取权限;而如果访问的是一个php文件,则首先需要nginx的运行账户对文件有读取权限,读取到文件后发现是一个php文件,则转发给php-fpm,此时则需要php-fpm账户对文件具有读取权限。

nginx 在centos下的安全配置

  1. nginx设置问题
#隐藏 Nginx 的版本号,提高安全性。
    server_tokens off;
#开启高效文件传输模式,sendfile 指令指定 Nginx 是否调用sendfile 函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘 IO 重负载应用,可设置为 off,以平衡磁盘与网络 I/O 处理速度,降低系统的负载。
    sendfile on;
#是否开启目录列表访问,默认关闭。
    autoindex off;

开头的配置

user www-data;   //用户和组
worker_processes auto;   //进程数
pid /run/nginx.pid;  //进程文件
include /etc/nginx/modules-enabled/*.conf;  //导入其他配置文件到nginx配置文件

events配置

events {
	worker_connections 768;   //设置一个worker进程同时打开的最大连接数
	# multi_accept on;    //告诉nginx收到一个新连接通知后接受尽可能多的连接
}

http配置

http {

	##
	# Basic Settings
	##

	sendfile on;      //开启高效文件传输模式
	tcp_nopush on;     //告诉 Nginx 在一个数据包里发送所有头文件
	tcp_nodelay on;    //告诉 Nginx 不要缓存数据,而是一段一段的发送
	keepalive_timeout 65;   //连接超时时间,单位是秒
	types_hash_max_size 2048;   //上传文件大小限制	
	# server_tokens off;      //隐藏 Nginx 的版本号

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;   //包含配置
	default_type application/octet-stream;  //默认传输类型

	##
	# SSL Settings	
	##

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;   //访问日志
	error_log /var/log/nginx/error.log;     //错误日志

	##
	# Gzip Settings
	##

	gzip on;

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	##
	# Virtual Host Configs
	##

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}

server配置

众所周知,Nginx的配置文件分为Server、Location、If等一些配置块,并且存在包含关系,和编程语言比较类似。如果在外层配置的一些选项,是可以被继承到内层的。

但这里的继承也有一些特性,比如add_header,子块中配置后将会覆盖父块中的add_header添加的所有HTTP头,造成一些安全隐患。

server配置在一些系统上不是默认的nginx配置,如果需要修改可以在nginx配置中添加,或者添加include,包含进其他的自定义server。

如下列代码,Server块添加了CSP头:

server {
    ...
    add_header Content-Security-Policy "default-src 'self'";
    add_header X-Frame-Options DENY;

    location = /test {
        add_header X-Content-Type-Options nosniff;
        rewrite ^(.*)$ /xss.html break;
    }
}

但/test的location中又添加了X-Content-Type-Options头,导致父块中的add_header全部失效。

  1. 禁止一个目录的访问
    示例:禁止访问path目录
location ^~ /path { 
deny all; 
} 

可以把path换成实际需要的目录,目录path后是否带有”/“,带“/”会禁止访问该目录和该目录下所有文件。不带”/“的情况就有些复杂了,只要目录开头匹配上那个关键字就会禁止;注意要放在fastcgi配置之前。

这个常见于Nginx做反向代理的情况,动态的部分被proxy_pass传递给后端端口,而静态文件需要Nginx来处理。

假设静态文件存储在/home/目录下,而该目录在url中名字为files,那么就需要用alias设置目录的别名:

location /files {
    alias /home/;
}

此时,访问http://example.com/files/readme.txt,就可以获取/home/readme.txt文件。

但我们注意到,url上/files没有加后缀/,而alias设置的/home/是有后缀/的,这个/就导致我们可以从/home/目录穿越到他的上层目录。从而导致一个目录穿越问题。

  1. 禁止php文件的访问及执行

示例:去掉单个目录的PHP执行权限

location ~ /attachments/.*\.(php|php5)?$ { 
deny all; 
} 

示例:去掉多个目录的PHP执行权限

location ~  
/(attachments|upload)/.*\.(php|php5)?$ { 
deny all; 
} 
  1. 禁止IP的访问

示例:禁止IP段的写法:

deny 10.0.0.0/24;

示例:只允许某个IP或某个IP段用户访问,其它的用户全都禁止

allow  
x.x.x.x;  
allow 10.0.0.0/24;  
deny all; 
  1. 禁用非必要的方法
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
    return   444;
	}
  1. 禁用扩展名
location ~* .(txt|doc|sql|gz|svn|git)$ {
   deny all;
   }
  1. 根据用户的真实 IP 做连接限制
## 这里取得原始用户的IP地址
map $http_x_forwarded_for  $clientRealIp {
    ""  $remote_addr;
    ~^(?P<firstAddr>[0-9\.]+),?.*$    $firstAddr;
}
 
## 针对原始用户 IP 地址做限制
limit_conn_zone $clientRealIp zone=TotalConnLimitZone:20m ;
limit_conn  TotalConnLimitZone  50;
limit_conn_log_level notice;
 
## 针对原始用户 IP 地址做限制
limit_req_zone $clientRealIp zone=ConnLimitZone:20m  rate=10r/s;
#limit_req zone=ConnLimitZone burst=10 nodelay;
limit_req_log_level notice;

参考资料:

https://www.cnblogs.com/chenpingzhao/p/5785416.html

https://wooyun.kieran.top/#!/drops/201.Nginx%E5%AE%89%E5%85%A8%E9%85%8D%E7%BD%AE%E7%A0%94%E7%A9%B6

https://wooyun.kieran.top/#!/drops/315.Apache%E5%AE%89%E5%85%A8%E9%85%8D%E7%BD%AE

https://blog.csdn.net/yf3585595511/article/details/54933646





# web安全  

tocToc: