ip网站ip记录源码分享?网站记录ip有什么用

老铁们,大家好,相信还有很多朋友对于ip网站ip记录源码分享和网站记录ip有什么用的相关问题不太懂,没关系,今天就由我来为大家分享分享ip网站ip记录源码分享以及网站记录ip有什么用的问题,文章篇幅可能偏长,希望可以帮助到大家,下面一起来看看吧!

前面给大家讲了Nginx是如何处理HTTP请求头部的,接下来就到了真正处理HTTP请求的阶段了。先看下面这张图,这张图是Nginx处理HTTP请求的示意图,虽然简单,但是却很好的说明了整个过程。

ReadRequestHeaders:解析请求头。IdentifyConfigurationBlock:识别由哪一个location进行处理,匹配URL。ApplyRateLimits:判断是否限速。例如可能这个请求并发的连接数太多超过了限制,或者QPS太高。PerformAuthentication:连接控制,验证请求。例如可能根据Referrer头部做一些防盗链的设置,或者验证用户的权限。GenerateContent:生成返回给用户的响应。为了生成这个响应,做反向代理的时候可能会和上游服务(UpstreamServices)进行通信,然后这个过程中还可能会有些子请求或者重定向,那么还会走一下这个过程(Internalredirectsandsubrequests)。ResponseFilters:过滤返回给用户的响应。比如压缩响应,或者对图片进行处理。Log:记录日志。

以上这七个步骤从整体上介绍了一下处理流程,下面还会再说一下实际的处理过程。

Nginx处理HTTP请求的11个阶段

下面介绍一下详细的11个阶段,每个阶段都可能对应着一个甚至多个HTTP模块,通过这样一个模块对比,我们也能够很好的理解这些模块具体是怎么样发挥作用的。

POST_READ:在read完请求的头部之后,在没有对头部做任何处理之前,想要获取到一些原始的值,就应该在这个阶段进行处理。这里面会涉及到一个realip模块。SERVER_REWRITE:和下面的REWRITE阶段一样,都只有一个模块叫rewrite模块,一般没有第三方模块会处理这个阶段。FIND_CONFIG:做location的匹配,暂时没有模块会用到。REWRITE:对URL做一些处理。POST_WRITE:处于REWRITE之后,也是暂时没有模块会在这个阶段出现。

接下来是确认用户访问权限的三个模块:

PREACCESS:是在ACCESS之前要做一些工作,例如并发连接和QPS需要进行限制,涉及到两个模块:limt_conn和limit_reqACCESS:核心要解决的是用户能不能访问的问题,例如auth_basic是用户名和密码,access是用户访问IP,auth_request根据第三方服务返回是否可以去访问。POST_ACCESS:是在ACCESS之后会做一些事情,同样暂时没有模块会用到。

最后的三个阶段处理响应和日志:

PRECONTENT:在处理CONTENT之前会做一些事情,例如会把子请求发送给第三方的服务去处理,try_files模块也是在这个阶段中。CONTENT:这个阶段涉及到的模块就非常多了,例如index,autoindex,concat等都是在这个阶段生效的。LOG:记录日志access_log模块。

以上的这些阶段都是严格按照顺序进行处理的,当然,每个阶段中各个HTTP模块的处理顺序也很重要,如果某个模块不把请求向下传递,后面的模块是接收不到请求的。而且每个阶段中的模块也不一定所有都要执行一遍,下面就接着讲一下各个阶段模块之间的请求顺序。

11个阶段的顺序处理

如下图所示,每一个模块处理之间是有序的,那么这个顺序怎么才能得到呢?其实非常简单,在源码ngx_module.c中,有一个数组ngx_module_name,其中包含了在编译Nginx的时候的with指令所包含的所有模块,它们之间的顺序非常关键,在数组中顺序是相反的。

char*ngx_module_names[]={\n……\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n&34;,\n……\n}\n

灰色部分的模块是Nginx的框架部分去执行处理的,第三方模块没有机会在这里得到处理。

在依次向下执行的过程中,也可能不按照这样的顺序。例如,在access阶段中,有一个指令叫satisfy,它可以指示当有一个满足的时候就直接跳到下一个阶段进行处理,例如当access满足了,就直接跳到try_files模块进行处理,而不会再执行auth_basic、auth_request模块。

在content阶段中,当index模块执行了,就不会再执行auto_index模块,而是直接跳到log模块。

整个11个阶段所涉及到的模块和先后顺序如下图所示:

下面开始详细讲解一下各个阶段。先来看下第一个阶段postread阶段,顾名思义,postread阶段是在正式处理请求之前起作用的。

postread阶段

postread阶段,是11个阶段的第1个阶段,这个阶段刚刚获取到了请求的头部,还没有进行任何处理,我们可以拿到一些原始的信息。例如,拿到用户的真实IP地址

问题:如何拿到用户的真实IP地址?

我们知道,TCP连接是由一个四元组构成的,在四元组中,包含了源IP地址。而在真实的互联网中,存在非常多的正向代理和反向代理。例如最终的用户有自己的内网IP地址,运营商会分配一个公网IP,然后访问某个网站的时候,这个网站可能使用了CDN加速一些静态文件或图片,如果CDN没有命中,那么就会回源,回源的时候可能还要经过一个反向代理,例如阿里云的SLB,然后才会到达Nginx。

我们要拿到的地址应该是运营商给用户分配的公网IP地址115.204.33.1,对这个IP来进行并发连接的控制或者限速,而Nginx拿到的却是2.2.2.2,那么怎么才能拿到真实的用户IP呢?

HTTP协议中,有两个头部可以用来获取用户IP:

X-Forwardex-For是用来传递IP的,这个头部会把经过的节点IP都记录下来X-Real-IP:可以记录用户真实的IP地址,只能有一个

拿到真实用户IP后如何使用?

针对这个问题,Nginx是基于变量来使用。

例如binary_remote_addr、remote_addr这样的变量,其值就是真实的IP,这样做连接限制也就是limit_conn模块才有意义,这也说明了,limit_conn模块只能在preaccess阶段,而不能在postread阶段生效。

realip模块

默认不会编译进Nginx需要通过–with-http_realip_module启用功能变量:如果还想要使用原来的TCP连接中的地址和端口,需要通过这两个变量保存realip_remote_addrrealip_remote_port功能修改客户端地址指令set_real_ip_from指定可信的地址,只有从该地址建立的连接,获取的realip才是可信的real_ip_header指定从哪个头部取真实的IP地址,默认从X-Real-IP中取,如果设置从X-Forwarded-For中取,会先从最后一个IP开始取real_ip_recursive环回地址,默认关闭,打开的时候,如果X-Forwarded-For最后一个地址与客户端地址相同,会过滤掉该地址

Syntax:set_real_ip_fromaddress|CIDR|unix:;\nDefault:—\nContext:http,server,location\n\nSyntax:real_ip_headerfield|X-Real-IP|X-Forwarded-For|proxy_protocol;\nDefault:real_ip_headerX-Real-IP;\nContext:http,server,location\n\nSyntax:real_ip_recursiveon|off;\nDefault:real_ip_recursiveoff;\nContext:http,server,location\n

实战

上面关于real_ip_recursive指令可能不太容易理解,我们来实战练习一下,先来看real_ip_recursive默认关闭的情况:

重新编译一个带有realip模块的nginx

关于如何编译Nginx,详见:https://iziyang.github.io/2020/03/10/1-nginx/

屏蔽默认的nginx.conf文件的server块内容,并添加一行\ninclude/Users/mtdp/myproject/nginx/test_nginx/conf/example/*.conf;\n

real_ip_headerX-Real-IP;\nreal_ip_recursiveoff;\n34;Clientrealip:$remote_addr\\n&39;X-Forwarded-For:1.1.1.1,192.168.0.108&real_ip_headerX-Real-IP;\n34;Clientrealip:$remote_addr\\n&39;X-Forwarded-For:1.1.1.1,2.2.2.2,192.168.0.108&return405;\nlocation/{\n34;findnothing!&39;first!\\n&39;second!\\n&39;third!\\n&0:*25&34;matches&34;,client:127.0.0.1,server:rewrite.ziyang.com,request:&34;,host:&34;\n2020/05/0606:24:05[notice]8695934;/second/3.txt&34;&34;GET/first/3.txtHTTP/1.1&34;rewrite.ziyang.com&0:*25&34;matches&34;,client:127.0.0.1,server:rewrite.ziyang.com,request:&34;,host:&34;\n2020/05/0606:24:05[notice]8695934;/third/3.txt&34;&34;GET/first/3.txtHTTP/1.1&34;rewrite.ziyang.com&与变量http_user_agent匹配\nrewrite^(.*)$/msie/$1break;\n}\nif($http_cookie~*&34;){与变量request_method匹配,获取请求方法\nreturn405;\n}\nif($slow){roothtml/;\n\tdefault_typetext/plain;\n\tmerge_slashesoff;\n\n\tlocation~/Test1/${\n\treturn200&39;;\n}\n\tlocation~*/Test1/(\\w+)${\n\treturn200&39;;\n}\n\tlocation^~/Test1/{\n\treturn200&39;;\n}\nlocation/Test1/Test2{\nreturn200&39;;\n}\nlocation/Test1{\nreturn200&39;;\n}\n\tlocation=/Test1{\n\treturn200&39;;\n}\n}\n

问题就来了,访问下面几个URL会分别返回什么内容呢?

/Test1\n/Test1/\n/Test1/Test2\n/Test1/Test2/\n/test1/Test2\n

例如访问/Test1时,会有几个部分都匹配上:

常规前缀匹配:location/Test1精确匹配:location=/Test1

访问/Test1/时,也会有几个部分匹配上:

location~/Test1/$location^~/Test1/

那么究竟会匹配哪一个呢?Nginx其实是遵循一套规则的,如下图所示:

全部的前缀字符串是放置在一棵二叉树中的,Nginx会分为两部分进行匹配:

先遍历所有的前缀字符串,选取最长的一个前缀字符串,如果这个字符串是=的精确匹配或^~的前缀匹配,会直接使用如果第一步中没有匹配上=或^~,那么会先记住最长匹配的前缀字符串location按照nginx.conf文件中的配置依次匹配正则表达式如果所有的正则表达式都没有匹配上,那么会使用最长匹配的前缀字符串

下面看下实际的响应是怎么样的:

?test_nginxcurllocation.ziyang.com/Test1\nexactmatch!\n?test_nginxcurllocation.ziyang.com/Test1/\nstopregularexpressionsmatch!\n?test_nginxcurllocation.ziyang.com/Test1/Test2\nlongestregularexpressionsmatch!\n?test_nginxcurllocation.ziyang.com/Test1/Test2/\nlongestprefixstringmatch!\n?test_nginxcurllocation.ziyang.com/Test1/Test3\nstopregularexpressionsmatch!\n

/Test1匹配location=/Test1/Test1/匹配location^~/Test1//Test1/Test2匹配location~*/Test1/(\\w+)$/Test1/Test2/匹配location/Test1/Test2/Test1/Test3匹配location^~/Test1/

这里面重点解释一下/Test1/Test3的匹配过程:

遍历所有可以匹配上的前缀字符串,总共有两个^~/Test1//Test1选取最长的前缀字符串/Test1/,由于前面有^~禁止正则表达式匹配,因此直接使用location^~/Test1/的规则返回stopregularexpressionsmatch!

preaccess阶段

下面就来到了preaccess阶段。我们经常会遇到一个问题,就是如何限制每个客户端的并发连接数?如何限制访问频率?这些就是在preaccess阶段处理完成的,顾名思义,preaccess就是在连接之前。先来看下limit_conn模块。

limit_conn模块

这里面涉及到的模块是ngx_http_limit_conn_module,它的基本特性如下:

生效阶段:NGX_HTTP_PREACCESS_PHASE阶段模块:http_limit_conn_module默认编译进Nginx,通过–without-http_limit_conn_module禁用生效范围全部worker进程(基于共享内存)进入preaccess阶段前不生效限制的有效性取决于key的设计:依赖postread阶段的realip模块取到真实IP

这里面有一点需要注意,就是limit_connkey的设计,所谓的key指的就是对哪个变量进行限制,通常我们取的都是用户的真实IP。

说完了limit_conn的模块,再来说一下指令语法。

指令语法

定义共享内存(包括大小),以及key关键字

Syntax:limit_conn_zonekeyzone=name:size;\nDefault:—\nContext:http\n

限制并发连接数

Syntax:limit_connzonenumber;\nDefault:—\nContext:http,server,location\n

限制发生时的日志级别

Syntax:limit_conn_log_levelinfo|notice|warn|error;\nDefault:limit_conn_log_levelerror;\nContext:http,server,location\n

限制发生时向客户端返回的错误码

Syntax:limit_conn_statuscode;\nDefault:limit_conn_status503;\nContext:http,server,location\n

实战

下面又到了实战的环节了,通过一个实际的例子来看一下以上的几个指令是怎么起作用的。

老规矩,先上配置文件:

limit_conn_zone$binary_remote_addrzone=addr:10m;\nlimit_reqzone=oneburst=3nodelay;\nlimit_rate50;\nlimit_reqzone=oneburst=3nodelay;\n\tlimit_reqzone=one;\n}\n}\n

结论:在limit_reqzone=one指令下,超出每分钟处理的请求数后就会立刻返回503。

?test_nginxcurllimit.ziyang.com\n<html>\n<head><title>503ServiceTemporarilyUnavailable</title></head>\n<body>\n<center><h1>503ServiceTemporarilyUnavailable</h1></center>\n<hr><center>nginx/1.17.8</center>\n</body>\n</html>\n

改变一下注释的指令:

limit_reqzone=oneburst=3;\ncomment\nname1:password1\nname2:password2:comment\nname3:password3\n

实战

在example目录下生成密码文件auth.pass

htpasswd-bcauth.passziyang123456\n

添加配置文件

server{\n\tserver_nameaccess.ziyang.com;\nlisten80;\n\terror_loglogs/error.logdebug;\n\tdefault_typetext/plain;\n\tlocation/auth_basic{\n\tsatisfyany;\n\tauth_basic&34;;\n\tauth_basic_user_fileexample/auth.pass;\n\tdenyall;\n}\n}\n

重载Nginx配置文件在/etc/hosts文件中添加access.ziyang.com

这时候访问access.ziyang.com就会弹出对话框,提示输入密码:

auth_request模块

功能:向上游的服务转发请求,若上游服务返回的响应码是2xx,则继续执行,若上游服务返回的响应码是2xx,则继续执行,若上游服务返回的是401或者403,则将响应返回给客户端原理:收到请求后,生成子请求,通过反向代理技术把请求传递给上游服务默认未编译进Nginx,需要通过–with-http_auth_request_module编译进去

指令语法

Syntax:auth_requesturi|off;\nDefault:auth_requestoff;\nContext:http,server,location\n\nSyntax:auth_request_set$variablevalue;\nDefault:—\nContext:http,server,location\n

实战

在上一个配置文件中添加以下内容

server{\n\tserver_nameaccess.ziyang.com;\nlisten80;\n\terror_loglogs/error.logdebug;\n34;testauth_basic&34;&34;testauth_basic&39;lasturl!\\n&34;&39;$request_filename:$document_root:$realpath_root\\n&39;$request_filename:$document_root:$realpath_root\\n&0:*10723open()&34;failed(2:Nosuchfileordirectory)\n

如果不想记录日志,可以关掉。

重定向跳转的域名

现在有另外一个问题,当我们访问目录时最后没有带/,static模块会返回301重定向,那么这个规则是怎么定义的呢,看下面三个指令:

该指令决定重定向时的端口\nSyntax:port_in_redirecton|off;\nDefault:port_in_redirecton;\nContext:http,server,location\n开启或关闭Syntax:autoindexon|off;Default:autoindexoff;Context:http,server,location控制以哪种格式输出Syntax:autoindex_formathtml|xml|json|jsonp;Default:autoindex_formathtml;Context:http,server,locationindexb.html;\nautoindex_exact_sizeon;\nautoindex_formathtml;\nautoindex_localtimeon;\n}\n}\n

这里我把indexb.html这条指令给注释掉了,而index模块是默认编译进Nginx的,且默认指令是indexindex.html,因此,会去找是否有index.html这个文件。

打开浏览器,访问autoindex.ziyang.com:8080,html目录下默认是有index.html文件的,因此显示结果为:打开indexb.html指令注释。由于html文件夹下并不存在b.html这个文件,所以请求会走到autoindex模块,显示目录:

后面的文件大小显示格式就是由autoindex_exact_sizeon;这条指令决定的。

concat模块

下面介绍一个可以提升小文件性能的模块,这个模块是由阿里巴巴开发的,在淘宝网中有广泛应用。

模块:ngx_http_concat_module模块开发者:Tengine(https://github.com/alibaba/nginx-http-concat)\u0005–add-module=../nginx-http-concat/功能:合并多个小文件请求,可以明显提升HTTP请求的性能指令:39;:::&34;…&39;$remote_addr-$remote_user[$time_local]&39;&34;$status$body_bytes_sent&39;&34;\n&34;';\n

配置日志文件路径

Syntax:access_logpath[format[buffer=size][gzip[=level]][flush=time][if=condition]];\naccess_logoff;\nDefault:access_loglogs/access.logcombined;\nContext:http,server,location,ifinlocation,limit_except\n

path路径可以包含变量:不打开cache时每记录一条日志都需要打开、关闭日志文件if通过变量值控制请求日志是否记录日志缓存功能:批量将内存中的日志写入磁盘写入磁盘的条件:所有待写入磁盘的日志大小超出缓存大小;达到flush指定的过期时间;worker进程执行reopen命令,或者正在关闭。日志压缩功能:批量压缩内存中的日志,再写入磁盘buffer大小默认为64KB压缩级别默认为1(1最快压缩率最低,9最慢压缩率最高)打开日志压缩时,默认打开日志缓存功能

对日志文件名包含变量时的优化

Syntax:open_log_file_cachemax=N[inactive=time][min_uses=N][valid=time];\nopen_log_file_cacheoff;\nDefault:open_log_file_cacheoff;\nContext:http,server,location\n

max:缓存内的最大文件句柄数,超出后用LRU算法淘汰inactive:文件访问完后在这段时间内不会被关闭。默认10秒min_uses:在inactive时间内使用次数超过min_uses才会继续存在内存中。默认1valid:超出valid时间后,将对缓存的日志文件检查是否存在。默认60秒off:关闭缓存功能

日志模块没有实战。

到了这里,我们已经将Nginx处理HTTP请求的11个阶段全部梳理了一遍,每个阶段基本都有对应的模块。相信对于这样一个全流程的解析,大家都能够看懂Nginx的配置了,在此之上,还能够按照需求灵活配置出自己想要的配置,这样就真正的掌握了11个阶段。

关于ip网站ip记录源码分享,网站记录ip有什么用的介绍到此结束,希望对大家有所帮助。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平