跳至主要內容

Nginx安装部署

三思原创大约 14 分钟nginxnginx

本文介绍了使用预编译包安装Nginx的步骤,包括选择适合操作系统版本的预编译包、上传安装、启动、关闭和重载配置等操作。同时还提供了Nginx主要目录结构和配置文件说明。

image
image

Nginx安装部署

安装部署

预编译包安装

优势:零依赖,秒级安装 劣势:不可定制

根据操作系统选取预编译包

查看操作系统版本

cat /etc/redhat-release

上传安装

rpm -ivh nginx-*-neu.el?.x86_64.rpm

启动(对应/opt/nginx/sbin/nghinx​)

service nginx start

关闭(对应/opt/nginx/sbin/nghinx -s stop​)

service nginx stop

重载配置(对应/opt/nginx/sbin/nghinx -s reload​)

service nginx reload

目录说明

/opt/nginx/  # 主目录
├── conf # 配置主目录
│   ├── bots.d # ip黑名单(内置,无需调整)
│   │   ├── bad-referrer-words.conf
│   │   ├── blacklist-ips.conf
│   │   ├── blacklist-user-agents.conf
│   │   ├── blockbots.conf
│   │   ├── custom-bad-referrers.conf
│   │   ├── ddos.conf
│   │   ├── whitelist-domains.conf
│   │   └── whitelist-ips.conf
│   ├── conf.d # 自定义配置目录,该目录下所有*.conf文件会被引用
│   │   ├── botblocker-nginx-settings.conf # 限流配置
│   │   ├── example # 配置样例
│   │   │   ├── drugstore.conf.example # 医药服务
│   │   │   ├── ehrss.conf.example # 网厅
│   │   │   ├── hxpt.conf.example # 核心平台
│   │   │   ├── inner.conf.example
│   │   │   ├── kbms.conf.example 
│   │   │   └── medicine.conf # 医保
│   │   ├── globalblacklist.conf # 无需调整
│   │   ├── http.proxy # 反向代理相关header,配置后台代理时需要引用(include conf.d/http.proxy;)
│   │   ├── nginx.refrence
│   │   └── white.rules # naxsi防火墙白名单
│   ├── fastcgi.conf 
│   ├── fastcgi.conf.default
│   ├── fastcgi_params
│   ├── fastcgi_params.default
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types
│   ├── mime.types.default
│   ├── naxsi # naxsi配置目录(防护sql注入,XSS等)
│   │   ├── naxsi_core.rules
│   │   └── naxsi.rules
│   ├── nginx.conf # nginx主配置文件
│   ├── nginx.conf.default
│   ├── scgi_params
│   ├── scgi_params.default
│   ├── tcp.d # tcp代理目录(所有*.conf文件会被引用)
│   │   └── example.conf
│   ├── uwsgi_params
│   ├── uwsgi_params.default
│   ├── waf # waf防火墙配置(请求方法、Host白名单、Referer、Url等)
│   │   ├── access.lua
│   │   ├── black
│   │   │   ├── args
│   │   │   ├── cookie
│   │   │   ├── post
│   │   │   ├── url
│   │   │   ├── user-agent
│   │   │   └── whiteurl
│   │   ├── config.lua
│   │   ├── init.lua
│   │   └── white
│   │       ├── host
│   │       ├── method
│   │       └── referer
│   └── win-utf
├── html
│   ├── 50x.html
│   └── index.html
├── lj2 # lua相关库
│   ├── bin
│   │   ├── luajit -> luajit-2.0.5
│   │   └── luajit-2.0.5
│   ├── include
│   │   └── luajit-2.0
│   │       ├── lauxlib.h
│   │       ├── luaconf.h
│   │       ├── lua.h
│   │       ├── lua.hpp
│   │       ├── luajit.h
│   │       └── lualib.h
│   ├── lib
│   │   ├── libluajit-5.1.a
│   │   ├── libluajit-5.1.so -> libluajit-5.1.so.2.0.5
│   │   ├── libluajit-5.1.so.2 -> libluajit-5.1.so.2.0.5
│   │   ├── libluajit-5.1.so.2.0.5
│   │   ├── lua
│   │   │   └── 5.1
│   │   └── pkgconfig
│   │       └── luajit.pc
│   └── share
│       ├── lua
│       │   └── 5.1
│       ├── luajit-2.0.5
│       │   └── jit
│       │       ├── bc.lua
│       │       ├── bcsave.lua
│       │       ├── dis_arm.lua
│       │       ├── dis_mipsel.lua
│       │       ├── dis_mips.lua
│       │       ├── dis_ppc.lua
│       │       ├── dis_x64.lua
│       │       ├── dis_x86.lua
│       │       ├── dump.lua
│       │       ├── v.lua
│       │       └── vmdef.lua
│       └── man
│           └── man1
│               └── luajit.1
├── logs # 日志目录
│   ├── access.log # 访问日志
│   ├── error.log # 错误日志
│   └── tcp.log # tcp代理日志
└── sbin
    └── nginx # nginx二进制文件(事实上的'程序')

源码编译安装

提示

适用于CentOS Red Hat

1、yum可用性检测

  • yum可用情况

尝试yum安装vim

yum install -y vim
echo $?

若返回值为0,证明安装完成,如非0说明yum有问题,yum配置方式参考open in new windowopen in new window

2、安装nginx

上传安装包open in new windowopen in new window至目标服务器/tmp目录下,root执行:

tar zxvf nginx-deploy-latest.tar.gz && cd nginx && sh install.sh && cd -

3、配置文件说明

  • 主配置文件:/opt/nginx/conf/nginx.conf
  • 自定义配置文件:/opt/nginx/conf/conf.d/*.conf

即/opt/nginx/conf/conf.d/下创建以.conf​结尾的文件,重启生效

4、启停命令

  • 启动
/opt/nginx/sbin/nginx
  • 关闭
/opt/nginx/sbin/nginx -s stop
  • 重载配置
/opt/nginx/sbin/nginx -s reload
  • 检测配置
/opt/nginx/sbin/nginx -t

dpkg安装Nginx

Debian使用apt-get作为软件包管理器,所以我们可以使用apt-get直接安装dpkg,进而安装Nginx:

sudo apt-get install nginx

安装完以后,输入whereis nginx​查看Nginx的安装位置,其中的nginx.conf​为Nginx的配置文件。

这样的方法很简单,也十分快但是坏处也很明显:

  • 无法自定义Nginx模块

Docker安装Nginx

Docker上安装Nginx

Docker上安装Nginx

Docker安装Nginx其实和dpkg安装差不多,在安装了Docker情况下

# 查找Nginx
docker search nginx

查找Nginx镜像

查找Nginx镜像

使用命令拉取镜像到本地

docker pull nginx

pull操作

pull操作之后,查看镜像ID:

docker images nginx

查看ID

查看ID

根据ID,创建Docker容器,并完成80端口的映射:

docker run -d --name myNginx -p 80:80 d1a

创建容器

创建容器

此时,浏览器登陆即可看到Nginx页面:

Nginx页面

Nginx页面

至于修改镜像,个人推荐把Docker镜像挂载到Linux上进行修改。

总的来说,Docker安装的Nginx,我觉得配置起来,和dpkg安装Nginx​差不多。

手动编译安装Nginx

手动编译安装

手动编译安装

手动编译安装Nginx比较复杂,但是平时一般使用最多。原因:

  • 便于管理 编译安装的Nginx,其安装地址可控,如果需要卸载,执行反编译即可。
  • 模块可控 Nginx有其丰富的模块库,如:ngx-fancyindexopen in new window。使用Docker或软件包管理器安装的Nginx,模块有时不方便载入。

现在就来讲解如何编译安装Nginx。

在这之前,首先确保的软件包没过时:

sudo apt-get update

环境准备

编译Nginx需要gcc+的环境支持,build-essential内包含gcc+套件,所以我们安装build-essential即可:

sudo apt-get install build-essential

安装build-essential

安装build-essential

*Tips*​ ________:你也可以自己编译gcc+

因为nginx.conf中使用了正则表达式,所以编译Nginx时就需要把PCRE库编译进Nginx,而Debian内安装PCRE库,可以这样安装:

sudo apt-get install libpcre3 libpcre3-dev

安装libpcre3和libpcre3-dev

安装libpcre3和libpcre3-dev

当热,Nginx编译过程和Http相应过程还需要gzip​格式的压缩,所以我们还需要安装zlib库​用于对HTTP包的内容做gzip格式的压缩,可以这样安装:

sudo apt-get install zlib1g-dev

安装 zlib1g-dev

安装 zlib1g-dev

最后,现在SSL协议很重要,Chrome等主流浏览器,都开始默认相应HTTPS了,所以OpenSSL编译环境也很重要:

sudo apt-get install openssl libssl-dev

安装openssl和libssl-dev库

安装openssl和libssl-dev库

另外,如果你不想安装OpenSSL,或者想指定第三方OpenSSL用于编译,可以在Nginx编译时添加编译参数:--with-openssl

下载Nginx源码

接下来,我们下载并解压Nginx的源码,Nginx源码下载官方地址:

http://nginx.org/en/download.htmlopen in new window

开发环境,我们使用最新稳定版本Nginx:

下载Nginx源码

下载Nginx源码

# 下载Nginx 1.20.1源码(Stable稳定版本)
wget "http://nginx.org/download/nginx-1.20.1.tar.gz"
# 使用tar命令解压
tar -xf nginx-1.20.1.tar.gz
# 进入解压后出现的目录,已备接下来的编译
cd nginx-1.20.1

编译Nginx

首先,我们需要生成makefile文件,编译时候的参数可以参考官方Nginx文档:

http://nginx.org/en/docs/configure.htmlopen in new window

我自己编译Nginx时候,选择的参数一般是:

./configure \--prefix=/etc/nginx \--sbin-path=/usr/sbin/nginx \--conf-path=/etc/nginx/nginx.conf \--error-log-path=/var/log/nginx/error.log \--http-log-path=/var/log/nginx/access.log \--pid-path=/var/run/nginx.pid \--lock-path=/var/run/nginx.lock \--http-client-body-temp-path=/var/cache/nginx/client_temp \--http-proxy-temp-path=/var/cache/nginx/proxy_temp \--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \--http-scgi-temp-path=/var/cache/nginx/scgi_temp \--user=www \--group=www \--with-file-aio \--with-threads \--with-http_addition_module \--with-http_auth_request_module \--with-http_dav_module \--with-http_flv_module \--with-http_gunzip_module \--with-http_gzip_static_module \--with-http_mp4_module \--with-http_random_index_module \--with-http_realip_module \--with-http_secure_link_module \--with-http_slice_module \--with-http_ssl_module \--with-http_stub_status_module \--with-http_sub_module \--with-http_v2_module \--with-mail \--with-mail_ssl_module \--with-stream \--with-stream_realip_module \--with-stream_ssl_module \--with-stream_ssl_preread_module 

复制

其中:

  • --prefix:Nginx主要安装路径,后续Nginx子目录依照这个变量展开
  • --user:设置Nginx进程启动时,所属的用户
  • --group:设置Nginx进程启动时,所属的用户组

如果没问题,会显示信息:

Configuration summary
  + using threads
  + using system PCRE library
  + using system OpenSSL library
  + using system zlib library

  nginx path prefix: "/etc/nginx"
  nginx binary file: "/usr/sbin/nginx"
  nginx modules path: "/etc/nginx/modules"
  nginx configuration prefix: "/etc/nginx"
  nginx configuration file: "/etc/nginx/nginx.conf"
  nginx pid file: "/var/run/nginx.pid"
  nginx error log file: "/var/log/nginx/error.log"
  nginx http access log file: "/var/log/nginx/access.log"
  nginx http client request body temporary files: "/var/cache/nginx/client_temp"
  nginx http proxy temporary files: "/var/cache/nginx/proxy_temp"
  nginx http fastcgi temporary files: "/var/cache/nginx/fastcgi_temp"
  nginx http uwsgi temporary files: "/var/cache/nginx/uwsgi_temp"
  nginx http scgi temporary files: "/var/cache/nginx/scgi_temp"

makefile

makefile

之后,执行编译即可:

make && make install

编译安装完成

编译安装完成

这个时候,我们使用浏览器即可看到Nginx已经可以使用了。

集群方案

方案依赖
keepalive虚拟IP
负载均衡硬件设备

1、申请虚拟IP

该IP为浮动IP,与nginx​节点IP vlan id​需一致,并需要备案以免IP冲突

2、安装keepalived

所有nginx​节点(推荐两个节点)安装keepalived

yum install -y keepalived

3、配置keepalived

主节点配置

cat > /etc/keepalived/keepalived.conf <<-'EOF'
! Configuration File for keepalived

global_defs {
   router_id master
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass weiliang
    }
    virtual_ipaddress {
        172.16.145.200/24
    }
}
EOF

从节点配置

cat > /etc/keepalived/keepalived.conf <<-'EOF'
! Configuration File for keepalived

global_defs {
   router_id bakup
}

vrrp_instance VI_1 {
    state BAKUP
    interface ens33
    virtual_router_id 51
    priority 150
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass weiliang
    }
    virtual_ipaddress {
        172.16.145.200/24
    }
}
EOF

需要调整内容:

  • 网卡接口名称: interface ens33​ 改为实际接口名称(ip a​获取)
  • 虚拟IP地址: 172.16.145.200/24​ 改为实际虚拟IP地址

4、启动

centos7

systemctl enable keepalived --now

centos6

service keepalived start
chkconfig keepalived on

主动健康检测

目的:保证负载高可用

配置样例: /opt/nginx/conf/conf.d/test.conf

upstream backend-server {
server 127.0.0.1:8080;
# health check
check interval=5000 rise=2 fall=3 timeout=1000 type=http;
check_http_send "GET /api/actuator/health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
keepalive 16;
}

server {
  listen 8081;
  location /api {
    proxy_pass http://backend-server;
    include conf.d/http.proxy;
  }
  location / {
    alias /opt/nginx/static/frontend/;
  }
}

官方地址open in new windowopen in new window

配置调优

1、upstream 配置 keepalive

upstream backend-server {
server 192.168.1.2:8080;
keepalive 16;
}

server {
	listen 8080;
	location / {
		# Default is HTTP/1, keepalive is only enabled in HTTP/1.1:
	    proxy_http_version  1.1;
	    # Remove the Connection header if the client sends it,
	    # it could be "close" to close a keepalive connection:
	    proxy_set_header    Connection "";
		proxy_pass http://backend-server;
	}
}

#nginx upstream{}默认与上游服务以HTTP1.0进行通信,不具备keepalive能力

https配置样例

获取ssl证书

  • 购买
  • 自签
  • 第三方免费

自签证书

自签脚本ssl.sh​内容

#!/bin/bash

# 域名
export domain=www.example.com

# IP地址(可选)
export address=192.168.1.11

# 国家
export contryName=CN

# 省/州/邦
export stateName=Liaoning

# 地方/城市名
export locationName=Shenyang

# 组织/公司名称
export organizationName=example

# 组织/公司部门名称
export sectionName=develop

echo "Getting Certificate Authority..."
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -sha512 -days 3650 \
  -subj "/C=$contryName/ST=$stateName/L=$locationName/O=$organizationNaem/OU=$sectionName/CN=$domain" \
  -key ca.key \
  -out ca.crt

echo "Create your own Private Key..."
openssl genrsa -out nginx.key 4096

echo "Generate a Certificate Signing Request..."
openssl req -sha512 -new \
  -subj "/C=$contryName/ST=$stateName/L=$locationName/O=$organizationNaem/OU=$sectionName/CN=$domain" \
  -key nginx.key \
  -out $domain.csr

echo "Generate the certificate of your registry host..."
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=$domain
DNS.2=hostname
IP.1=$address
EOF
openssl x509 -req -sha512 -days 3650 \
  -extfile v3.ext \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -in $domain.csr \
  -out nginx.crt

echo "Convert server nginx.crt to $domain.cert..."
openssl x509 -inform PEM -in nginx.crt -out $domain.cert

echo "merge the intermediate certificate with your own certificate to create a certificate bundle..."
cp nginx.crt /etc/pki/ca-trust/source/anchors/nginx.crt
update-ca-trust

echo "successful..."

需要调整内容:

# 域名
export domain=www.example.com

# IP地址(可选)
export address=192.168.1.11

# 国家
export contryName=CN

# 省/州/邦
export stateName=Liaoning

# 地方/城市名
export locationName=Shenyang

# 组织/公司名称
export organizationName=example

# 组织/公司部门名称
export sectionName=develop

nginx所在服务器执行:

mkdir -p /opt/ssl && cd /opt/ssl && sh ssl.sh

配置样例

server {
    listen 5443 ssl;
    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_certificate /opt/ssl/nginx.crt;
    ssl_certificate_key /opt/ssl/nginx.key;
...其他Location配置...
}

免费ssl社区证书

Let's encryptopen in new windowopen in new window

环境依赖:

  • 域名
  • 边界服务器(域名绑定的主机)可访问互联网

基于IP签发ssl证书

DVSSLopen in new windowopen in new window

安全加固

原文地址

https://github.com/trimstray/nginx-admins-handbook#hardeningopen in new windowopen in new window

非root用户运行

nginx.conf -> user xxx;

不间断的更新版本

由于新版本会解决旧版本Bug等,建议每次官方稳定版出来一周后进行nginx升级。

隐藏版本信息

nginx.conf中

http {
	...
	server_tokens off;
	...
}

敏感文件禁止访问

如.git .svn等

server {
	...
	location ~* ^.*(\.(?:git|svn|htaccess))$ {
  		return 403;
	}
	...
}

剔除无用模块

源码编译时剔除

./configure --without-http_autoindex_module

修改nginx server标识

原因说明

https://www.troyhunt.com/shhh-dont-let-your-response-headers/open in new windowopen in new window

nginx.conf中添加(需要编译时引入ngx_headers_more模块)

http {
	...
	more_set_headers "Server: Unknown";
	...
}

剔除不安全HEADER

https://veggiespam.com/headers/open in new windowopen in new window

location / {
	proxy_hide_header X-Powered-By;
	proxy_hide_header X-AspNetMvc-Version;
	proxy_hide_header X-AspNet-Version;
	proxy_hide_header X-Drupal-Cache;
	proxy_pass http://backend-server;
}

配置TLS

https

使用最新版openssl

https://www.openssl.org/policies/releasestrat.htmlopen in new windowopen in new window

#系统自带的一般版本不是最新的,建议自己编译安装

关于openssl版本维护信息

  • the next version of OpenSSL will be 3.0.0

  • version 1.1.1 will be supported until 2023-09-11 (LTS)

    • last minor version: 1.1.1c (May 23, 2019)
  • version 1.1.0 will be supported until 2019-09-11

    • last minor version: 1.1.0k (May 28, 2018)
  • version 1.0.2 will be supported until 2019-12-31 (LTS)

    • last minor version: 1.0.2s (May 28, 2018)
  • any other versions are no longer supported

https安全配置

#一般配置tls证书时需要用到以下配置
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers on;

使用tls时关闭gzip

Some attacks are possible (e.g. the real BREACH attack is a complicated) because of gzip (HTTP compression not TLS compression) being enabled on SSL requests. In most cases, the best action is to simply disable gzip for SSL.

gzip off;

降低XSS劫持配置

add_header Content-Security-Policy "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';" always;
add_header X-XSS-Protection "1; mode=block" always;

配置Referrer-Policy

refer介绍

https://scotthelme.co.uk/a-new-security-header-referrer-policy/open in new windowopen in new window

#http请求分为请求行,请求头以及请求体,而请求头又分为general,request headers,此字段设置与general中,用来约定request headers中的referer

#任何情况下都不发送referer
add_header Referrer-Policy "origin";

可选值

"no-referrer",                     #任何情况下都不发送referer
"no-referrer-when-downgrade",      #在同等安全等级下(例如https页面请求https地址),发送referer,但当请求方低于发送方(例如https页面请求http地址),不发送referer
"same-origin",                     #当双方origin相同时发送
"origin",                          #仅仅发送origin,即protocal+host
"strict-origin",                   #当双方origin相同且安全等级相同时发送
"origin-when-cross-origin",        #跨域时发送origin
"strict-origin-when-cross-origin",
"unsafe-url"                       #任何情况下都显示完整的referer

配置X-Frame-Option

add_header X-Frame-Options "SAMEORIGIN" always;

配置Feature-Policy

Feature Policy是一个新的http响应头属性,允许一个站点开启或者禁止一些浏览器属性和API,来更好的确保站点的安全性和隐私性。 可以严格的限制站点允许使用的属性是很愉快的,而可以对内嵌在站点中的iframe进行限制则更加增加了站点的安全性。

W3C标准

https://w3c.github.io/webappsec-feature-policy/open in new windowopen in new window

add_header Feature-Policy "geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; usb 'none';";

禁用不安全HTTP方法

if ($request_method !~ ^(GET|POST|HEAD)$) {

	return 405;

}

禁止缓存敏感数据

expires 0;
add_header Cache-Control "no-cache, no-store";

防止缓冲区溢出攻击

client_max_body_size    100m;

client_body_buffer_size 128k;

client_header_buffer_size 512k;

large_client_header_buffers 4 512k

waf功能

基于ngx_lua_wafopen in new windowopen in new window项目更改部分内容

该模块可导致nginx 402状态码返回,可查看/opt/nginx/logs/waf.log定位拦截规则

核心功能说明:

  • host白名单
  • referer白名单
  • http方法白名单
  • agent黑白名单
  • url黑名单

引用配置

/opt/nginx/conf/nginx.conf

http {
...
lua_package_path "/opt/nginx/conf/waf/?.lua";
lua_shared_dict limit 10m;
init_by_lua_file  conf/waf/init.lua;
access_by_lua_file conf/waf/access.lua;
...
}

waf开关

/opt/nginx/conf/waf/config.lua

# 是否开启waf,默认true,可选(true|false),总开关,若置为false以下配置不生效
open_waf=true
# 检测url规则黑名单文件为 /opt/nginx/conf/waf/black/url(主要拦截请求隐藏文件及活体检测端点等)
open_check_url=false
# 检测args规则黑名单文件为 /opt/nginx/conf/waf/black/args(主要拦截非法注入等)
open_check_agrs=false
# 检测host合法性,文件为 /opt/nginx/conf/waf/white/host,除配置文件内以外的host全视为非法Host
open_check_host=false
# referer白名单,文件为 /opt/nginx/conf/waf/white/referer
open_check_referer=false
open_check_agent=false
# http方法,白名单/opt/nginx/conf/waf/white/method
open_check_method=false
# 检测body(空body,非法内容等)
open_check_body=false
white_rule_path="/opt/nginx/conf/waf/white/"
black_rule_path="/opt/nginx/conf/waf/black/"
log_path="/opt/nginx/logs/"
open_logging=true