关于Nginx与Httpd整合的逆向分析

本文为旧博客迁移的文章

一个典型的 Nginx + Httpd 应用方案可以是Nginx 占用 80 端口,过滤静态请求,然后动态请求即 Proxy 到 Apache 的 8080 端口或其他。Proxy 反向代理的好处是访问的时候,始终就是 80 端口,来访者不会觉察到有任何的区别。
nginx 适合做静态,简单,效率高
apache 适合做动态,稳定,功能强

以下是某次对位置服务器探索与分析,在首次进入服务器后探索服务器架构,如nginx、httpd安装路径以及修改相应的配置文件。

1、通过进入/alidata/server目录,可以看到

1
httpd  httpd-2.4.10  mysql  mysql-5.5.40  nginx  php  php-5.4.23

易知服务器同时安装了nginxhttpd

2、通过netstat -tunlp发现,nginx占用80端口,Http占用8088端口。
通过访问IP:80,无反应,推测Nginx作为前端代理服务器,httpd作为后端服务器。

1
2
3
4
5
6
7
8
9
10
11
12
[username conf]# netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 27851/mysqld
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 23151/nginx
tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 8029/vsftpd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1398/sshd
tcp 0 0 0.0.0.0:8088 0.0.0.0:* LISTEN 23190/httpd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1500/master
udp 0 0 172.18.65.6:123 0.0.0.0:* 1409/ntpd
udp 0 0 127.0.0.1:123 0.0.0.0:* 1409/ntpd
udp 0 0 0.0.0.0:123 0.0.0.0:* 1409/ntpd

3、通过ps -ef | grep nginx 命令,找到nginx的运行位置(aux | grep nginx 同理)

1
2
3
4
[username conf]# ps -ef | grep nginx
root 23151 1 0 Jul15 ? 00:00:00 nginx: master process /alidata/server/nginx/sbin/nginx -c /alidata/server/nginx/conf/nginx.conf
www 27516 23151 0 Jul17 ? 00:00:00 nginx: worker process
root 28504 28099 0 00:37 pts/0 00:00:00 grep nginx

4、通过上面找到的路径,通过 /alidata/server/nginx/sbin/nginx -t命令找到nginx.conf路径

1
2
3
[username conf]# /alidata/server/nginx/sbin/nginx -t
nginx: the configuration file /alidata/server/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /alidata/server/nginx/conf/nginx.conf test is successful

5、通过对nginx的配置文件/alidata/server/nginx/conf/nginx.conf分析,相应的vhosh是通过以下语句加载include /alidata/server/nginx/conf/vhosts/*.conf;

1
[username conf]# vi /alidata/server/nginx/conf/nginx.conf

6、通过查看vhosh目录,发现服务器内存在3个文件:

1
2
3
4
[username conf]# ls /alidata/server/nginx/conf/vhosts/*.conf
/alidata/server/nginx/conf/vhosts/app1.conf
/alidata/server/nginx/conf/vhosts/app2.conf
/alidata/server/nginx/conf/vhosts/app3.conf

7、分别查看三个配置文件:

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
[username conf]# vi /alidata/server/nginx/conf/vhosts/appX.conf
server
{
listen 80;
#listen [::]:80;
server_name appX.XXX.com;
index index.html index.htm index.php default.html default.htm default.php;
root /alidata/www/appX;

location /
{
try_files $uri @apache;
}

location @apache
{
internal;
proxy_pass http://127.0.0.1:8088;
include proxy.conf;
}

location ~ [^/]\.php(/|$)
{
proxy_pass http://127.0.0.1:8088;
include proxy.conf;
}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}

location ~ .*\.(js|css)?$
{
expires 12h;
}

access_log /alidata/log/nginx/access/appX.log;
}

命令讲解:【来源:初识nginx——配置解析篇

location  
location会尝试根据用户请求中的URI来匹配设置的表达式 并选中最终结果中的配置来处理用户的请求

  • location [=||*|^~|@] / uri / { … }
  • =表示把uri作为字符串,与参数中的URI作完全匹配
  • ~进行正则表达式匹配的时候,区分大小写
  • ~*进行正则表达式匹配的时候,不区分大小写
  • ^~表示匹配URI的时候,如果该location是最佳匹配,那么对于匹配这个location的字符串不在进行正则表达式的匹配检测
  • @表示仅用于nginx服务内部请求之间的重定向,带有@的location不直接处理用户请求

匹配的优先级如下:

  • 如果查询精确的命中了一个使用=前缀的location,那个它将被使用,并结束匹配
  • 在剩下普通字符串中,将按照最大前缀匹配的原则进行匹配,将结果最后候选结果,如果最终命中的结果使用了^~前缀表示或者它是一个完全匹配,那么它将被使用,并结束匹配
  • 正则表达式匹配时,按照正则表达式在配置文件中出现的顺序,并且只有匹配到了一条正则local,就不在匹配下面的local了
  • 如果步骤3命中了一个匹配,那个它将被使用,否则将使用步骤2的候选结果
  • (普通字符串和正则字符串的区别 *前缀表示location是正则字符串,其他前缀和无前缀表示location是普通字符串)

try_files
try_files:【来源:nginx中的try_files指令解释

1
try_files $uri $uri/ /index.php?q=$uri&$args;

按顺序检查文件是否存在,返回第一个找到的文件。结尾的斜线表示为文件夹 $uri/。如果所有的文件都找不到,会进行一个内部重定向到最后一个参数。  
  务必确认只有最后一个参数可以引起一个内部重定向,之前的参数只设置内部URI的指向。 最后一个参数是回退URI且必须存在,否则将会出现内部500错误。
  命名的location也可以使用在最后一个参数中。与rewrite指令不同,如果回退URI不是命名的location那么$args不会自动保留,如果你想保留$args,必须明确声明。
Nginx配置指令try_files:不存在就去查找location @qwe的值

internal:【来源:Nginx配置文件详细说明】【参考:Nginx模块参考手册:HTTP核心模块
设定某个location路径只能在内部使用,不能用于外部,外部的调用请求会返回”Not found” (404)

proxy_pass:【参考:Nginx配置proxy_pass的/路径问题
反向代理到http://127.0.0.1:8088

expires:【参考:nginx配置静态文件expires时间与cache-control
设置静态文件过期时间

access_log:【用法:nginx日志配置
nginx有一个非常灵活的日志记录模式。每个级别的配置可以有各自独立的访问日志。
日志格式通过log_format命令来定义。ngx_http_log_module是用来定义请求日志格式的。

8、分析得出,当打开网站的时候,首先由nginx路由。对于路径不存在的文件、*.php文件就转发到httpd处理。对于静态的文件,就由nginx处理,并且做缓存。

9、接下来打开httpd.conf

1
[username conf]# vi /alidata/server/httpd/conf/httpd.conf
  • 通过搜索 <Directory "/alidata/www">就可以看到相关配置了,
  • 通过搜索 Include 可以看到Include conf/extra/httpd-vhosts.conf

10、查看conf/extra/httpd-vhosts.conf 文件

1
[username conf]# vi /alidata/server/httpd/conf/extra/httpd-vhosts.conf

里面存在引入vhosts目录下所有.conf后缀的文件

1
Include /alidata/server/httpd/conf/vhosts/*.conf

11、通过ls /alidata/server/httpd/conf/vhosts/命令查看目录下所有文件,  
通过vivimtail等工具查看全部文件的内容

1
2
[username conf]# ls /alidata/server/httpd/conf/vhosts/
[username conf]# vi /alidata/server/httpd/conf/vhosts/appX.conf

12、得到最终的httpd配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<DirectoryMatch "/alidata/www/appX(attachment|html|data)">
<Files ~ ".php">
Order allow,deny
Deny from all
</Files>
</DirectoryMatch>

<VirtualHost *:8088>
DocumentRoot /alidata/www/appX
ServerName app3.xxx.com
<Directory "/alidata/www/appX">
Options FollowSymLinks
AllowOverride all
Order allow,deny
Allow from all
</Directory>
<IfModule dir_module>
DirectoryIndex index.php index.html index.htm
</IfModule>
</VirtualHost>