Nginx常用模块
企业中网站的安全访问配置
a. 根据用户访问的地址进行控制 Nginx实现基于ip的访问控制功能:(Ngx_http_access_module)
官方文档:http://nginx.org/en/docs/http/ngx_http_access_module.html 官方示例: The ngx_http_access_module module allows limiting access to certain client addresses.限定资源只被指定的客户端访问。 Example Configuration: location / { deny 192.168.1.1; #自上而下检测,匹配范围小的在上面 allow 192.168.1.0/24; allow 10.1.1.0/16; allow 2001:0db8::/32; deny all; } Syntax: allow address | CIDR | unix: | all; Default: — Context: http, server, location, limit_except #适用配置段 Syntax: deny address | CIDR | unix: | all; Default: — Context: http, server, location, limit_except #适用配置段
10.0.0.0/24 www.mxxl.com/gota/ 不能访问
172.16.1.0/24 www.mxxl.com/gota/ 可以访问
第一个历程: 编写配置文件
[root@web01 conf.d]# vim www.conf
server { listen 80; server_name www.mxxl.com; location / { root /html/www; index index.html; } location /gota { deny 10.0.0.0/24; #禁止 allow 172.16.1.0/24; #允许 root /html/www; index index.html; } }
补充: location外面的信息, 全局配置信息 ;location里面的信息, 局部配置信息
b 根据用户访问进行认证 nginx认证模块: ngx_http_auth_basic_module
Example Configuration location / { auth_basic "closed site"; #开启认证功能 auth_basic_user_file conf/htpasswd; #加载用户密码文件 } Directives Syntax: auth_basic string | off; Default: auth_basic off; Context: http, server, location, limit_except Syntax: auth_basic_user_file file; Default: — Context: http, server, location, limit_except
第一个历程: 编写虚拟主机配置文件
server { listen 80; server_name www.oldboy.com; location / { root /html/www; index index.html; auth_basic "oldboy-sz-01"; auth_basic_user_file password/htpasswd; }
第二个历程: 创建密码文件(文件中密码信息必须是密文的)
htpasswd 创建一个有密文信息的密码文件
[root@web01 conf.d]# rpm -qf `which htpasswd`
httpd-tools-2.4.6-89.el7.centos.x86_64
[root@web01 nginx-1.16]# htpasswd -cb password/htpasswd gota 123456
Adding password for user gota
[root@web01 nginx-1.16]# cat password/htpasswd
gota:$apr1$De.drvif$VNuHFsViBt2HpYzWpyPiK.
[root@web01 nginx-1.16]#mv password conf/
-c Create a new file. ***** 创建一个密码文件 -n Don't update file; display results on stdout. 不会更新文件; 显示文件内容信息 -b Use the password from the command line rather than prompting for it. ***** 免交互方式输入用户密码信息 -i Read password from stdin without verification (for script usage). 读取密码采用标准输入方式,并不做检查 ??? -m Force MD5 encryption of the password (default). md5的加密算法 -B Force bcrypt encryption of the password (very secure). 使用bcrypt对密码进行加密 -C Set the computing time used for the bcrypt algorithm (higher is more secure but slower, default: 5, valid: 4 to 31). 使用bcrypt algorithm对密码进行加密 -d Force CRYPT encryption of the password (8 chars max, insecure). 密码加密方式 -s Force SHA encryption of the password (insecure). 加密方式 -p Do not encrypt the password (plaintext, insecure). 不进行加密 -D Delete the specified user. 删除指定用户 -v Verify password for the specified user.
修改密码文件权限: ??? #安全问题
chmod 600 ./htpasswd
500 Internal Server Error
01. 内部程序代码编写有问题
02. 程序服务中文件权限不正确
curl命令参数:
-u, --user USER[:PASSWORD] Server user and password
[root@web01 password]# curl www.mxxl.com -u gota
Enter host password for user 'gota':
10.0.0.7 www.mxxl.com
[root@web01 password]# curl www.mxxl.com -u mxxl:123456
10.0.0.7 www.mxxl.com
C. Nginx 隐藏版本号和信息
查看http请求的response里面的header我们会发现有server这个参数,它表示服务端使用的是什么web服务器。
例如 原文链接:https://blog.csdn.net/weixin_42104231/article/details/83653987
新浪网:Server:nginx
开源中国:Server:Tengine
segmentfault甚至都没有返回server!
Nginx默认是显示版本号的。这样就给人家看到你的服务器nginx的真实版本号,前些时间暴出了一些Nginx版本漏洞,就是说有些版本有漏洞,而有些版本没有。这样暴露出来的版本号就容易变成攻击者可利用的信息。所以,从安全的角度来说,隐藏版本号会相对安全些!
[root@proxy ~]# curl -i 192.168.4.5
HTTP/1.1 200 OK
Server: nginx/1.12.2
那nginx版本号可以隐藏不?其实可以的,看下面的步骤(nginx + php)
1 进入nginx配置文件的目录(此目录根据安装时决定)nginx.conf,用vim编辑打开。
[root@proxy ~]# vim /usr/local/nginx/conf/nginx.conf
http { include mime.types; default_type application/octet-stream; server_tokens off; #### 在http节点下加入server_tokens off;即可 }
2 编辑php-fpm配置文件fastcgi.conf 和 fastcgi_params.
在没有修改之前的字段内容:fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
[root@proxy ~]# vim /usr/local/nginx/conf/fastcgi.conf
fastcgi_param SERVER_SOFTWARE nginx;
[root@proxy ~]# vim /usr/local/nginx/conf/fastcgi_params
fastcgi_param SERVER_SOFTWARE nginx;
3 重新加载nginx配置:
[root@proxy ~]# nginx -s reload
4 再次测试能够发现版本号对外已经完全隐藏了
[root@proxy ~]# curl -i 192.168.4.5
HTTP/1.1 200 OK
Server: nginx
Nginx的企业实践应用
1) 利用nginx服务搭建网站文件共享服务器
第一个步骤: 编写配置文件(www.conf)
a. nginx模块功能: ngx_http_autoindex_module
Syntax: autoindex on | off;
Default:
autoindex off;
Context: http, server, location
server { listen 80; server_name localhost; location / { root html/gota; #index index.html index.htm; #注释掉这行 autoindex on; #开启nginx站点目录索引功能 } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
注意:
1. 需要将首页文件(例如html/gota/index.html)进行删除
2. mime.types 媒体资源类型文件作用(里面记录了nginx支持的文件类型)
文件中有的扩展名信息资源, 进行访问时会直接看到数据信息(直接打开,如果不想直接打开就将其注释或删掉)
文件中没有的扩展名信息资源, 进行访问时会直接下载资源
[root@web01 nginx-1.16]# vim conf/mime.types
types { text/html html htm shtml; text/css css; text/xml xml; image/gif gif; image/jpeg jpeg jpg; application/javascript js; application/atom+xml atom; application/rss+xml rss; text/mathml mml; # text/plain txt; text/vnd.sun.j2me.app-descriptor jad; text/vnd.wap.wml wml; text/x-component htc; image/png png; image/svg+xml svg svgz; image/tiff tif tiff; image/vnd.wap.wbmp wbmp; image/webp webp; image/x-icon ico; image/x-jng jng; image/x-ms-bmp bmp; font/woff woff; font/woff2 woff2; application/java-archive jar war ear; application/json json; application/mac-binhex40 hqx; application/msword doc; application/pdf pdf; application/postscript ps eps ai; application/rtf rtf; application/vnd.apple.mpegurl m3u8; application/vnd.google-earth.kml+xml kml; application/vnd.google-earth.kmz kmz; application/vnd.ms-excel xls; application/vnd.ms-fontobject eot; application/vnd.ms-powerpoint ppt; application/vnd.oasis.opendocument.graphics odg; application/vnd.oasis.opendocument.presentation odp; application/vnd.oasis.opendocument.spreadsheet ods; application/vnd.oasis.opendocument.text odt; application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; application/vnd.wap.wmlc wmlc; application/x-7z-compressed 7z; application/x-cocoa cco; application/x-java-archive-diff jardiff; application/x-java-jnlp-file jnlp; application/x-makeself run; application/x-perl pl pm; application/x-pilot prc pdb; application/x-rar-compressed rar; application/x-redhat-package-manager rpm; application/x-sea sea; application/x-shockwave-flash swf; application/x-stuffit sit; application/x-tcl tcl tk; application/x-x509-ca-cert der pem crt; application/x-xpinstall xpi; application/xhtml+xml xhtml; application/xspf+xml xspf; application/zip zip; application/octet-stream bin exe dll; application/octet-stream deb; application/octet-stream dmg; application/octet-stream iso img; application/octet-stream msi msp msm; audio/midi mid midi kar; audio/mpeg mp3; audio/ogg ogg; audio/x-m4a m4a; audio/x-realaudio ra; video/3gpp 3gpp 3gp; video/mp2t ts; video/mp4 mp4; video/mpeg mpeg mpg; video/quicktime mov; video/webm webm; video/x-flv flv; video/x-m4v m4v; video/x-mng mng; video/x-ms-asf asx asf; video/x-ms-wmv wmv; video/x-msvideo avi; }
[root@web01 nginx-1.16]# ./sbin/nginx -s stop
[root@web01 nginx-1.16]# ./sbin/nginx
网站页面目录数据,中文出现乱码,如何解决:
location / { root /html/www; #index index.html; auth_basic "oldboy-sz-01"; auth_basic_user_file password/htpasswd; autoindex on; charset utf-8; --- 修改目录结构中出现的中文乱码问题 }
2) 利用nginx服务搭配置文件别名功能
第一个历程: 编写配置文件
server_name www.oldboy.com old.com;
第二个历程: 配置好解析信息
作用:
01. 编写网站访问测试
02. 定位要访问的网站服务器
3) 利用nginx状态模块功能对网站进行监控 b. 状态模块: ngx_http_stub_status_module
location = /basic_status {
stub_status;
}#官方实例
第一个历程: 编写配置文件
[root@web01 nginx-1.16]# vim conf.d/server.conf
server { listen 80; server_name localhost; location / { root html/gota; #index index.html index.htm; autoindex on; #开启nginx站点目录索引功能 } location /nginx_status { stub_status on; #开启状态监测 access_log off; #关闭访问日志 allow 10.192.27.0/25; #允许指定网段 deny all; #拒接所有 } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
第二个历程: 重启nginx服务,并且编写解析文件
systemctl reload nginx
访问
Active connections: 激活的连接数信息 4000用户 3500 #当前正在连接的总数 (此参数关键 后期监控用)
accepts: 接收的连接数汇总(综合) TCP
handled: 处理的连接数汇总(综合) TCP
requests: 总计的请求数量 HTTP协议请求 #客户端的请求总数 (客户端在很短的时间多次请求,只建立一次连接) 不一定请求和处理成功 (请求数高于当服务器并发量,或出现等待)
Reading: nginx服务读取请求报文的数量 100人点餐
Writing: nginx服务响应报文信息数量 100人响应
Waiting: nginx队列机制等待处理的,要处理(读取或者响应保存进行保存) 监控 (此参数关键 后期监控用)
4) nginx日志功能配置
访问日志: /var/log/nginx/access.log c. 访问日志模块:ngx_http_log_module
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; #定义日志内容格式 access_log /var/log/nginx/access.log main; #调用日志格式
10.192.27.71 - gota [29/Oct/2019:10:45:23 +0800] "GET /gota.txt HTTP/1.1" 304 0 "http://10.192.27.111/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36"
10.192.33.24 - - [29/Oct/2019:13:55:32 +0800] "GET / HTTP/1.1" 200 374 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
$remote_addr 显示用户访问源IP地址信息 $remote_user 显示认证的用户名信息 [$time_local] 显示访问网站时间 "$request" 请求报文的请求行信息 $status 用户访问网站状态码信息 $body_bytes_sent 显示响应的数据尺寸信息(服务器给客户端口的文件大小 例如index.html的大小) $http_referer 记录调用网站资源的连接地址信息(防止用户盗链) # 京东nginx---access.log---某个广告(xxx---京东图片链接)---http_referer(链接) $http_user_agent 记录用户使用什么客户端软件进行访问页面的 (谷歌 火狐 IE 安卓 iphone) $http_x_forwarded_for ??? 负载均衡
错误日志: /var/log/nginx/error.log d. 错误日志模块 Core functionality #http://nginx.org/en/docs/ngx_core_module.html
Syntax: error_log file [level]; 指定错误日志路径以及错误日志记录的级别 Default: error_log logs/error.log error; Context: main, http, mail, stream, server, location
error_log /var/log/nginx/error.log warn;
debug :调试级别, 服务运行的状态信息和错误信息详细显示 信息越多 info :信息级别, 只显示重要的运行信息和错误信息 notice :通知级别: 更加重要的信息进行通知说明 warn :警告级别: 可能出现了一些错误信息,但不影响服务运行 error :错误级别: 服务运行已经出现了错误,需要进行纠正 推荐选择 crit :严重级别: 必须进行修改调整 alert :严重警告级别: 即警告,而且必须进行错误修改 emerg :灾难级别: 服务已经不能正常运行 信息越少
PS: 日志文件信息需要做切割处理 几个G
Location
5) nginx服务location作用说明 (使用到的模块 ngx_http_core_module)
参考地址:http://nginx.org/en/docs/http/ngx_http_core_module.html
1、示例一:location匹配小栗子 ( uri 统一资源标识符 )
location /oldboy { root html/www; error_page 404 /oldboy.jpg; } location /oldgirl { root html/www; error_page 404 /oldgirl.jpg; }
location详细配置(官方实例):
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... } location @name { ... } Default: — Context: server, location location = / { --- 精确匹配 优先级01 最高 [ configuration A ] } location / { --- 默认匹配 优先级04 最低 [ configuration B ] } location /documents/ { --- 按照目录进行匹配 优先级03 [ configuration C ] } location ^~ /images/ { --- 优先匹配/不识别uri信息中符号信息 优先级02 [ configuration D ] } location ~* \.(gif|jpg|jpeg)$ { --- 不区分大小写进行匹配 优先级03 [ configuration E ] }
上面级别顺序的佐证
server { listen 80; server_name www.mxxl.com; location / { return 505; } location = / { return 403; } location /documents/ { return 501; } location ^~ /images/ { return 502; } location ~* \.(gif|jpg|jpeg)$ { return 500; } # error_page 500 502 503 504 /50x.html; # location = /50x.html { # root html; # } }
访问:http://www.mxxl.com/
访问:http://www.mxxl.com/images/haha.jpg
访问:http://www.mxxl.com/xixi/haha.jpg
访问:http://www.mxxl.com/xixi/ 无任何匹配 走 /
2、location匹配规则 ( uri 统一资源标识符 )
1. 以 = 开头表示精确匹配,跟网址的uri一模一样 2. ^~ 开头表示uri以某个常规字符串开头,不是正则匹配 3.1 ~ 开头表示区分大小写的正则匹配; 3.2 ~* 开头表示不区分大小写的正则匹配 4. / 通用匹配, 如果没有其它匹配,任何请求都会匹配到 大致的匹配顺序: (location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)
3、示例二:location匹配小栗子 ( uri 统一资源标识符 )
location = / { # 精确匹配 / ,主机名后面不能带任何字符串 [ configuration A ] } location / { # 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求 # 但是正则和最长字符串会优先匹配 [ configuration B ] } location /documents/ { # 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索 # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条 [ configuration C ] } location ~ /documents/Abc { # 匹配任何以 /documents/Abc 开头的地址,匹配符合以后,还要继续往下搜索 # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条 [ configuration CC ] } location ^~ /images/ { # 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。 [ configuration D ] } location ~* \.(gif|jpg|jpeg)$ { # 匹配所有以 gif,jpg或jpeg 结尾的请求 # 然而,所有请求 /images/ 下的图片会被 config D 处理,因为 ^~ 到达不了这一条正则 [ configuration E ] } location /images/ { # 字符匹配到 /images/,继续往下,会发现 ^~ 存在 [ configuration F ] } location /images/abc { # 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在 # F与G的放置顺序是没有关系的 [ configuration G ] } location ~ /images/abc/ { # 只有去掉 config D 才有效:先最长匹配 config G 开头的地址,继续往下搜索,匹配到这一条正则,采用 [ configuration H ] } location ~* /js/.*/\.js 上面的匹配结果 按照上面的location写法,以下的匹配示例成立: / -> config A 精确完全匹配,即使/index.html也匹配不了 /downloads/download.html -> config B 匹配B以后,往下没有任何匹配,采用B /images/1.gif -> configuration D 匹配到F,往下匹配到D,停止往下 /images/abc/def -> config D 最长匹配到G,往下匹配D,停止往下 你可以看到 任何以/images/开头的都会匹配到D并停止,FG写在这里是没有任何意义的,H是永远轮不到的,这里只是为了说明匹配顺序 /documents/document.html -> config C 匹配到C,往下没有任何匹配,采用C /documents/1.jpg -> configuration E 匹配到C,往下正则匹配到E /documents/Abc.jpg -> config CC 最长匹配到C,往下正则顺序匹配到CC,不会往下到E
实际生产环境使用建议
所以实际使用中,个人觉得至少有三个匹配规则定义,如下: #直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。 #这里是直接转发给后端应用服务器了,也可以是一个静态首页 # 第一个必选规则 location = / { proxy_pass http://tomcat:8080/index } # 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项 # 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用 location ^~ /static/ { root /webroot/static/; } location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ { root /webroot/res/; } #第三个规则就是通用规则,用来转发动态请求到后端应用服务器 #非静态文件请求就默认是动态请求,自己根据实际把握 #毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了 location / { proxy_pass http://tomcat:8080/ }
6) 利用nginx实现页面跳转功能(使用到的模块 http_rewrite_module)
Syntax: rewrite regex replacement [flag]; Default: — Context: server, location, if
#语法格式:rewite 匹配的正则信息 替换成什么信息
跳转示例:
rewrite ^/(.*) http://www.mxxl.com/$1 permanent; 重写规则配置 ^/ 改写成 http://www.mxxl.com/ (.*)的任意内容继续使用放到$1 例如:mxxl.com/haha.html ---> http://www.mxxl.com/haha.html 跳转方式: 永久跳转: permanent 301 会将跳转信息进项缓存,不需要每次去服务端 临时跳转: redirect 302 不会缓存跳转信息,每次都要服务端进行跳转
出现无限跳转如何解决:
第一种方法: 利用不同server区块配置打破循环 server { listen 80; server_name mxxl.com; rewrite ^/(.*) http://www.mxxl.com/$1 permanent; } server { listen 80; server_name www.mxxl.com; location / { root html; index index.html index.htm; } } 测试curl -Lv mxxl.com
第二种方法: 利用if判断实现打破循环 server { listen 80; server_name www.mxxl.com; if ($host ~* "^mxxl.com$") { rewrite ^/(.*) http://www.mxxl.com/$1 permanent; } # $host变量是nginx自定义的 匹配以mxxl.com开头和结尾的,否则不跳转 location / { root html; index index.html index.htm; } }
https://www.jianshu.com/p/47269f4ca8b3
location ^~/integration/yzjShareOpen.do { if ($query_string ~* "accountId=1082741233173923840"){ rewrite ^/(.*) http://erp-dev.test.hihonor.com/$1?formId=wf_approvalpage_bac&mb_formId=wf_approvalpagemobile_bac&accountId=1273001854610965504 permanent; return 302; } }