NGINX web服务器配置
https://zhuanlan.zhihu.com/p/112314267
检查nginx 的日志目录
nginx服务器日志相关指令主要有两条:一条是log_format,用来设置日志格式;另外一条是access_log,用来指定日志文件的存放路径、格式和缓存大小,可以参加ngx_http_log_module。一般在nginx的配置文件中日记配置(/usr/local/nginx/conf/nginx.conf)。
nginx的log_format有很多可选的参数用于指示服务器的活动状态,默认的是:
1
2
3
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
参数 说明 示例
$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
|
每个子域名单独配置一个 日志文件
1
2
3
4
5
6
7
8
9
10
11
|
server {
listen 80;
server_name yuying-api.xutongbao.top;
#配置根目录
location / {
proxy_pass http://127.0.0.1:85;
}
access_log logs/access_yuyingapi.log;
error_log logs/access_yuyingapi.log;
}
|
basic认证开启
秒懂HTTP基本认证(Basic Authentication)
在网络活动中,身份认证是非常重要的一环。Basic身份认证,是HTTP 1.0中引入的认证方案之一。虽然方案比较古老,同时存在安全缺陷,但由于实现简单,至今仍有不少网站在使用它。
Basic认证的安全缺陷比较明显,它通过明文传输用户的密码,这会导致严重的安全问题。
在传输层未加密的情况下,用户明文密码可被中间人截获。
明文密码一旦泄露,如果用户其他站点也用了同样的明文密码(大概率),那么用户其他站点的安全防线也告破。
关于上述问题的建议:
传输层未加密的情况下,不要使用Basic认证。
如果使用Basic认证,登录密码由服务端生成。
如果可能,不要使用Basic认证。
除了安全缺陷,Basic认证还存在无法吊销认证的情况。
1
2
3
4
5
|
cd /usr/local/nginx/conf/passwd
#生成密码
htpasswd -c ./ip_passwdfile username
#执行上命令后会要求输入两次密码,./passwdfile 是在当前目录下创建密码文件passwdfile ,username即为需要设置的账号
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
server
{
listen 80 default_server reuseport;
server_name _;
index index.html index.htm index.php;
root /home/wwwroot/default;
auth_basic "请输入账号密码"; #这里是验证时的提示信息
auth_basic_user_file /usr/local/nginx/conf/passwd/ip_passwdfile;
include enable-php.conf;
location /nginx_status
{
stub_status on;
access_log off;
}
location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*.(js|css)?$
{
expires 12h;
}
location ~ /.well-known {
allow all;
}
location ~ /.
{
deny all;
}
access_log /home/wwwlogs/access.log;
}
|
再访问站点,提示需要输入用户名和密码才可以访问,此方法适合不宜公开的站点,或不想对其专门做账号登录系统的时候。这样可避免被弱口令扫描,无疑再上了一把锁。
SSL 证书配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
#监听443端口
listen 443;
#你的域名
server_name huiblog.top;
ssl on;
#ssl证书的pem文件路径
ssl_certificate /root/card/huiblog.top.pem;
#ssl证书的key文件路径
ssl_certificate_key /root/card/huiblog.top.key;
location / {
proxy_pass http://公网地址:项目端口号;
}
}
server {
listen 80;
server_name huiblog.top;
#将请求转成https
rewrite ^(.*)$ https://$host$1 permanent;
}
}
|
Return 和 rewrite跳转
return 比 rewrite 更高效,因为它在 Nginx 的内部进行处理,不会引起额外的请求-响应往返。 rewrite 会引发额外的请求-响应往返,因此相对于 return 来说,性能稍差一些。 如果只是简单的重定向需求,推荐使用 return,而如果需要更复杂的 URI 重写逻辑,则可以使用 rewrite。
Nginx的重写指令用于改变客户端的URL请求。主要有return和rewrite。两个指令都有重写URL的能力,但rewrite支持更复杂的功能。
1. server 重定向
1
2
3
4
5
|
server {
listen 80;
server_name www.olddomain.com;
return 301 $scheme://www.newdomain.com$request_uri;
}
|
location重定向
1
2
3
4
|
location = /tutorial/learning-nginx {
return 301 $scheme://example.com/nginx/understanding-nginx
}
|
rewrite 重定向
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
location = /nginx-tutorial
{
rewrite ^/nginx-tutorial?$ /somePage.html last;
}
location = /
{
if ($http_user_agent ~* (mobile|nokia|iphone|ipad|android|samsung|htc|blackberry)) {
rewrite ^(.*) https://m.example.com$1 redirect;
}
}
|
gzip 压缩配置
Nginx 开启 gzip,不仅能提高网站打开速度,还能节约网站流量。
参考博客
gzip配置的常用参数
gzip on|off; #是否开启gzip
gzip_buffers 32 4K| 16 8K #缓冲(压缩在内存中缓冲几块? 每块多大?)
gzip_comp_level [1-9] #推荐6 压缩级别(级别越高,压的越小,越浪费CPU计算资源)
gzip_disable #正则匹配UA 什么样的Uri不进行gzip
gzip_min_length 200 # 开始压缩的最小长度(再小就不要压缩了,意义不在)
gzip_http_version 1.0|1.1 # 开始压缩的http协议版本(可以不设置,目前几乎全是1.1协议)
gzip_proxied # 设置请求者代理服务器,该如何缓存内容
gzip_types text/plain application/xml # 对哪些类型的文件用压缩 如txt,xml,html ,css
gzip_vary on|off # 是否传输gzip压缩标志
1
2
3
4
5
6
7
|
gzip on;
gzip_buffers 32 4K;
gzip_comp_level 6;
gzip_min_length 100;
gzip_types application/javascript text/css text/xml;
gzip_disable "MSIE [1-6]\."; #配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
gzip_vary on;
|
Content-Encoding:gzip 说明开启了gzip压缩
Transfet-Encoding:chunked 说明压缩后分块传输
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
# $gzip_ratio计算请求的压缩率,$body_bytes_sent请求体大小
log_format main '$remote_addr - $remote_user [$time_local] "$host" - "$request" '
'$gzip_ratio - $body_bytes_sent - $request_time';
access_log logs/access.log main;
# 开启gzip
gzip off;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 1;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 禁用IE 1-6 gzip
gzip_disable "MSIE [1-6]\.";
# 设置压缩所需要的缓冲区大小
gzip_buffers 32 4k;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.0;
|
Nginx 开启目录访问
autoindex on; //开启目录浏览功能;
1
2
3
4
5
6
7
8
9
10
11
|
location / {
root /data/www/file //指定实际目录绝对路径;
autoindex on; //开启目录浏览功能;
autoindex_exact_size off; //关闭详细文件大小统计,让文件大小显示MB,GB单位,默认为b;
autoindex_localtime on; //开启以服务器本地时区显示文件修改日期!
}
|
Nginx访问控制
访问控制的2种方式, 一种是 OSI模型的四层传输层,一种是在七层应用层, 主机防火墙就是四层控制(ip,传输层), Nginx是七层控制(应用层的软件)
例如 firewallcmd
1
|
systemctl start firewalld.service
|
Nginx匹配符号的优先级
符号优先级 = ~ ~* 无符号
有= 的优先级最大,然后依次排布,例如
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
touch jpg
location ~ /jpg {
return 501
}
location = /jpg {
return 502
}
location ~* /jpg {
return 503
}
location /jpg {
return 505
}
|
$args #请求中的参数值
$query_string #同 $args
$arg_NAME #GET请求中NAME的值
$is_args #如果请求中有参数,值为"?",否则为空字符串
$uri #请求中的当前URI(不带请求参数,参数位于$args),可以不同于浏览器传递的$request_uri的值,它可以通过内部重定向,或者使用index指令进行修改,$uri不包含主机名,如"/foo/bar.html"。
$document_uri #同 $uri
$document_root #当前请求的文档根目录或别名
$host #优先级:HTTP请求行的主机名>“HOST"请求头字段>符合请求的服务器名.请求中的主机头字段,如果请求中的主机头不可用,则为服务器处理请求的服务器名称
$hostname #主机名
$https #如果开启了SSL安全模式,值为"on”,否则为空字符串。
$binary_remote_addr #客户端地址的二进制形式,固定长度为4个字节
$body_bytes_sent #传输给客户端的字节数,响应头不计算在内;这个变量和Apache的mod_log_config模块中的"%B"参数保持兼容
$bytes_sent #传输给客户端的字节数
$connection #TCP连接的序列号
$connection_requests #TCP连接当前的请求数量
$content_length #“Content-Length” 请求头字段
$content_type #“Content-Type” 请求头字段
$cookie_name #cookie名称
$limit_rate #用于设置响应的速度限制
$msec #当前的Unix时间戳
$nginx_version #nginx版本
$pid #工作进程的PID
$pipe #如果请求来自管道通信,值为"p",否则为"."
$proxy_protocol_addr #获取代理访问服务器的客户端地址,如果是直接访问,该值为空字符串
$realpath_root #当前请求的文档根目录或别名的真实路径,会将所有符号连接转换为真实路径
$remote_addr #客户端地址
$remote_port #客户端端口
$remote_user #用于HTTP基础认证服务的用户名
$request #代表客户端的请求地址
$request_body #客户端的请求主体:此变量可在location中使用,将请求主体通过proxy_pass,fastcgi_pass,uwsgi_pass和scgi_pass传递给下一级的代理服务器
$request_body_file #将客户端请求主体保存在临时文件中。文件处理结束后,此文件需删除。如果需要之一开启此功能,需要设置client_body_in_file_only。如果将次文件传 递给后端的代理服务器,需要禁用request body,即设置proxy_pass_request_body off,fastcgi_pass_request_body off,uwsgi_pass_request_body off,or scgi_pass_request_body off
$request_completion #如果请求成功,值为"OK",如果请求未完成或者请求不是一个范围请求的最后一部分,则为空
$request_filename #当前连接请求的文件路径,由root或alias指令与URI请求生成
$request_length #请求的长度 (包括请求的地址,http请求头和请求主体)
$request_method #HTTP请求方法,通常为"GET"或"POST"
$request_time #处理客户端请求使用的时间,单位为秒,精度毫秒; 从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。
$request_uri #这个变量等于包含一些客户端请求参数的原始URI,它无法修改,请查看$uri更改或重写URI,不包含主机名,例如:"/cnphp/test.php?arg=freemouse"
$scheme #请求使用的Web协议,“http” 或 “https”
$server_addr #服务器端地址,需要注意的是:为了避免访问linux系统内核,应将ip地址提前设置在配置文件中
$server_name #服务器名
$server_port #服务器端口
$server_protocol #服务器的HTTP版本,通常为 “HTTP/1.0” 或 “HTTP/1.1”
$status #HTTP响应代码
$time_iso8601 #服务器时间的ISO 8610格式
$time_local #服务器时间(LOG Format 格式)
$cookie_NAME #客户端请求Header头中的cookie变量,前缀"$cookie_“加上cookie名称的变量,该变量的值即为cookie名称的值
$http_NAME #匹配任意请求头字段;变量名中的后半部分NAME可以替换成任意请求头字段,如在配置文件中需要获取http请求头:“Accept-Language”,$http_accept_language即可
$http_cookie
$http_host #请求地址,即浏览器中你输入的地址(IP或域名)
$http_referer #url跳转来源,用来记录从那个页面链接访问过来的
$http_user_agent #用户终端浏览器等信息
$http_x_forwarded_for
$sent_http_NAME #可以设置任意http响应头字段;变量名中的后半部分NAME可以替换成任意响应头字段,如需要设置响应头Content-length,$sent_http_content_length即可
$sent_http_cache_control
$sent_http_connection
$sent_http_content_type
$sent_http_keep_alive
$sent_http_last_modified
$sent_http_location
$sent_http_transfer_encoding
referer 防盗链
https://zhuanlan.zhihu.com/p/463197529
Nginx 用于实现防盗链功能的模块为 refer 模块,其依据的原理是: 如果网站盗用了你的图片,那么用户在点击或者查看这个盗链内容时,发送 http 请求的头部中的 referer 字段将为该盗版网站的 url。这样我们通过获取这个头部信息,知道 http 发起请求的页面,然后判断这个地址是否是我们的合法页面,不是则判断为盗链。Nginx 的 referer 模块中有3个指令,用法分别如下:
ngx_http_referer_module模块用于阻止"Refer"头字段中具有无效值的来源非法的域名请求。使用适当的"Referer"字段值创建请求非常容易,这些伪造的"Referer"字段可能会包括一些不合法的字段。本模块的目的不是彻底阻止此类请求,而是阻止常规浏览器发送的大量非允许"Refer"请求。还需应考虑到,即使对于有效的请求,常规浏览器也不应发送"Referer"字段。
none:请求头缺少Referer字段,即空Referer
blocked:请求头Referer字段不为空(即存在Referer),但是值被代理或者防火墙删除了,这些值不以“http://”或“https://”开头,通俗点说就是允许“http://”或"https//“以外的请求。
server_names:Referer请求头白名单。
arbitrary string:任意字符串,定义服务器名称或可选的URI前缀,主机名可以使用*号开头或结尾,Referer字段中的服务器端口将被忽略掉。
regular expression:正则表达式,以“~”开头,在“http://”或"https://“之后的文本匹配。
下面是示例:
配置合法的Referer为*.test.com*.dingtalkcloud.com 和 无Referer(none)(浏览器直接访问,就没有Referer) ; 其他非法Referer请求过来时, $invalid_referer 值为1 , 就return 403
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
server {
listen 80;
server_name app123456.eapps.dingtalkcloud.com;
client_max_body_size 100m;
proxy_buffering off;
proxy_read_timeout 3600;
access_log /var/log/nginx/app123456.eapps.dingtalkcloud.com-access.log main;
error_log /var/log/nginx/app123456.eapps.dingtalkcloud.com.com-error.log;
if ($host != 'app123456.eapps.dingtalkcloud.com') {
return 403 ;
}
valid_referers server_names none *.test.com *.dingtalkcloud.com;
if ($invalid_referer) {
return 403;
}
add_header 'X-Permitted-Cross-Domain-Policies' 'master-only';
add_header 'X-Content-Type-Options' 'nosniff';
add_header 'X-XSS-Protection' '1; mode=block';
add_header 'X-Frame-Options' 'SAMEORIGIN';
add_header 'X-Download-Options' 'noopen';
location / {
proxy_pass https://123456-dingtalk-h5-dev.test.com;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /cb/ {
proxy_pass https://cb.test.com/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
|
nginx 中英文自动匹配
参考博客
判断 Accept-Language 来实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#根据http请求头中的accept-language转发到不同的页面
if ($http_accept_language ~* ^zh){
set $lang "/index_cn.jsp";
}
if ($http_accept_language !~* ^zh){
set $lang "/index_en.jsp";
}
location =/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://localhost:8080$lang;
}
|
应对网站扫描/ 攻击/采集的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
#禁垃圾蜘蛛
if ($http_user_agent ~* "CheckMarkNetwork|Synapse|Bingbot|Googlebot|Nimbostratus-Bot|Dark|scraper|LMAO|Hakai|Gemini|Wappalyzer|masscan|crawler4j|Mappy|Center|eright|aiohttp|MauiBot|Crawler|researchscan|Dispatch|AlphaBot|Census|ips-agent|NetcraftSurveyAgent|ToutiaoSpider|EasyHttp|Iframely|sysscan|fasthttp|muhstik|DeuSu|mstshash|HTTP_Request|ExtLinksBot|package|SafeDNSBot|CPython|SiteExplorer|SSH|MegaIndex|BUbiNG|CCBot|NetTrack|Digincore|aiHitBot|SurdotlyBot|null|SemrushBot|Test|Copied|ltx71|Nmap|DotBot|AdsBot|InetURL|Pcore-HTTP|PocketParser|Wotbox|newspaper|DnyzBot|redback|PiplBot|SMTBot|WinHTTP|Auto Spider 1.0|GrabNet|TurnitinBot|Go-Ahead-Got-It|Download Demon|Go!Zilla|GetWeb!|GetRight|libwww-perl|Cliqzbot|MailChimp|SMTBot|Dataprovider|XoviBot|linkdexbot|SeznamBot|Qwantify|spbot|evc-batch|zgrab|Go-http-client|FeedDemon|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|CoolpadWebkit|Java|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|HttpClient|MJ12bot|EasouSpider|LinkpadBot|Ezooms|YoudaoBot|YandexBot|Rogerbot|exabot|ia_archiver|Teoma|gigabot|DOCOMO Sprider|AhrefsBot|SemrushBot|Sosospider|Yahoo! Slurp China|Yahoo! Slurp|MSNBot|MSNot-media|FlightDeckReports Bot|Bytespider|Mail.RU_Bot") {
return 403;
break;
}
#禁攻击采集
if ($http_user_agent ~* "FeedDemon|BOT/0.1 (BOT for JCE)|CrawlDaddy|Java|Jullo|Feedly|UniversalFeedParser|ApacheBench") {
return 403;
break;
}
#过滤url参数
set $URL $request_uri;
if ($URL ~* "member|plus|base|data|dede|public|plug|Vote|tool|feed|components|skin|tinyMCE|version|sysimage|wp-content|wp-admin|static|common|face|shell|swfupload|utility|convert|sitemap|siteserver|BackupDB|file|user|system|upimg|install|wap|multiupload|ewebeditor|office|wallet|backup|bitcoin|maccms|vendor|apply|bjebhgm|photo|module|external|Analytics|tools|subdomains|notes|md5|ckeditor|bbs|ajax|zhuitanyun|logbaak|help|weki|dxyylc|Somnus|manage|J4H7eFjWoBa3bO6U|SiteFiles|dowds|source|ucenter|phpcms|language|TeatchClass|taglib|sql|allowurl|shitan|root|wp-login|houtai|admin001|htadmin|clock2|webadmin"){
return 403;
break;
}
#禁特殊后缀
location ~* \.(asp|xml|jsp|aspx|dev|aspx|ewebeditor|sql|xsl|asmx|htaccess|ini|env|git|project|cgi|md5|ajax.js|swf|tpl.php)$ {
return 403;
break;
}
#禁止非GET方式的抓取
if ($request_method !~ ^(GET)$) {
return 403;
}
#禁止特殊请求方式
if ($request_method ~* "HEAD|DELETE|OPTIONS|POST" ) {
return 403;
break;
}
#禁特殊请求工具
if ($http_user_agent ~* "Wget|Curl" ) {
return 403;
break;
}
#禁部分爬取工具
if ($http_user_agent ~* "crawl|curb|git|Wtrace|Scrapy|python|http://www.snsbianpofanghu.com/" ) {
return 403;
break;
}
#禁压缩包
location ~* \.(tgz|bak|zip|rar|tar|gz|bz2|xz|tar.gz)$ {
return 403;
break;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#UA 不全,十有八九不是正常访问,禁
if ($http_user_agent = "Mozilla") {
return 403;
break;
}
#UA 不全,十有八九不是正常访问,禁
if ($http_user_agent = "Mozilla/5\.0") {
return 403;
break;
}
#UA 不全,十有八九不是正常访问,禁
if ($http_user_agent = "Mozilla/4\.0") {
return 403;
break;
}
#禁空 UA
if (http_user_agent ~* ^http_user_agent ~* ^http_user_agent ~* ^) {
return 403;
break;
}
|
屏蔽ip
1
2
3
4
5
6
7
8
9
|
#屏蔽ip
deny 113.92.157.0/24;
deny 223.199.0.0/16;
deny 192.74.225.105;
#限制所有ip访问频次
limit_req_zone $binary_remote_addr zone=allips:100m rate=30r/m;
limit_req zone=allips burst=5 nodelay;
|
1
2
3
4
5
6
7
8
9
10
|
#限制指定蜘蛛访问频次
limit_req_zone $anti_spider zone=one:100m rate=30r/m;
limit_req zone=one burst=5 nodelay;
server
{
if ($http_user_agent ~* "Sogou web spider|YisouSpider") {
set $anti_spider $http_user_agent;
}
|