前言:统一互联网出口安全方案,Nginx安全配置。
〇、Nginx 安装-开机自启动
关闭防火墙。
代码语言:javascript复制systemctl stop firewalld.service
systemctl disable firewalld.service
setenforce 0
安装nginx依赖包
代码语言:javascript复制yum -y install wget
yum -y install gcc gcc-c make
yum -y install pcre pcre-devel zlib zlib-devel openssl openssl-devel
# pcre pcre-devel:使nginx支持正则表达式
# zlib zlib-devel:使nginx支持gzip压缩
# openssl openssl-devel:使nginx支持https
上传软件包
代码语言:javascript复制wget http://nginx.org/download/nginx-1.14.0.tar.gz
添加nginx用户
代码语言:javascript复制useradd -M -s /sbin/nologin nginx
# 新建用户 nginx 服务程序默认 以 nobody 身份运行,建议为其创建专门的用户账户,以便更准确的控制访问权限
编译安装nginx
代码语言:javascript复制mv nginx-1.14.0.tar.gz /usr/local
tar zxvf nginx-1.14.0.tar.gz
cd nginx-1.14.0
./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module --with-stream
make&make install
ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginx
rm -rf nginx-1.14.0.tar.gz
rm -rf nginx-1.14.0
检查配置文件
代码语言:javascript复制nginx -t
# nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
# nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
启动nginx进程
代码语言:javascript复制nginx
netstat -antlp | grep 8089
# tcp 0 0 0.0.0.0:8089 0.0.0.0:* LISTEN 67228/nginx: master
ps -aux | grep nginx
# root 67228 0.0 0.1 46180 1972 ? Ss 14:13 0:00 nginx: master process nginx
# nginx 67252 0.0 0.1 48500 1996 ? S 14:15 0:00 nginx: worker process
lsof -i:8089
# nginx 67228 root 12u IPv4 116705 0t0 TCP *:8089 (LISTEN)
# nginx 67252 nginx 12u IPv4 116705 0t0 TCP *:8089 (LISTEN)
测试能否访问成功
代码语言:javascript复制curl 192.168.18.53:8089
tail -f /usr/local/nginx/logs/access.log
# 192.168.18.52 - - [21/Nov/2022:14:54:51 0800] "GET / HTTP/1.1" 200 612 "-" "curl/7.83.1" "-"
# 192.168.18.52 - - [21/Nov/2022:14:54:53 0800] "GET / HTTP/1.1" 200 612 "-" "curl/7.83.1" "-"
# 192.168.18.52 - - [21/Nov/2022:14:54:54 0800] "GET / HTTP/1.1" 200 612 "-" "curl/7.83.1" "-"
nginx开机启动
systemd服务文件以.service结尾。如果用yum install命令安装的,yum命令会自动创建nginx.service文件可以直接使用systemctl相关命令。而用源码编译安装的,则需要手动创建nginx.service服务文件。
代码语言:javascript复制vim /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
代码语言:javascript复制systemctl daemon-reload # 重新加载systemd
nginx服务操作 (启动前停止nginx服务,否则启动时可能出现报错)
代码语言:javascript复制nginx -s stop #停止nginx服务
代码语言:javascript复制systemctl status nginx.service #查看nginx服务状态
systemctl start nginx.service #启动nginx服务
systemctl stop nginx.service #停止nginx服务
systemctl restart nginx.service #重启nginx服务
systemctl reload nginx.service #重新读取nginx配置)
systemctl is-enabled nginx.service #查看nginx是否开机自启动
systemctl enable nginx.service #设置nginx开机自启动
systemctl disable nginx.service #取消nginx开机自启动
一、HTTP服务器
网站只是静态页面,可以通过Nginx来实现部署。
1、创建html目录
代码语言:javascript复制mkdir /usr/local/nginx/www
echo "<h1>hello,world</h1>" >> /usr/local/nginx/www/index.html
2、配置server
nginx.conf
代码语言:javascript复制user nginx; # 运行Nginx的默认账号
worker_processes 5; # 指定 Nginx 要开启的进程数
error_log logs/error.log; # 错误日志
pid logs/nginx.pid; # 用来指定进程id的存储文件位置
events { # 设定nginx的工作模式及连接数上限
worker_connections 1024; # 每个work进程处理的连接数
}
http {
include mime.types; # 指定nginx支持的多媒体文件类型
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'; # 日志格式
sendfile on; # 开启高效文件传输模式
keepalive_timeout 65; # 客户端连接超时时间
gzip on; # 开启gzip模块
include /usr/local/nginx/vhosts_enable/web/*.conf; # 多模块开发(注意路径(实用点))
}
代码语言:javascript复制 mkdir /usr/local/nginx/vhosts_enable/web
vim /usr/local/nginx/vhosts_enable/web/index.conf
index.conf
代码语言:text复制server { # 用于定义服务http中可以有多个server块
listen 8089; # 指定服务器侦听请求的IP地址和端口。如果省略端口,则使用标准端口
# hosts文件添加域名192.168.18.53 www.nginx.com.cn
server_name www.nginx.com.cn; # 服务名称用于配置域名。如果省略地址,服务器将侦听所有地址
charset utf-8;
access_log logs/index/access.log main; # 访问日志
# 用于配置映射路径uri对应的配置,一个server中可以有多个location
# location后面跟一个uri,可以是一个正则表达式
# /表示匹配任意路径, 当客户端访问的路径满足这个uri时就会执行location块里面的代码
location / {
# 根路径
# 当访问http://www.nginx.com.cn/index.html,/index.html会匹配到/uri
# 找到root为/usr/local/nginx/www路径
# 用户访问的资源物理地址=root uri = /usr/local/nginx/www /index.html
# =/usr/local/nginx/www/index.html
root www; # (难点)
# 设置首页,如果访问路径中没有指定具体的文件,则返回index设置的资源
index index.html index.htm;
}
error_page 404 /404.html; # 404错误页面
location = /404.html {
root html;
}
error_page 500 502 503 504 /50x.html; # 50x错误页面
location = /50x.html {
root html;
}
}
测试能否访问成功
代码语言:javascript复制curl www.nginx.com.cn:8089
# <h1>hello,world</h1>
location uri正则表达式(难点)
代码语言:javascript复制. # 匹配除换行符以外的任意字符
? # 重复0次或1次
# 重复1次或更多次
* # 重复0次或更多次
d # 匹配数字
^ # 匹配字符串的开始
$ # 匹配字符串的结束
{n} # 重复n次
{n,} # 重复n次或更多次
[c] # 匹配单个字符c
[a-z] # 匹配a-z小写字母的任意一个
(a|b|c) # 匹配任意一种情况
反斜杠 # 转义特殊字符
二、静态服务器
应用服务器通常会提供一个上传的功能,应用如果需要静态资源就从静态服务器中获取。
index.conf
代码语言:text复制server {
listen 8089;
server_name www.nginx.com.cn;
charset utf-8;
access_log logs/index/access.log main;
set $doc_root /usr/local/nginx/www/static;
location / {
root /usr/local/nginx/www;
index index.html index.htm;
}
# 使用路径 /images/
location ^~ /images/ {
#alias $doc_root; # http://www.nginx.com.cn/usr/local/nginx/www/static/images/
root $doc_root; http://www.nginx.com.cn/images/
}
# 使用后缀 .jpg、.png 等后缀匹配模式
location ~* .(gif|jpg|jpeg|png|bmp|ico|swf|css|js)$ {
root $doc_root/img;
}
error_page 404 /404.html;
location = /404.html {
root html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
代码语言:javascript复制# 创建静态资源目录
mkdir /usr/local/nginx/www/static/
mkdir /usr/local/nginx/www/static/images
mkdir /usr/local/nginx/www/static/img
测试访问
代码语言:javascript复制使用后缀 .jpg、.png 等后缀匹配模式
http://www.nginx.com.cn:8089/favicon.ico --->/usr/local/nginx/www/static/img/favicon.ico
使用路径 /images/一般图片都会放在某个图片目录下
http://www.nginx.com.cn:8089/images/favicon.ico --->/usr/local/nginx/www/static/images/favicon.ico
location路径映射路径
代码语言:javascript复制= # 进行普通字符精确匹配。也就是完全匹配。
^~ # 前缀匹配。如果匹配成功,则不再匹配其他location。
~ # 表示执行一个正则匹配,区分大小写
~* # 表示执行一个正则匹配,不区分大小写
/xxx/ # 常规字符串路径匹配
/ # 通用匹配,任何请求都会匹配到
location优先级:优先级的顺序于location值的表达式类型有关,和在配置文件中的先后顺序无关。
代码语言:javascript复制1、等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项,停止搜索。
2、^~类型表达式,不属于正则表达式。一旦匹配成功,则不再查找其他匹配项,停止搜索。
3、正则表达式类型(~ ~*)的优先级次之。如果有多个location的正则能匹配的话,则使用正则表达式最长的那个
4、/xxx/常规字符串匹配类型。按前缀匹配。
5、/ 通用匹配,如果没有匹配到,就匹配通用的
(location =
) > (location 完整路径
) > (location ^~ 路径
) > (location ~,~* 正则顺序
) > (location 部分起始路径
) > (/
)
三、反向代理
以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端。真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已。
index.conf
代码语言:text复制server {
listen 8089;
server_name www.nginx.com.cn;
charset utf-8;
access_log logs/index/access.log main;
set $doc_root /usr/local/nginx/www/static;
location / {
proxy_pass http://www.nginx.back.com.cn:9090;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; #获取客户端真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
hosts
代码语言:javascript复制192.168.18.53 www.nginx.com.cn
192.168.18.54 www.nginx.back.com.cn
测试访问
代码语言:javascript复制curl www.nginx.com.cn:8089
# {"id":100001,"name":"1neptune"}
四、负载均衡
分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
index.conf
代码语言:javascript复制upstream back_web_servers {
server www.nginx.back.com.cn:9090;
server www.nginx.back.com.cn:9091;
}
server {
listen 8089;
server_name www.nginx.com.cn;
charset utf-8;
access_log logs/index/access.log main;
location / {
proxy_pass http://back_web_servers;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr; #获取客户端真实IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
代码语言:javascript复制[root@www web]# curl www.nginx.com.cn:8089
{"id":100001,"name":"1neptune"}
[root@www web]# curl www.nginx.com.cn:8089
{"id":100002,"name":"lina"}
代码语言:javascript复制upstream oracle {
server 192.168.146.123:1521 weight=1 max_fails=2 fail_timeout=30s;
}
server {
listen 3335;
proxy_connect_timeout 1s;
proxy_timeout 3s;
proxy_pass oracle;
}
upstream mysql {
server 192.168.146.122:3306 weight=1 max_fails=2 fail_timeout=30s;
}
server {
listen 3336;
proxy_connect_timeout 1s;
proxy_timeout 3s;
proxy_pass mysql;
}
}
负载均衡策略
代码语言:javascript复制1、RR(round robin :轮询 默认)
2、权重:weight和访问比率成正比
3、ip_hash:把登录信息保存到了session中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用iphash了,iphash的每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题
4、fair:按后端服务器的响应时间来分配请求,响应时间短的优先分配
5、url_hash:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
权重策略
代码语言:javascript复制upstream test {
server localhost:8081 weight=1;
server localhost:8082 weight=3;
server localhost:8083 weight=4 backup;
}
ip_hash策略
代码语言:javascript复制upstream test {
ip_hash;
server localhost:8080;
server localhost:8081;
}
fair策略
代码语言:javascript复制upstream backend {
fair;
server localhost:8080;
server localhost:8081;
}
url_hash策略
代码语言:javascript复制upstream backend {
hash $request_uri;
hash_method crc32;
server localhost:8080;
server localhost:8081;
}
五、动静分离
让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来。可以根据静态资源的特点将其做缓存操作。Web 缓存分为客户端缓存
和服务端缓存
客户端缓存就是浏览器缓存
,而服务器缓存就是常见的Nginx
、Redis
、Memcached
等。
index.conf
代码语言:text复制upstream back_web_servers {
server www.nginx.back.com.cn:9090;
server www.nginx.back.com.cn:9091;
}
server {
listen 8089;
server_name www.nginx.com.cn;
charset utf-8;
access_log logs/index/access.log main;
set $doc_root /usr/local/nginx/www/static;
location / {
proxy_pass http://back_web_servers;
proxy_set_header Host $host:$server_port;
}
location ^~ /images/ {
root $doc_root;
expires 1d;
add_header description "expires data";
}
location ^~ /img/ {
root $doc_root;
expires 1d;
add_header description "expires data";
}
location ~* .(gif|jpg|jpeg|png|bmp|ico|swf|css|js)$ {
root $doc_root;
expires 1d;
add_header description "expires data";
}
}
六、重定向
return指令:返回http状态码和可选的第二个参数可以是重定向的URL
代码语言:javascript复制if ($scheme = http){
return 301 https://$host$request_uri;
}
代码语言:javascript复制upstream back_web_servers {
server www.nginx.back.com.cn:9090;
server www.nginx.back.com.cn:9091;
}
server {
listen 8089;
server_name www.nginx.com.cn;
charset utf-8;
access_log logs/index/access.log main;
set $doc_root /usr/local/nginx/www/static;
location / {
proxy_pass http://back_web_servers;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
}
location ^~ /root {
return 301 https://$host$request_uri;
}
}
rewirte指令:在请求处理期间多次修改请求URI
代码语言:javascript复制if ($scheme = http) {
rewrite ^(.*)$ https://$host$1 permanent;
}
代码语言:javascript复制if ($host = 'www.nginx.com.cn'){
rewrite ^/(.*)$ http://www.nginx.back.com.cn:9090/$1 break;
}
# 第一个(必需)参数是请求URI必须匹配的正则表达式。
# 第二个参数是用于替换匹配URI的URI。
# 可选的第三个参数是可以停止进一步重写指令的处理或发送重定向(代码301或302)的标志(break,permanent)
代码语言:javascript复制server {
listen 8089;
server_name www.nginx.com.cn;
charset utf-8;
access_log logs/index/access.log main;
#设置是否合法的IP标记
set $rewrite true; #设置变量$rewrite,变量值为boole值true
#判断是否为合法IP
if ($remote_addr = "192.168.18.52"){ #当客户端IP为192.168.18.52时,将变量值设为false,不进行重写
set $rewrite false;
}
#除了合法IP,其它都是非法IP,进行重写跳转维护页面
if ($rewrite = true){ #当变量值为true时,进行重写
rewrite (. ) /weihu.html; #将域名后边的路径重写成/weihu.html,例如www.nginx.com.cn/weihu.html
}
location = /weihu.html {
root /var/www/html; #网页返回/var/www/html/weihu.html的内容
}
location / {
root html;
index index.html index.htm;
}
}
七、日志审计
nginx服务器日志相关指令主要有两条:一条是log_format,用来设置日志格式;另外一条是access_log,用来指定日志文件的存放路径、格式和缓存大小。
代码语言:javascript复制参数 说明 示例
$remote_addr 客户端地址 211.28.65.253
$remote_user 客户端用户名称 --
$time_local 访问时间和时区 18/Jul/2012:17:00:01 0800
$request 请求的URI和HTTP协议 "GET /article-10000.html HTTP/1.1"
$http_host 请求地址,即浏览器中你输入的地址(IP或域名) www.wang.com 192.168.100.100
$status HTTP请求状态 200
$upstream_status upstream状态 200
$body_bytes_sent 发送给客户端文件内容大小 1547
$http_referer url跳转来源 https://www.baidu.com/
$http_user_agent 用户终端浏览器等信息 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SV1; GTB7.0; .NET4.0C;
$ssl_protocol SSL协议版本 TLSv1
$ssl_cipher 交换数据中的算法 RC4-SHA
$upstream_addr 后台upstream的地址,即真正提供服务的主机地址 10.10.10.100:80
$request_time 整个请求的总时间 0.205
$upstream_response_time 请求过程中,upstream响应时间 0.002
假设将Nginx服务器作为Web服务器,位于负载均衡设备、Nginx反向代理之后,不能获取到客户端的真实IP地址了。原因是经过反向代理后,由于在客户端和Web服务器之间增加了中间层,因此Web服务器无法直接拿到客户端的IP。反向代理服务器在转发请求的HTTP头信息中,可以增加X-Forwarded-For信息,用以记录原有的客户端IP地址和原来客户端请求的服务器地址。要用log_format指令设置日志格式,让日志记录X-Forearded-For信息中的IP地址,即客户的真实IP。
代码语言:text复制 proxy_set_header X-Forwarded-For $remote_addr;
代码语言:javascript复制og_format main '$remote_addr - [$time_local] - $request - $http_host - $status - $request_time - $body_bytes_sent - [$http_user_agent] - $http_referer - $upstream_addr - "$upstream_status"';
nginx.conf
代码语言:javascript复制user nginx;
worker_processes 5;
error_log logs/error.log;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - [$time_local] - $request - $http_host - $status - $request_time - $body_bytes_sent - [$http_user_agent] - $http_referer - $upstream_addr - "$upstream_status"';
sendfile on;
keepalive_timeout 65;
gzip on;
include /usr/local/nginx/vhosts_enable/web/*.conf;
}
index.conf
代码语言:javascript复制upstream back_web_servers {
server www.nginx.back.com.cn:9090;
server www.nginx.back.com.cn:9091;
}
server {
listen 8089;
server_name www.nginx.com.cn;
charset utf-8;
access_log logs/index/access.log main;
location / {
proxy_pass http://back_web_servers;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
}
八、访问控制
禁止访问目录
代码语言:javascript复制server {
listen 8089;
server_name www.nginx.com.cn;
charset utf-8;
access_log logs/index/access.log main;
set $doc_root /usr/local/nginx/www/static;
location ~* .(txt|doc)$ {
root $doc_root;
deny all;
}
}
只允许指定IP访问(日常中断维护)
代码语言:javascript复制server {
listen 8089;
server_name www.nginx.com.cn;
charset utf-8;
access_log logs/index/access.log main;
#设置是否合法的IP标记
set $rewrite true; #设置变量$rewrite,变量值为boole值true
#判断是否为合法IP
if ($remote_addr = "192.168.18.52"){ #当客户端IP为192.168.18.52时,将变量值设为false,不进行重写
set $rewrite false;
}
#除了合法IP,其它都是非法IP,进行重写跳转维护页面
if ($rewrite = true){ #当变量值为true时,进行重写
rewrite (. ) /weihu.html; #将域名后边的路径重写成/weihu.html,例如www.nginx.com.cn/weihu.html
}
location = /weihu.html {
root /var/www/html; #网页返回/var/www/html/weihu.html的内容
}
location / {
root html;
index index.html index.htm;
}
}
九、内置变量
代码语言:javascript复制$args :等于请求行中的参数,同$query_string
$content_length :请求头中的Content-length字段
$content_type :请求头中的Content-Type字段
$document_root :当前请求在root指令中指定的值
$http_user_agent :客户端agent信息
$http_cookie :客户端cookie信息
$limit_rate :限制连接速率
$request_method :客户端请求的动作,通常为GET或POST
$remote_addr :客户端的IP地址
$remote_port :客户端的端口
$remote_user :已经经过Auth Basic Module验证的用户名
$request_filename :当前请求的文件路径,由root或alias指令与URI请求生成
$scheme :HTTP方法(如http,https)
$server_protocol :请求使用的协议,通常是HTTP/1.0或HTTP/1.1
$server_addr :服务器地址
$server_name :服务器名称
$server_port :请求到达服务器的端口号
$host :请求主机头字段,否则为服务器名称
$request_uri :包含请求参数的原始URI,不包含主机名 /foo/bar.php?arg=1
$uri :不带请求参数的当前URI,$uri不包含主机名 /foo/bar.html
$document_uri :与$uri相同
十、证书配置
代码语言:javascript复制server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/www.nginx.com.cn.crt;
ssl_certificate_key /etc/nginx/ssl/www.nginx.com.cn.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4 RSA: HIGH: MEDIUM: LOW: SSLv2: EXP;
ssl_prefer_server_ciphers on;
server_name www.nginx.com.cn;
# 强跳转 https
if ($scheme = http) {
rewrite ^(.*)$ https://$host$1 permanent;
}
location / {
rewrite ^(.*)$ /test/$1 permanent;
}
location /test/ {
proxy_pass http://172.22.3.22:8889/test/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
error_page 403 = /403.html;
error_page 404 = /404.html;
error_page 500 502 503 504 = /50x.html;
}
location = /403.html{
root /usr/share/nginx/html;
}
location = /404.html{
root /usr/share/nginx/html;
}
location = /50x.html{
root /usr/share/nginx/html;
}
}