如何在两层服务器的第二层Nginx上获取用户IP
一.之前在做nginx的服务器配置的时候遇到了一个问题,在之前服务器有用到一个限制客户端最大并发连接的功能,而且这个功能的实现是依靠在服务器中做
$remote-addr
这样的配置来达到的。但在增加了前端一层(负载、CDN、防火墙、安全服务)服务器之后,拿到的客户端IP就都变成了前端服务器的IP,而并非真是的用户IP地址。
二.这样的问题下,我又重新看了几次nginx官网的介绍,也发现其中另外一个特别重要的变量
$proxy_add_x_forwarded_for
这个变量是客户端访问请求中的X-forwarded-for 字段的值,如果请求中不包含这个字段,则自动用这个变量会等价于remote-addr这个变量。这允许我们获取HTTP请求中通常情况下前端服务器保存的客户真实IP地址的字段,通常就是我们说的X_FORWARDED_FOR字段,然后通过这样的方法,我们就可以实现各种各样的功能了。
三.下面我来实际给大家做一个简单演示。诸多不足,欢迎指正。
首先我们先搭建好Nginx的环境,这里我们使用1.7 系列的最新版本 1.7.9为例,(关于版本的问题参见FAQ 1)
下载、WGET所需地址 http://nginx.org/download/nginx-1.7.9.tar.gz
1. 下载Nginx
[lugt@localhostmysql]$ wget http://nginx.org/download/nginx-1.7.9.tar.gz
2. 解压
[lugt@localhostmysql]$ tar zxvf nginx-1.7.9.tar.gz
3. 直接编译(需要考虑是否需要openssl等插件的支持)
[lugt@localhost mysql]$cd nginx-1.7.9
[lugt@localhost nginx-1.7.9]$ ./configure
[lugt@localhost nginx-1.7.9]$ make
[lugt@localhost nginx-1.7.9]$ su
[lugt@localhostnginx-1.7.9]$ make install
4. 然后接下来修改nginx.conf配置文件
[lugt@localhost nginx-1.7.9]$ su
[lugt@localhost nginx-1.7.9]$cd /usr/local/nginx
[lugt@localhostnginx]$ vi conf/nginx.conf
然后在nginx.conf 中找到这里,加入来设置负载均衡,模仿CDN
upstream dnsnginx1 { server[*.*.*.*/yourhostname]:8080 weight=10000; #填IP、域名 } server { listen 80; server_name #access_log logs/host.access.log main location /{ proxy_pass http://dnsnginx1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header HTTP_X_FORWARDED_FOR $remote_addr; proxy_redirect default; } }
在设置一个虚拟服务器在8080端口,
limit_conn_zone $proxy_add_x_forwarded_for zone=addr:10m; # 并发设置 空间10M server { listen 8080; server_name [*.*.*.*/yourhostname]:8080 weight=10000; #填IP、域名 limit_conn addr 1; #限制客户端最大并发连接数为 1 location / { root html; index index.html index.htm; } }
保存。接着测试配置文件语法
[lugt@localhostnginx]$ ./sbin/nginx –t
启动服务器
[lugt@localhostnginx]$ ./sbin/nginx
四.使用ab 工具查看效果。
[lugt@localhost nginx]$ ab –c 10 –n 100 –v 4 http://127.0.0.1/ | grep HTTP/1.1
这行的意思:通过AB测试工具访问地址,并发连接数为30,总测试300次,显示HTTP返回头信息
通过ab 工具可以测出无论同时发送多少连接,最后成功返回200的只有之前限制nginx的最大并发连接数,所以可以证明对于IP的限制功能已经可以使用了。参考数据见FAQ2
FAQ 1 版本问题
如果当前正在使用的Nginx版本没有达到1.7.1版本,很可能nginx还不支持这个功能,
这时候就需要通过一段代码夹在limit_conn_handler函数中来从request中取得x_forwarded_for 的值。
以1.6.1版本为例,代码增加如下。 src/http/modules/ngx_http_limit_conn.c 第184行
hash =ngx_crc32_short(key.data, key.len); If(“” == &ctx->key){ <span style="white-space:pre"> </span>If(NULL!= r->main->headers_in->x_forwarded_for->elts){ key.data= *(char*)r->main->headers_in->x_forwarded_for->elts; key.len = 4; hash =ngx_crc32_short(key.data, key.len); <span style="white-space:pre"> </span>} }
FAQ 2 参考数据
这里是一份参考数据, 获取
[lugt@localhost~]$ ab -c 10 -n 100 -v 4 http://127.0.0.1/ | grep HTTP/1.1
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1 200 OK
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1 200 OK
English Version
How to retrievethe true ip of the client user if there are two layers of servers
Days before, wehave been faced such a difficulty which is we can’t use the variable $remote_addr for gathering the clients’ip address. This problem surfaces when we used a proxy server between the trueserver and client, which is actually a cdn. And that makes our functions oflimiting the maximum connections a client can make to a server at a time. Thissituation can also found if the load balance or any anti-spam service are inuse. So that’s why we can’t use remote_addr variable further.
After I did someresearch on the documentation and the code , I found out that this problem canbe solved by replacing the
$remote_addr
variable with the
$proxy_add_x_forwarded_forvariable. As this variable allows to retrievethe data from the column X_forwarded_for from the request, we can use thisvariable functioning in many ways.
And now I shall makean easy example to practically use this method.
First of all,build up a Nginx server.
Here, I will usethe 1.7.9 version (latest to the written time) for instance, therefore, thereexist some differences between older versions than 1.7.1 (see FAQ 1)
1. Download A Nginx Copy:
[lugt@localhostmysql]$ wget http://nginx.org/download/nginx-1.7.9.tar.gz
2. Decompress the file
[lugt@localhostmysql]$ tar zxvf nginx-1.7.9.tar.gz
3. Compile The Code
[lugt@localhostmysql]$ cd nginx-1.7.9
[lugt@localhostnginx-1.7.9]$ ./configure
[lugt@localhostnginx-1.7.9]$ make
[lugt@localhostnginx-1.7.9]$ su
[lugt@localhostnginx-1.7.9]$ make install
4. And edit the config file nginx.conf
[lugt@localhost nginx-1.7.9]$ su
[lugt@localhostnginx-1.7.9]$ cd /usr/local/nginx
[lugt@localhostnginx]$ vi conf/nginx.conf
There add suchdirectives to the server1 for emulate for an CDN server
upstream dnsnginx1 { server[*.*.*.*/yourhostname]:8080 weight=1000; #fill in your ip/hostname } server { listen 80; server_name [hostname] #fill your ip/ hostname here #access_log logs/host.access.log main location /{ proxy_pass http://dnsnginx1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header HTTP_X_FORWARDED_FOR $remote_addr; proxy_redirect default; } }
After the end ofone server directive, and in the http directive, add so to function the sever2
limit_conn_zone $proxy_add_x_forwarded_for zone=addr:10m; # sample setting server { listen 8080; server_name [*.*.*.*/hostname]:8080 weight=10000; #fill in ip/hostname here limit_conn addr 1; # Enablethe limitation of connection per ip at a time to 1. location / { root html; index index.html index.htm; } }
And then you cansave , test the config file and run nginx
Test your configfile:
[lugt@localhostnginx]$ ./sbin/nginx –t
Start the nginx server
[lugt@localhostnginx]$ ./sbin/nginx
Now, the serverhas been set and you can run a test at instance.
/* This CommandMeans to run a tool to connect to server as 10conn/once and 10 conns in total*/
[lugt@localhost~]$ ab -c 10 -n 100 -v 4 http://127.0.0.1/ | grep HTTP/1.1
FAQ 1
There is actuallysome little malfunctions when using elder versions than 1.7.1 (Probably the newversion has it for a new feature).So to use this directive in earlier versions,some code need to be added.
As a Example inthe version 1.6.1
In filesrc/http/modules/ngx_http_limit_conn.c Line around 184
hash =ngx_crc32_short(key.data, key.len); If("" == &ctx->key){ If(NULL!= r->main->headers_in->x_forwarded_for->elts){ key.data= *(char*)r->main->headers_in->x_forwarded_for->elts; key.len = 4; hash =ngx_crc32_short(key.data, key.len); }
}<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
FAQ 2 TestingResults
[lugt@localhost~]$ ab -c 10 -n 100 -v 4 http://127.0.0.1/ | grep HTTP/1.1
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1 200 OK
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1503 Service Temporarily Unavailable
HTTP/1.1 200 OK
以上就介绍了如何在两层服务器的第二层Nginx上获取用户IP,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

PHP在现代编程中仍然是一个强大且广泛使用的工具,尤其在web开发领域。1)PHP易用且与数据库集成无缝,是许多开发者的首选。2)它支持动态内容生成和面向对象编程,适合快速创建和维护网站。3)PHP的性能可以通过缓存和优化数据库查询来提升,其广泛的社区和丰富生态系统使其在当今技术栈中仍具重要地位。

在PHP中,弱引用是通过WeakReference类实现的,不会阻止垃圾回收器回收对象。弱引用适用于缓存系统和事件监听器等场景,需注意其不能保证对象存活,且垃圾回收可能延迟。

\_\_invoke方法允许对象像函数一样被调用。1.定义\_\_invoke方法使对象可被调用。2.使用$obj(...)语法时,PHP会执行\_\_invoke方法。3.适用于日志记录和计算器等场景,提高代码灵活性和可读性。

Fibers在PHP8.1中引入,提升了并发处理能力。1)Fibers是一种轻量级的并发模型,类似于协程。2)它们允许开发者手动控制任务的执行流,适合处理I/O密集型任务。3)使用Fibers可以编写更高效、响应性更强的代码。

PHP社区提供了丰富的资源和支持,帮助开发者成长。1)资源包括官方文档、教程、博客和开源项目如Laravel和Symfony。2)支持可以通过StackOverflow、Reddit和Slack频道获得。3)开发动态可以通过关注RFC了解。4)融入社区可以通过积极参与、贡献代码和学习分享来实现。

PHP和Python各有优势,选择应基于项目需求。1.PHP适合web开发,语法简单,执行效率高。2.Python适用于数据科学和机器学习,语法简洁,库丰富。

PHP不是在消亡,而是在不断适应和进化。1)PHP从1994年起经历多次版本迭代,适应新技术趋势。2)目前广泛应用于电子商务、内容管理系统等领域。3)PHP8引入JIT编译器等功能,提升性能和现代化。4)使用OPcache和遵循PSR-12标准可优化性能和代码质量。

PHP的未来将通过适应新技术趋势和引入创新特性来实现:1)适应云计算、容器化和微服务架构,支持Docker和Kubernetes;2)引入JIT编译器和枚举类型,提升性能和数据处理效率;3)持续优化性能和推广最佳实践。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

Atom编辑器mac版下载
最流行的的开源编辑器

Dreamweaver CS6
视觉化网页开发工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。