Nginx安装及应用

ng安装

下载源码包

[root@ghs etc]# wget http://nginx.org/download/nginx-1.20.2.tar.gz

解压和创建nginx用户及安装依赖

[root@ghs tmp]# tar -zxvf nginx-1.20.2.tar.gz
[root@ghs tmp]# useradd -s /sbin/nologin -M nginx
[root@ghs tmp]# yum -y install gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel

编译

[root@ghs nginx-1.20.2]# ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --with-pcre-jit --with-http_ssl_module --with-http_v2_module --with-http_sub_module --with-stream --with-stream_ssl_module
 
初始化中出现的错误
./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.
提示错误缺少pcre包
 
./configure: error: the HTTP gzip module requires the zlib library.
You can either disable the module by using --without-http_gzip_module
option, or install the zlib library into the system, or build the zlib library
statically from the source with nginx by using --with-zlib=<path> option.
提示错误缺少zlib-devel包

解决方法

[root@ghs nginx-1.20.2]# yum -y install pcre-devel zlib-devel
[root@ghs nginx-1.20.2]# make && make install

设置环境变量

[root@ghs nginx-1.20.2]# cat /etc/profile.d/path.sh
#!/bin/bash
export PATH=$PATH:/usr/local/nginx/sbin

[root@ghs nginx-1.20.2]# source !$

启动nginx

[root@ghs nginx-1.20.2]# nginx
[root@ghs nginx-1.20.2]# ps aux|grep nginx
root     16203  0.0  0.0  48960  3300 ?        Ss   Jun01   0:00 nginx: master process nginx
nobody   18542  0.0  0.2  74712  8324 ?        S    Aug26  22:44 nginx: worker process
nobody   18543  0.2  0.2  74720  8388 ?        S    Aug26  84:12 nginx: worker process
root     30071  0.0  0.0 112708   980 pts/0    R+   15:33   0:00 grep --color=auto nginx

添加systemctl管理

[root@ecs-cc4c-0002 ~]# cat /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target

拓展

脚本按天切割Ng日志

#!/bin/bash
Date=`date -d '-1 day' '+%Y-%m-%d'`
cd /var/log/nginx && mkdir logs/$Date
for i in access.log error.log
do
    gzip -c $i  > logs/$Date/"$i"_"$Date".gz
    echo " " >  $i
    find logs/ -ctime +30 | xargs rm -f
done

error_page处理错误信息

fastcgi_intercept_errors on;
#语法:fastcgi_intercept_errors on|off
#默认值:fastcgi_intercept_errors off
#使用字段:http, server, location 
#该指令指定是否传递4xx和5xx错误信息到客户端,或者允许nginx使用error_page处理错误信息
#你必须明确的在error_page中指定处理方法使这个参数有效,正如Igor所说“如果没有适当的处理方法,nginx不会拦截一个错误,这个错误不会显示自己的默认页面,这里允许通过某些方法拦截错误

server {
...
error_page 404 /etc/nginx/error_page/404.html;
error_page 500 502 503 504 /etc/nginx/error_page/500.html;
...
}

设置HSTS

#HTTP严格传输安全(HSTS)是一种安全功能,web服务器通过它来告诉浏览器仅用HTTPS来与之通讯,而不是使用HTTP。
#实际使用中用户很少直接在地址栏输入https://这种方式访问,而是通过点击链接或在地址栏直接输入网址然后通过3xx重定向从HTTP页面进入HTTPS页面。那么访问者在重定向前的初始会话是非加密的。这就给了中间人攻击的一个机会,重定向可能会被破坏,从而定向到一个恶意站点而不是应该访问的加密页面。
#HTTP 严格传输安全(HSTS)功能使 Web 服务器告知浏览器绝不使用 HTTP 访问,在浏览器端自动将所有到该站点的 HTTP 访问替换为 HTTPS 访问。另外,如果中间人使用自己的自签名证书来进行攻击,浏览器会给出警告,但是许多用户会忽略警告。HSTS解决了这一问题,一旦服务器发送了HSTS字段,用户将不再允许忽略警告。
#注意,如果之前没有使用HTTPS协议访问过该站点,那么HSTS是不奏效的,只有浏览器曾经与服务器创建过一次安全连接并且网站通过HTTPS协议告诉浏览器它支持HSTS,那么之后浏览器才会强制使用HTTPS,即使链接被换成了HTTP。
#服务器开启HSTS的方法是当客户端通过HTTPS发出请求时,在服务器返回的响应头中包含Strict-Transport-Security 字段。使用HTTP协议传输时设置HSTS字段无效。

server {
...
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
...
}

基线安全加固

#!/bin/bash
set -e
sed -i 's/#user  nobody/user  nginx/' /usr/local/nginx/conf/nginx.conf
sed -i 's#worker_processes.*#worker_processes auto\;#g' /usr/local/nginx/conf/nginx.conf
sed -i 's#worker_connections.*#worker_connections 65535\;#g' /usr/local/nginx/conf/nginx.conf
sed -i '/events/a\    use epoll\;' /usr/local/nginx/conf/nginx.conf
sed -i 's#\#keepalive_timeou.*##g' /usr/local/nginx/conf/nginx.conf
sed -i '/sendfile/a\    send_timeout 10\;' /usr/local/nginx/conf/nginx.conf
sed -i '/sendfile/a\    client_body_timeout 10\;' /usr/local/nginx/conf/nginx.conf
sed -i '/sendfile/a\    client_header_timeout 10\;' /usr/local/nginx/conf/nginx.conf
sed -i '/sendfile/a\    server_tokens off\;' /usr/local/nginx/conf/nginx.conf
sed -i '/keepalive_timeout/a\    limit_conn_zone \$binary_remote_addr zone=one:10m\;' /usr/local/nginx/conf/nginx.conf
sed -i '/keepalive_timeout/a\    limit_conn_status 503\;' /usr/local/nginx/conf/nginx.conf
sed -i '/        location \//a\\tlimit_conn one 10\;' /usr/local/nginx/conf/nginx.conf
sed -i '/        location \//a\\tlimit_rate 10240k\;' /usr/local/nginx/conf/nginx.conf
sed -i '/\#error_page/a\        error_page   400 404 413 \/40x.html\;' /usr/local/nginx/conf/nginx.conf
sed -i '/error_page   400/a\\tlocation = \/40x.html {\n\t    root    html\;\n\t\}' /usr/local/nginx/conf/nginx.conf

TLS版本过低

控制台提示:The connection used to load resources from https://xxx.test.com used TLS 1.0 or TLS 1.1, which are deprecated and will be disabled in the future. Once disabled, users will be prevented from loading these resources. The server should enable TLS 1.2 or later. See https://www.chromestatus.com/feature/5654791610957824 for more information.

这是由于TLS版本过低导致,需要升级openssl版本(1.0.1以上的版本支持 TLS1.2,1.1.1以上的版本支持 TLS1.3)并重新编译nginx

openssl升级可以参考另外一篇文章,这里只贴出nginx编译升级的过程

# nginx编译升级
# 安装所需依赖(openssl编译升级过的无需通过yum安装)
yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel
# 下载安装包
cd ~ && wget https://nginx.org/download/nginx-1.17.1.tar.gz
# 解压
tar -zxf nginx-1.17.1.tar.gz
# 查看nginx启用的模块
nginx -V > /root/test.txt 2>&1
modules=`cat /root/test.txt |awk -F':' 'NR==5{print $2}'`
# 编译升级(切勿make install)
cd nginx-1.17.1 && ./configure $modules && make
# 备份nginx执行文件
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx-bak
# 替换新版本nginx执行文件
nginx -s quit && \cp objs/nginx /usr/local/nginx/sbin/nginx
# 启动nginx服务
/usr/local/nginx/sbin/nginx

批量修改

# 批量注释以前的配置
for i in `ls`;do echo sed -i 's/^ssl_protocols/#&/' $i;done
# 指定内容的下一行添加配置(/a)
for i in `ls`;do sed -i '/#ssl_protocols/assl_protocols TLSv1 TLSv1.1 TLSv1.2;' $i;done

# 启用所有协议,禁用已废弃的不安全的SSLv2和SSLv3(必须在所有站点中配置以下参数才能生效,上面的sed已添加)
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

注意:./configure $modules时,如openssl编译升级过的,需要指定路径:./configure xxxxx --with-openssl=/usr/local/include/openssl

如仍然报错找不到openssl模块等,需要修改nginx源码包openssl的配置文件

$ vim /root/nginx-1.17.1/auto/lib/openssl/conf
# 将以下配置进行相应的修改(find一下就知道路径各个模块的路径了)
# $OPENSSL变量的值是--with-openssl指定的路径

            CORE_INCS="$CORE_INCS $OPENSSL/"
            CORE_DEPS="$CORE_DEPS $OPENSSL/ssl.h"
            CORE_LIBS="$CORE_LIBS /usr/local/lib64/libssl.a"
            CORE_LIBS="$CORE_LIBS /usr/local/lib64/libcrypto.a"
            CORE_LIBS="$CORE_LIBS $NGX_LIBDL"

控制Nginx并发连接数量

ngx_http_limit_conn_module这个模块用于限制每个定义key值得连接数,特别是单个TP的连接数。 不是所有的连接数都会被计算。一个符合计数要求的连接是整个请求头已经被读取的连接。

http {
    ...
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    ...
}
server {
    listen 80 default;
    server_name localhost;
    location / {
         limit_conn addr 6;
        limit_rate_after 10m;
        limit_rate 100k;
        limit_conn_status 488;
        limit_conn_log_level warn;
        root  /usr/nginx/share/html;
    }
}

----------
|参数说明 |
----------
http区域
 $binary_remote_addr:限制同一客户端 ip 地址。
 zone=addr:10m:生成一个大小为10M,名字为 addr 的内存区域,用来存储访问的频次信息。
server 区域,可以直接写在 server 区域内,表示限制所有,也可以写到对应的 location 当中,以表示单独区域限制。
 limit_conn:表示单个 IP 限制最大连接数为 6。
 limit_rate_after:表示请求前 10m 大小时不限速。
 limit_rate:表示单个连接最大连接带宽限制为 100k。
 limit_conn_status:设置拒绝请求的返回值(当超过最大连接数时触发)。值只能设置 400 到 599 之间(默认是 503)
 limit_conn_log_level:定义日志级别,默认 error。

控制客户端请求Nginx的速率

ngx_http_limit_req_module模块用于限制每个IP访问每个定义key的请求速率。

limit_req_zone参数说明如下。 
  语法:limit_req_zone key zone=name:size rate=rate; 
  上下文:http 
  用于设置共享内存区域,key可以是字符串,Nginx自带变量或前两个组合。name为内存区域的名称,size为内存区域的大小,rate为速率,单位为r/s,每秒一个请求。 
limit_req参数说明如下: 
  语法:limit_req zone=name [burst-number] [nobelay] 
  上下文:http、server、location 
  这里运用了令牌桶原理,burst=num,一个有num快令牌,令牌发完后,多出来的那些请求就会返回503。 
       nodelay默认在不超过burst值得前提下会排队等待处理,如果使用此参数,就会处理完num+1次请求,剩余的请求为超时,返回503。

http{
...
# 区域名称allips,大小10m,平均处理的请求频率不能超过每秒10次,键值是客户端IP
    limit_req_zone $binary_remote_addr zone=allips:10m rate=10r/s;
...
}

server{
...
    location / {
        # 限制每个IP只能同时发起10次连接
        limit_conn addr 10;
        # 限制平均每秒不超过一个请求,同时允许超过频率限制的请求数不多于5个,如果不希望超过的请求被延迟,可以用nodelay参数
        limit_req zone=allips burst=50 nodelay;
        root   /home/third/cq_port/html;
        index  index.html index.htm;
    }

}

添加登陆认证访问

#ngx_http_auth_basic_module :实现让用户只有输入正确的用户名密码才允许访问web内容
# 编译时默认已经包含这个模块
# 安装工具
yum -y install httpd

# -c指定密码文件,后面自定义登陆的用户名
htpasswd -c /etc/nginx/passwd nginxuser

# 配置文件server内新增加如下两行
auth_basic "Please input password"; #这里是验证时的提示信息 
auth_basic_user_file /etc/nginx/passwd;

# 验证
nginx -t
nginx -s reload

配置文件优化

user  nginx;
# nginx开启的进程数
worker_processes  auto;

pid        /etc/nginx/nginx.pid;

events {
    # 设置网路连接序列化,防止惊群现象发生,默认为on
    # 惊群现象:一个网路连接到来,多个睡眠的进程被同事叫醒,但只有一个进程能获得链接,这样会影响系统性能
    accept_mutex on;
    # 事件驱动模型 select|poll|kqueue|epoll|resig|/dev/poll|eventport
    use epoll;
    # 指定单进程的最大连接数
    worker_connections  65535;
    # 设置一个进程是否同时接受多个网络连接,默认为off
    multi_accept on;
}


http {
    # 文件扩展名与文件类型映射表
    include       mime.types;
    # 默认文件类型,默认为text/plain
    default_type  application/octet-stream;
    # 关闭nginx版本显示
    server_tokens off;
    # 关闭自动忽略下划线
    # underscores_in_headers on;
    # 设定日志格式
    log_format  main  '客户端地址: $remote_addr - 客户端用户名称: $remote_user 访问时间和时区: [$time_local] URL: "$request" '
                      'HTTP请求状态: $status 发给客户端文件内容大小: $body_bytes_sent URL跳转来源: "$http_referer" '
                      '用户终端信息: "$http_user_agent" 请求总时间: "$request_time" "$http_x_forwarded_for" '
		      'upstream服务地址: "$upstream_addr" upstream状态: $upstream_status upstream相应时间: $upstream_response_time';

    access_log  /etc/nginx/logs/access.log  main;
    # 允许sendfile方式传输文件,默认为off,可以在http块,server块,location块
    sendfile        on;
    # 防止网络阻塞
    tcp_nopush     on;

    # 连接超时时间,默认为75s,可以在http,server,location块
    keepalive_timeout  60;
    # 响应客户端的超时时间
    # send_timeout 60;
    tcp_nodelay    on;
    # 单连接请求上限次数
    keepalive_requests 8192;
    #以请求的客户端IP作为key值,内存区域命名为one,分配10m内存空间,访问速率限制为1秒1次请求(request)
    #limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

    gzip  on;
    # 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
    gzip_min_length  1k;
    # 压缩缓冲区大小,表示申请4个单位为16K的内存作为压缩结果流缓存,默认是申请与原始是数据大小相同的内存空间来存储gzip压缩结果
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    # gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间
    gzip_comp_level 6;
    # 压缩的文件类型
    gzip_types     text/plain text/javascript text/css text/html application/json application/javascript application/x-javascript application/xml application/xml+rss;
    # 让前端的缓存服务器缓存通过gzip压缩的页面
    gzip_vary on;
    # Nginx 作为反向代理的时候启用,决定开启或者关闭后端服务器返回的结果是否压缩,匹配的前提是后端服务器必须要返回包含”Via” 的 header 头
    gzip_proxied   expired no-cache no-store private auth;
    gzip_disable   "MSIE [1-6]\.";


    # http_proxy 设置
    # 客户端请求头部的缓冲区大小
    #client_header_buffer_size 4k;
    # 允许客户端请求的最大文件字节数,默认1m
    client_max_body_size 5m;
    # 缓冲区代理缓冲用户端请求的最大字节数
    client_body_buffer_size 128k
    # 设置读取客户端请求标头的缓冲区大小
    #client_header_buffer_size 1k;
    # 设置用于读取大客户端请求标头的最大值number和size缓冲区
    #large_client_header_buffers 4 8k;

    include /usr/local/nginx/conf/vhost/*.conf;

    # 负载均衡池
    upstream backend {
        #ip_hash;
        server 192.168.10.10:8080 max_fails=2 fail_timeout=30s;
        server 192.168.10.11:8080 max_fails=2 fail_timeout=30s;
    }

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass http://backend;
            # 重定向客户端对/发起的请求转发到/main/index.html
            rewrite ^/$ /main/index.html redirect;
            # 客户端发起请求时,使用代理端的ip和端口
            proxy_set_header Host $host:$server_port;
            # 客户端发起请求时,使用代理端的ip和源端口
            # proxy_set_header Host $host;
            # 后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
#            使用前面定义的名为one的内存空间,队列值为5,即可以有5个请求排队等待
#            limit_req zone=one burst=5; 

	# 防爬虫
#	if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot"){
#		return 403;
#	    }
#        }

#	HTTP只能使用GET、HEAD和POST方法
#       if ($request_method !~ ^(GET|HEAD|POST)$ ) {
#           return 501;
       }

        #error_page  404              /404.html;

	# 防盗链:referers不是*.baidu.cn的话,就给他一个跳转
#	location ~* ^.+\.(jpg|png|swf|flv|rar|zip)$ {
#	    valid_referers none blocked *baidu.cn baidu.cn;
#	    if ($invalid_referer) {
#		rewrite ^/ http://www.baidu.cn/img/nolink.gif;
#	    }
#	    root html/www;
#	}

        # 让用户浏览器本地缓存文件1天
        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires      30d;
        }
	# 缓存css js 12小时
        location ~ .*\.(js|css)?$
        {
            expires      12h;
        }
	# nginx下禁止访问*.txt|doc文件
#	location ~*\.(txt|doc)$
#	{
#	    if (-f $request_filename) {
#		root /home/wwwroot;
#		break;
#	    }
#	}
#	location ~*\.(doc|txt)${
#	    root /home/wwwroot;
#	    deny all;
#	}
	# 禁止以下目录运行可执行程序文件
	location ~ ^/images/.*\.(php|php5|.sh|.pl|.py)$
	{
	    deny all;
	}
	location ~ ^/static/.*\.(php|php5|.sh|.pl|.py)$
	{
	    deny all;
	}
	location ~ ^/data/.*\.(php|php5|.sh|.pl|.py)$
	{
	    deny all;
	}

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

	# 匹配不记录日志的元素扩展名,然后关掉了日志
        location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF)?$ {
        access_log off;
	}
    }
}

proxy_cookie_path

使用场景:

cookie 的 path 与地址栏上的 path 不一致,浏览器就不会接受这个 cookie,无法传入 JSESSIONID 的 cookie 导致登录验证失败

说明文档:

Module ngx_http_proxy_module (nginx.org)

配置举例:

location /etc-job/api/ {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://10.55.3.139:8088/api/;
    proxy_cookie_path / /etc-job/api/;
    proxy_set_header   Cookie $http_cookie;
}

域名Https无法加载js和css样式

# 域名配置Https后无法加载js、css样式
location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header Upgrade-Insecure-Requests 1;
    proxy_set_header X-Forwarded-Proto https;
    add_header Content-Security-Policy upgrade-insecure-requests;
}

socket代理

# stream与http模块平级
stream {
    upstream socket_proxy {
        # Hash负载平衡方法还用于配置会话持久性。由于散列函数基于客户端IP地址,因此来自给定客户端的连接始终传递到同一服务器,除非服务器已关闭或不可用。
        # hash $remote_addr consistent
        server 192.168.2.111:6443 weight=5 max_fails=3 fail_timeout=30s;
}
    server {
        listen       2222;
        # 与后端/上游服务器建立连接的超时时间,默认60s
        proxy_connect_timeout 3s;
        # 接收后端响应内容超时
        proxy_timeout 3s;
        proxy_pass socket_proxy;
   }
}

文件服务器

server {
        listen 28080;
        server_name localhost;

        location ~ .*\.jar {
            deny all;
        }
        location / {
            # 只显示,不下载
            add_header Content-Type text/plain;
            root /opt/background;
            autoindex on;
            autoindex_exact_size on;
            autoindex_localtime on;
            access_log off;
        }
    }

 

posted @ 2019-10-08 16:41  MegaloBox  阅读(311)  评论(0编辑  收藏  举报