windows下用nginx配置https服务器

1.安装nginx

先到nginx官网下载nginx http://nginx.org/en/download.html

未分类

将下载好的文件解压出来修改文件名为 nginx ,然后拷贝到C盘下,目录如下:

未分类

  • 运行 nginx
start nginx
  • 验证

在浏览器中输入 localhost 访问即可,如出现以下页面,即安装成功

未分类

2.安装 OpenSSL

下载OpenSSL http://slproweb.com/products/Win32OpenSSL.html

未分类

下载完成安装到 C:OpenSSL-Win64

配置环境变量

未分类

在path变量后需要加入 %OPENSSL_HOME%

未分类

3.生成https证书

在C:nginx下创建ssl文件夹 用于存放证书

创建私钥 (建议使用系统窗口,不要用gitBash 有涉及到选择的地方,gitBash无法选择)

openssl genrsa -des3 -out shidian.key 1024 //shidian 自己取的名字

效果如下:

未分类

未分类

创建 csr 证书

openssl req -new -key shidian.key -out shidian.csr

未分类

此时效果:

未分类

删除密码 复制 shidian.key 并重命名 shidian.key.org

openssl rsa -in shidian.key.org -out shidian.key

未分类

生成crt证书

openssl x509 -req -days 365 -in shidian.csr -signkey shidian.key -out shidian.crt

未分类

最后生成证书如下

未分类

4.修改 nginx 下的 nginx.conf配置文件

C:nginxconfnginx.conf
upstream nodejs__upstream2 {
    server 127.0.0.1:8080; # 需要监听的端口名 我用的
    keepalive 64;
}

server {
    listen 443 ssl;
    server_name dev.kt.looklook.cn; # 配置的https的域名

    ssl_certificate      C://nginx//ssl//shidian.crt;  # 这个是证书的crt文件所在目录
    ssl_certificate_key  C://nginx//ssl//shidian.key;  # 这个是证书key文件所在目录

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

 location / {
    proxy_set_header   X-Real-IP            $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header   Host                   $http_host;
    proxy_set_header   X-NginX-Proxy    true;
    proxy_set_header   Connection "";
    proxy_http_version 1.1;
    proxy_pass         http://nodejs__upstream2;
 }
}
  • 重启nginx
nginx -s reload
  • 访问

输入你配置好的域名即可访问了

Nginx使用的php-fpm的两种进程管理方式及优化

这篇文章主要介绍了Nginx使用的php-fpm的两种进程管理方式及优化,需要的朋友可以参考下
PS:前段时间配置php-fpm的时候,无意中发现原来它还有两种进程管理方式。与Apache类似,它的进程数也是可以根据设置分为动态和静态的。

php-fpm目前主要又两个分支,分别对应于php-5.2.x的版本和php-5.3.x的版本。在5.2.x的版本中,php-fpm.conf使用的是xml格式,而在新的5.3.x版本中,则是和php.ini一样的配置风格。
在5.2.x版本中,php-fpm.conf中对于进程管理号称是有两种风格,一种是静态(static)的,一种是类似于apache风格(apache-like)的。

代码如下:

Process manager settings
<value name=”pm”>
Sets style of controling worker process count.
Valid values are 'static' and ‘apache-like'
<value name=”style”>static</value>

按照文档的说明,如果pm的style采用apache-like,启动的进程数应该是和StartServers指定的一样。不过经过数次的尝试,会发现,实际上在这里将pm的style配置成apache-like没有起任何作用。也就是说,这里的apache-like并没有被实现。
不过,在最新的5.3.x的配套php-fpm中,apache风格的进程管理已经被实现了。

代码如下:

; Choose how the process manager will control the number of child processes.
; Possible Values:
; static - a fixed number (pm.max_children) of child processes;
; dynamic - the number of child processes are set dynamically based on the
; following directives:
; pm.max_children - the maximum number of children that can
; be alive at the same time.
; pm.start_servers - the number of children created on startup.
; pm.min_spare_servers - the minimum number of children in 'idle'
; state (waiting to process). If the number
; of 'idle' processes is less than this
; number then some children will be created.
; pm.max_spare_servers - the maximum number of children in 'idle'
; state (waiting to process). If the number
; of 'idle' processes is greater than this
; number then some children will be killed.
; Note: This value is mandatory.
;pm = dynamic
pm = static

由上面一段文字可知,对于进程的管理存在两种风格——static和dynamic。和之前的版本的进程管理其实还是一样的,只是将apache-like改成了dynamic,这样更容易理解。

如果设置成static,php-fpm进程数自始至终都是pm.max_children指定的数量,不再增加或减少。
如果设置成dynamic,则php-fpm进程数是动态的,最开始是pm.start_servers指定的数量,如果请求较多,则会自动增加,保证空闲的进程数不小于pm.min_spare_servers,如果进程数较多,也会进行相应清理,保证多余的进程数不多于pm.max_spare_servers。

这两种不同的进程管理方式,可以根据服务器的实际需求来进行调整。

这里先说一下涉及到这个的几个参数,他们分别是pm、pm.max_children、pm.start_servers、pm.min_spare_servers和pm.max_spare_servers。
pm表示使用那种方式,有两个值可以选择,就是static(静态)或者dynamic(动态)。在更老一些的版本中,dynamic被称作apache-like。这个要注意看配置文件的说明。

下面4个参数的意思分别为:

  • pm.max_children:静态方式下开启的php-fpm进程数量。
  • pm.start_servers:动态方式下的起始php-fpm进程数量。
  • pm.min_spare_servers:动态方式下的最小php-fpm进程数量。
  • pm.max_spare_servers:动态方式下的最大php-fpm进程数量。

如果dm设置为static,那么其实只有pm.max_children这个参数生效。系统会开启设置数量的php-fpm进程。
如果dm设置为dynamic,那么pm.max_children参数失效,后面3个参数生效。系统会在php-fpm运行开始的时候启动pm.start_servers个php-fpm进程,然后根据系统的需求动态在pm.min_spare_servers和pm.max_spare_servers之间调整php-fpm进程数。

那么,对于我们的服务器,选择哪种执行方式比较好呢?事实上,跟Apache一样,运行的PHP程序在执行完成后,或多或少会有内存泄露的问题。这也是为什么开始的时候一个php-fpm进程只占用3M左右内存,运行一段时间后就会上升到20-30M的原因了。
对于内存大的服务器(比如8G以上)来说,指定静态的max_children实际上更为妥当,因为这样不需要进行额外的进程数目控制,会提高效率。因为频繁开关php-fpm进程也会有时滞,所以内存够大的情况下开静态效果会更好。数量也可以根据 内存/30M 得到,比如8GB内存可以设置为100,那么php-fpm耗费的内存就能控制在 2G-3G的样子。如果内存稍微小点,比如1G,那么指定静态的进程数量更加有利于服务器的稳定。这样可以保证php-fpm只获取够用的内存,将不多的内存分配给其他应用去使用,会使系统的运行更加畅通。
对于小内存的服务器来说,比如256M内存的VPS,即使按照一个20M的内存量来算,10个php-cgi进程就将耗掉200M内存,那系统的崩溃就应该很正常了。因此应该尽量地控制php-fpm进程的数量,大体明确其他应用占用的内存后,给它指定一个静态的小数量,会让系统更加平稳一些。或者使用动态方式,因为动态方式会结束掉多余的进程,可以回收释放一些内存,所以推荐在内存较少的服务器或VPS上使用。具体最大数量根据 内存/20M 得到。比如说512M的VPS,建议pm.max_spare_servers设置为20。至于pm.min_spare_servers,则建议根据服务器的负载情况来设置,比较合适的值在5~10之间。

记录下在linux配置mongodb+nginx+node的过程

mongodb:

1、下载mongodb3.4版本,地址: https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-3.4.5.tgz

2、通过Xftp把文件放到已经创建好的目录里面。

3、使用tar xxx 命令,将压缩解压到当前的工作路径。顺便cd到解压后的文件夹,把所有文件的移到上一层,并删掉这个文件夹。现在目录如下

未分类

4、在bin的外层级新建一个文件夹树:data/db,以后这个db就是放数据的地方了。

5、进入到bin,使用mongod –dbpath ../data/db,就可以启动mongodb,默认端口是27017。

6、访问curl localhost:27017,看是否有这段信息,有则代表已成功启动。

未分类

7 如果bin文件夹没有index.html,可以自己建一个,开启成功后会打开这个index。

nginx:

1、先使用命令 rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm 安装nginx的安装yum源。

2、安装成功后/etc/yum.repos.d会有nginx.repo文件。

3、使用yum install nginx -y,安装nginx,默认地址为/etc/nginx。我安装完后是没有html文件夹的,可以自己添加一个html文件夹,里面放一个index.html。

4、使用cd进nginx文件夹。使用nginx即可开启nginx服务。

5、如果想修改nginx.conf,修改完后使用nginx -s -reload即可重启nginx服务。

此时可以在window界面使用浏览器直接访问地址了。如,我的centos的ip是123.456.7.89,并在nginx上监听了80端口,如下:

listen       80;
server_name  localhost;
location / {
        proxy_pass  http://localhost:27017;  #被代理的服务器的域名
    proxy_redirect     off;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }

6、打开浏览器,地址栏输入123.456.7.89,成功后提示

未分类

如果提示拒绝访问,可能是centos并没有开启80端口。

使用如下命令:

## 开放指定端口(永久)
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload
## 查看已开放的端口
firewall-cmd --list-ports

未分类

则是再重复步骤6即可。

nodejs:

1、使用命令安装源

V8.x: 

#curl --silent --location https://rpm.nodesource.com/setup_8.x | bash -
V7.x:

#curl --silent --location https://rpm.nodesource.com/setup_7.x | bash -
V6.x:

#curl --silent --location https://rpm.nodesource.com/setup_6.x | bash -
V5.x:

#curl --silent --location https://rpm.nodesource.com/setup_5.x | bash -

2、 yum install -y nodejs

Centos 7安装Nginx+PHP+MariaDB环境搭建WordPress博客

WordPress是一个免费的开源项目,是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。也可以把 WordPress当作一个内容管理系统(CMS)来使用,国内外有不少的知名网站建设都是基于WordPress程序,WordPress有许多第三方开发的免费模板和免费插件,安装方式简单易用,相信很多人的第一个站点都是基于WordPress建的。访问官网https://wordpress.org/

在安装ShadowsocksR服务之前希望先对服务器做基本安全配置(非强制) 跳转链接https://www.gyuryong.com/index.php/archives/18/

运行环境搭建

WordPress基于PHP开发的,相信是大家最熟悉也是最容易部署的Web项目了。环境准备:lnmp(linux+nginx+mysql+php)或者lamp(linux+apache+mysql+php),大同小异,本文推荐使用nginx作为Web服务器。
为了避免不必要的麻烦先关闭防火墙和selinux。

1.安装nginx

安装nginx,默认情况Centos7中无Nginx的源,可以如下执行命令添加源,Centos其他版本或者RHEL查看官方教程(教程链接https://www.nginx.com/resources/wiki/start/topics/tutorials/install/):

vi /etc/yum.repos.d/nginx.repo

写入

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1

安装nginx:

yum install nginx -y

2.安装php和mariadb

yum install php-fpm php-mysql mariadb-server unzip

3.修改配置文件

修改/etc/nginx/conf.d/default.conf中下面两断内容:

vi /etc/nginx/conf.d/default.conf

更改前:

location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
}

更改后:

    root   /usr/share/nginx/html;
    index  index.html index.htm index.php;
location / {
    try_files $uri $uri/ /index.php$is_args$args;
}

更改前:

#location ~ .php$ {
#    root           html;
#    fastcgi_pass   127.0.0.1:9000;
#    fastcgi_index  index.php;
#    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
#    include        fastcgi_params;
#}

更改后:

location ~ .php$ {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $request_filename;
    include        fastcgi_params;
}

修改/etc/php-fpm.d/www.conf配置:

vi /etc/php-fpm.d/www.conf

user = apache改为user = nginx,将group = apache改为group = nginx

4.开启服务

systemctl start nginx.service
systemctl start mariadb.service
systemctl start php-fpm.service

5.设置开机自启

systemctl enable nginx mariadb php-fpm

安装WorePress

1.移除/usr/share/nginx/html内所有文件:

cd /usr/share/nginx/html
rm 50x.html index.html

2.下载WordPress并解压,到官网复制最新版链接(跳转链接https://cn.wordpress.org/download/):

yum install wget -y
wget https://cn.wordpress.org/wordpress-4.9.4-zh_CN.zip
unzip wordpress-4.9.4-zh_CN.zip

3.将Web文件移动到根目录并删除没用文件夹:

mv wordpress/* .
rmdir wordpress
rm wordpress-4.9.4-zh_CN.zip

4.权限设置

chown nginx.nginx -R .

5.创建数据库wordpress:

mysql
create database wordpress;
exit

接下来输入你的ip地址就可以安装WordPress了!

Linux Nginx LVS HAproxy 负载均衡功能对比

Nginx:

  1. 工作在网络7层,可以针对http应用做一些分流的策略,比如针对域名,目录结构
  2. Nginx对网络的依赖较小,理论上能ping通就能进行敷在功能
  3. Nginx安装配置比较简单,测试起来很方便
  4. 也可以承担较高的负载压力且稳定,Nginx是为了解决c10k问题而诞生的
  5. 对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测
  6. Nginx对请求的异步处理可以帮助节点服务器减轻负载压力
  7. Nginx仅能支持http、https和Email协议,这样就在适用范围较小
  8. 不支持Session的直接保持,但能通过ip_hash来解决,对Bigrequestheader的支持不是很好
  9. Nginx还能做Web服务器即Cache功能。

LVS:

  1. 抗负载能力强,性能高,能达到F5的60%,对内存和cpu资源消耗比较低
  2. 工作在网络4层,通过VRRP协议(仅做代理使用),具体的流量是由liunx内核来处理,因此没有流量的产生。
  3. 稳定,可靠性强,自身有完美的热备方案(Keepalived+LVS)
  4. 不支持正则处理,不能做动静分离
  5. 支持多种负载均衡算法:rr(轮询),wrr(带权轮询)、lc(最小连接)、wlc(带权最小连接)
  6. 配置相对复杂,对网络依赖比较大,稳定性很高。

LVS工作模式有4种:

  • nat地址转换
  • dr直接路由
  • tun隧道
  • full-nat

HAproxy:

  1. 支持两种代理模式:TCP(四层)和HTTP(七层),支持虚拟主机
  2. 能够补充Nginx的一些缺点比如Session的保持,Cookie引导等工作
  3. 支持url检测后端的服务器出问题的检测会有很好的帮助。
  4. 更多负载均衡策略比如:动态加权轮循,加权源地址哈希,加权URL哈希加权等参数哈希已经实现。
  5. 单纯从效率上来讲HAproxy更会比Nginx有更出色的负载均衡
  6. HAproxy可以对MYsql进行负载均衡,对后端的DB节点进行检测和负载均衡
  7. 支持负载均衡算法:轮循、带权轮循、源地址保持、请求URL、根据Cookie
  8. 不能做Web服务器即Cache。

三大主流软件负载均衡器适用的生产场景:

  1. 网站建设初期,可以选用Nginx、HAproxy作为反向代理负载均衡(流量不大时可以选择不用负载均衡)因为其配置简单,性能也能满足一般业务场景。如果考虑到负载均衡器是有单点失败问题,可以采用Nginx+Keepalived避免负载均衡器自身单点问题。
  2. 网站并发达到一定程度后,为了提高稳定性和转发效率,可以使用LVS,毕竟LVS比Nginx/HAproxy要更稳定,转发效率也高。

nginx 日志切割的三种方法(logrotate切割、shell脚本切割、Python脚本切割)

nginx 日志切割

PS:nginx日志切割可以通过两种方式进行切割,日志logrotate,脚本

方法一:通过logrotate切割

个人感觉配置麻烦,且结合自己这边的项目的环境的复杂,所以就不使用这种方式。这里我也就不写了

可以参考:https://www.cnblogs.com/ilanni/p/5365420.html

方法二:通过shell脚本切割

1、编写shell脚本

#!/bin/bash
#此脚本用于自动分割Nginx的日志,包括access.log和error.log
#每天00:00执行此脚本 将前一天的access.log重命名为access-xxxx-xx-xx.log格式,并重新打开日志文件
#Nginx日志文件所在目录
LOG_PATH=/opt/nginx/logs
#获取昨天的日期
YESTERDAY=$(date -d "yesterday" +%Y-%m-%d)
#获取pid文件路径
PID=/var/run/nginx/nginx.pid
#分割日志
mv ${LOG_PATH}access.log ${LOG_PATH}access-${YESTERDAY}.log
mv ${LOG_PATH}error.log ${LOG_PATH}error-${YESTERDAY}.log
#向Nginx主进程发送USR1信号,重新打开日志文件
kill -USR1 `cat ${PID}`

2、配置crontab每天凌晨00:00定时执行这个脚本

crontab -e
# 输入以下内容并保存
00 00 * * * /bin/bash /opt/nginx/sbin/cut_nginx_log.sh

方法三:通过Python脚本切割

未分类

鉴于这种乱情况,日志目录下面还有多个项目的日志,且分别保存在不同的文件下面(下面又分为测试环境的日志,预发布环境的日志),使用shell脚本就不怎么好写,我就采取了通过Python来实现

脚本:

import os, sys, datetime,re

# nginx日志存放的路径
nginxLogPath="/opt/nginx-1.9.5/logs/"
# 获取昨天的日期
yesterday = (datetime.date.today() + datetime.timedelta(days = -1)).strftime("%Y-%m-%d")
# nginx启动的pid文件
PID = "/var/run/nginx.pid"


def cutNginxLog(path):
    """
    切割nginx日志函数
    :param path: 日志文件的第一级目录
    :return: 
    """
    logList = os.listdir(path)    # 判断传入的path是否是目录
    for logName in logList:      # 循环处理目录里面的文件
        logAbsPath = os.path.join(path, logName)
        if os.path.isdir(logAbsPath):   # 如果是目录,递归调用自己,继续处理
            cutNginxLog(logAbsPath)
        else:         # 如果是日志文件,就进行处理
            # 分割日志
            re_Num = re.compile(r'^[a-zA-Z]')
            # 判断日志文件是否是字母开头,如果是日期开头就不切割
            if re_Num.search(logName):
                logNewName = yesterday + "_" + logName          # 新日志文件名称列如:2018-11-8_access.log
                oldLogPath = os.path.join(path, logName)        # 旧日志文件绝对路径
                newLogPath = os.path.join(path, logNewName)     # 新日志文件绝对路径
                os.rename(oldLogPath, newLogPath)

    cmd = " kill -USR1 `cat %s` "% PID
    res = os.system(cmd)
    if res != 0:
        return "重新加载nginx失败"
cutNginxLog(nginxLogPath)

计划任务:

# crontab -e

30 02 * * * /usr/bin/python3.5 /opt/nginx-1.9.5/sbin/cut_nginx_log.py

切割后的效果图:

未分类

如何在Kubernetes里创建一个Nginx应用

使用命令行kubectl run --image=nginx nginx-app --port=80 创建一个名为nginx-app的应用

未分类

结果: deployment.apps/nginx-app created

使用命令行kubectl get pods查看创建结果,状态已经为running:

未分类

使用命令行kubectl describe pods查看pod明细:

未分类

未分类

未分类

把pod id记下来: nginx-app-f75d46bd9-q6c76

使用该pod id可以执行一些命令:

  • kubectl exec nginx-app-f75d46bd9-q6c76 ps aux

  • kubectl describe pod nginx-app-f75d46bd9-q6c76

  • kubectl logs nginx-app-f75d46bd9-q6c76

未分类

未分类

nginx/apache 配置静态资源允许跨域访问

有时为了优化网站访问速度,会给一些静态资源配置cdn加速,但是有时候会出现跨域访问的问题,在nginx和apache服务中可进行如下配置

1. apache

找到apache配置文件httpd.conf

找到这行

#LoadModule headers_module modules/mod_headers.so

把#注释符去掉

LoadModule headers_module modules/mod_headers.so

目的是开启apache头信息自定义模块

在独立主机配置文件中新增header

Header set Access-Control-Allow-Origin *

例如:

<VirtualHost *:88>
  ServerAdmin [email protected]
  DocumentRoot "****************"
  ServerName www.jianzhi12.com
  Header set Access-Control-Allow-Origin *

  ErrorLog "***********"
  CustomLog "****************************" common
<Directory "**************">
  SetOutputFilter DEFLATE
  Options FollowSymLinks ExecCGI
  Require all granted
  AllowOverride All
  Order allow,deny
  Allow from all
  DirectoryIndex index.html index.php
</Directory>
</VirtualHost>
ApacheCopy

意思是对这个域名的资源进行访问时,添加一个头信息

重启apache

service httpd restart

2. nginx

同理 找到相应域名配置文件

在server模块中添加配置:

add_header ‘Access-Control-Allow-Origin’ ‘*’;1

例:

server {
        listen       80;
        add_header 'Access-Control-Allow-Origin' '*';
        location /Roboto/ {
            root   /home/images;
            autoindex on;
        }
    }

nginx重载

./nginx -s reload

Apache、Nginx、php-fpm为PHP设置、添加$_SERVER服务器环境变量

在PHP开发中为了区分线上生产环境还是本地开发环境,

如果我们能通过判断$_SERVER['RUNTIME_ENVIROMENT']'DEV'还是'PRO'来区分该多好,

可惜的是$_SERVER数组里面根本没有RUNTIME_ENVIROMENT这个元素。

一、通过nginx的fastcgi_param来设置

在nginx配置文件中,可以在nginx总体的配置文件nginx.conf中,也可以在单独的网站配置环境中进行设置,如:www.regskynet.com.conf

在配置环境server段location中添加相应的配置信息:

    location ~ .php$ {
        limit_conn conn_zone 15;
        limit_req zone=req_zone burst=25 nodelay;
        try_files $uri /index.php =404;
        fastcgi_split_path_info ^(.+.php)(/.+)$;
        root           $root;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $root$fastcgi_script_name;
        include        fastcgi_params;
        fastcgi_param  RUNTIME_ENVIROMENT 'PRO';
    }

然后重启重启nginx

service nginx reload

二、通过php主配置文件php-fpm.conf来设置

这个设置必须放在主配置文件php-fpm.conf里,不能放到include指令设置的子配置文件里,否则会报错:「Array are not allowed in the global section」

我的php-fpm.conf位置在/etc/php-fpm.conf

直接在配置文件中添加:

env[RUNTIME_ENVIROMENT] = 'PRO'

添加后重启php-fpm

service php-fpm reload

通过上面2种方式添加$_SERVER变量值后,我们就可以直接在php文件中通过$_SERVER来获取相应的变量值了。

不过据说配置信息通过nginxfastcgi_param来设置的话,当nginx和php交互时,会带来大量的数据传输。

三、通过Apache设置环境变量

SetEnv 变量名 变量值

<VirtualHost *:80>
    ServerAdmin ...
    DocumentRoot ...
    ServerName www.regskynet.com
    ErrorLog ...
    CustomLog ...
    SetEnv RUNTIME_ENVIROMENT PRO
    <Directory "...">
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Apache/Nginx中Host头攻击的一些差异

1. Host header

服务器的域名(用于虚拟主机 ),以及服务器所监听的传输控制协议端口号。如果所请求的端口是对应的服务的标准端口,则端口号可被省略。
自超文件传输协议版本1.1(HTTP/1.1)开始便是必需字段。
以上是维基百科中对于Host头部的说明。可以看到Host头部并非是用于区别发送到哪台主机的字段。而是用于区分一台主机上不同的虚拟主机。(可以在Apache和Nginx中配置相应Host对应的虚拟主机。

利用PHP可以在 $_SERVER['HTTP_HOST'] 字段中获取到该字段的值

var_dump($_SERVER['HTTP_HOST']);

未分类

当没有配置虚拟主机或者匹配不到对应的Host主机时,webserver就会发送请求到默认的目录中去解析

从而Host头部就变成了一个可控的字段,当一些应用程序没有对$SERVER[‘HTTP_HOST’]字段进行处理,过分信任时,就会产生一些安全问题

未分类

2. Diff of win/linux

这里用的测试环境分别是

  • win10下的 phpstudy
  • ubuntu 18.04中默认安装的nginx和apache2

在1.php中会输出$_SERVER[‘HTTP_HOST’]变量

2.1 Windows

Apache

可以任意修改apache中的值,服务器都会默认接受

未分类

甚至可以插入两个Host头部,在win下会用,将两个头部相连

Host: localhost
Host:123468

未分类

Nginx

nginx中对于任意脏字符都是允许修改的

未分类

但是在插入两个Host头部的时候只会获取到第二个Host值

Host: localhost
Host: 'select user();

未分类

2.2 Linux

但是在linux中又会有些不同

Apache

linux下的apache就有着较为严格的限制,只允许修改对应的ip数字

未分类

插入一些脏字符就会返回400的错误

Host: 192.168.85.145'

未分类

两个头部也是一样的情况,即使头部是合法的

Host: 192.168.85.145
Host: 192.168.85.145

未分类

Nginx

linux下nginx中对于Host的处理类似于win中的就不过多介绍

未分类

从而网上有一些防御手段就变成了设置虚拟主机(virtual host),从而可以确保Host字段不会被更改,因为一旦修改了Host字段就不会解析到对应的目录当中。

3. Virtual Host

但即使配置了虚拟主机之后,所接受的Host字段就是可以信任的么?

在Apache、Nginx中会呈现不同的状态

测试环境为

  • ubuntu 18.04
  • Apache/2.4.29 (Ubuntu)
  • nginx/1.14.0 (Ubuntu)
  • PHP 7.2.10-0ubuntu0.18.04.1

至于虚拟主机配置的部分就不过多介绍,在网上可以找到很多配置的文章

至于域名,可以买一个域名修改解析,或者直接修改host文件

然后在/var/www目录下新建了三个文件夹

  • html 默认主目录
  • apache Apache的虚拟主机目录
  • nginx Nginx的虚拟主机目录

3.1 Apache

可以看到,在配置了虚拟主机之后,访问对应的域名就会访问到对应的目录中

Host: localhost.ba123.top

未分类

当遇到一个不认识的域名的时候,就会解析到默认目录下(当然,假如默认目录下没有1.php这个文件就会返回一个404

Host: localhost.ba123.to

未分类

那想攻击Apache中的虚拟主机时Host字段就不能添加别的脏字符了么?目前找到的可以添加的就只有通过冒号:分割开的端口号

只要是一个合法的端口就可以发起正常的请求

Host: localhost.ba123.top:23333

未分类

但是当想插入一些字符或者端口号过大的时候,都会拒绝请求,返回一个400,更不会允许两个Host头部的请求

Host: localhost.ba123.top:23333'select

未分类

总体来说,Apache对于Host字段的限制还是比较严格的,在开启了虚拟主机之后,几乎比较难以插入脏字符。

3.2 Nginx

在nginx中似乎有着更多的攻击手法

对于未知的主机名,处理方式还是与apache中一致,会解析到默认目录中

Host: localhost.ba123.to'select

未分类

但是这里假如利用冒号:的形式分割之后,冒号后面的port部分会直接被nginx给抛弃,从而可以插入任意的字符

Host: localhost.ba123.top'select sleep(5);

未分类

甚至在nginx中可以传入两个Host头部,Nginx将以第一个为准传送到对应的虚拟主机处理,而PHP-FPM将以第二个为准给$_SERVER[‘HTTP_HOST’]赋值。

Host: localhost.ba123.top
Host:'select sleep(5);

未分类

但是在apache中传入两个Host头部的时候,就会直接返回400

由此可见,在ngin中对于Host的并没有做过多的限制,从而可以比较容易的进行Host头部攻击。

windows上的虚拟主机原谅我确实没怎么遇到过,就没测试了,感兴趣的可以自己测试下。

4. Summary

可以看到Host头部,在不同的情况下会呈现出不同的状态,因此在编写程序的时候一定要将Host这个值设置为不可信任的,对其进行一些正则或者转义的一些过滤。否则极易引发安全问题。

在windows下对于这种头部的限制比较松,apache和nginx都能比较轻松的绕过去。

而在两个服务器相比,Apache对于数据的解析更加严谨,尤其是在linux的环境中,极大的限制了非法的请求。

Nginx则甚至会出现Nginx与PHP-FPM解析不一致的情况,有时这种解析不一样甚至会带来更多的危害。

5. Reference

https://www.leavesongs.com/PENETRATION/some-tricks-of-attacking-lnmp-web-application.html