Chinaunix首页 | 论坛 | 博客
  • 博客访问: 140665
  • 博文数量: 12
  • 博客积分: 45
  • 博客等级: 民兵
  • 技术积分: 194
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-03 13:16
文章分类

全部博文(12)

文章存档

2015年(3)

2014年(8)

2013年(1)

分类: 系统运维

2015-01-25 18:08:10

背景

部门因之前做web聊天应用,7层接入大量使用了haproxy。后来做第三方接入,针对https的应用场景,开始引入nginx。使用过程中发现nginx的插件非常丰富、特别是支持lua、而且方便进行模块开发定制。慢慢的开始替换haproxy,成为主要的7层接入组件。运营过程中也遇到不少问题,这里简单case by case做个总结记录:

总结

1. proxy_set_header

这个是后台鉴权server需要调用方提供一个QC_REAL_IP的http头做校验,我在nginx里配置如下:

  1. proxy_set_header QC_REAL_IP $http_host;
  2. location ^~/authorize/ {
  3.     proxy_set_header Host $http_host;
  4.     proxy_pass http://authorize_server;
  5.     proxy_redirect off;
  6. }
但是,却发现鉴权不成功,一直是返回503。掏出tcpdump抓包:

  1. tcpdump -i eth1 -nn -Als0p 'tcp and host author_server_ip and port author_server_port'
分析nginx发出的包头里没有QC_REAL_IP字段,遂翻阅nginx wiki,找到这行
proxy_set_header directives issued at higher levels are only inherited when no proxy_set_header directives have been issued at a given level.
原来proxy_set_header不完全是继承关系!把QC_REAL_IP的配置copy一份到location里,终于生效了。

2. nginx https proxy

平时拿nginx做proxy我有个习惯,一般会把upstream、proxy_pass名字一致,但稍微区分于server_name.例如:

  1. upstream xxoo_com {
  2.     server 10.8.8.8:8080;
  3. }
  4.                                            
  5. server {
  6.     listen 443;
  7.     server_name xxoo.com
  8.     ... ...
  9.     location / {
  10.         proxy_pass http://xxoo_com;
  11.         proxy_redirect off;
  12.     }
  13. }
重启nginx后,访问测试第一个https访问是正常的,由后端server返回的302跳转全部变成了http请求。自己找资料,不断调试,tcpdump抓包分析,继续调。最后意外发现,把upstream, proxy_pass名改成和server_name一致就可以了。
抓包发现nginx的proxy模块请求backend的http header中Host字段指就是proxy_pass 指令的值。nginx根据该Host是否和server_name匹配绝对是否对前端返回https。

3. 透传客户端ip

一般情况我们在nginx接入侧配置这条足以:

  1. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_add_x_forwarded_for的值为: 客户端穿过来的x_forwarded_for值+ remote_addr。如果客户端传来的x-forwarded-for值本事是非法、错误的。那么后端应用如果截取左起第一个字段获取到的ip值也是错误。
这个一般有2个办法,首先,可以在nginx接入对很明显非法的ip摘掉,强制把remote_addr值添到X-Forwarded-For字段:

  1. set $my_proxy_add_x_forwarded_for $proxy_add_x_forwarded_for;
  2. if ($proxy_add_x_forwarded_for ~* "127.0.0.1"){
  3.    set $my_proxy_add_x_forwarded_for $remote_addr;
  4. }
  5. proxy_set_header X-Forwarded-For $my_proxy_add_x_forwarded_for;
另外,如果是做ip频率限制、校验的话,还不如直接取X-Forwarded-For值的最后一段。因为伪造x-forword-for值的成本太低了。

4. 记录自动化测试用例请求
为定位问题时提供数据参考,如: 记录cookies中uin在某范围的请求延迟、返回码等。
这里用到lua:
  1. if ngx.var.cookie_uin ~= nil then
  2. local uin = tonumber(string.sub(ngx.var.cookie_uin,2,-1))


  3. if uin ~= nil and uin >=1011000140 and uin<=1011000149 then
  4.         --ngx.log(ngx.CRIT, "[ATT] att_client:"..ngx.var.remote_addr..",rsp_time:"..ngx.var.request_time..",upstream_rsp_time:" .. ngx.var.upstream_response_time .. ",upstream_addr:" .. ngx.var.upstream_addr..",upstream_status:"..tostring(ngx.var.upstream_status..","));
  5.         ngx.log(ngx.CRIT, "[ATT] att_uin:".. uin..",rsp_time:"..ngx.var.request_time..",upstream_rsp_time:" .. ngx.var.upstream_response_time .. ",upstream_status:"..ngx.var.upstream_status..",");
  6. end


阅读(2202) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~