Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。

正向代理

特点:客户端非常明确要访问的服务器地址,屏蔽或隐藏了真实客户端信息。

流程:客户端 —> 正向代理服务器–> 远程网站、资源

用途:1.访问无法访问资源;2.做缓存;3.对客户端访问授权,上网进行认证;4.代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息

反向代理

特点:反向代理隐藏了服务器的信息

作用:(1)保证内网的安全,通常将反向代理作为公网访问地址,Web服务器是内网;(2)负载均衡,通过反向代理服务器来优化网站的负载

Nginx日志

日志位置

默认在 /usr/local/nginx/logs 目录下

access.log 访问日志

error.log 错误日志

nginx.conf 配置文件

nginx.conf

日志格式

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"';

这里是通达OA中的默认配置

$remote_addr:请求服务器的客户端IP

$remote_user:客户端用户名称,此项是用来记录用户HTTP的身份验证信息。如果某些网站要求用户进行身份验证,那么这一项就是记录用户的身份信息;

$time_local: 请求的时间与时区;

$request: 用来记录”请求方法/访问路径请求参数/协议”;

$status: 用来记录请求状态;

$body_bytes_sent :记录发送给客户端文件主体内容大小;

$http_referer:用来记录从哪个页面链接访问过来的;

$http_user_agent:记录客户浏览器的相关信息;

$http_x_forwarded_for:用以记录客户端的ip地址;

日志样例

1
127.0.0.1 - - [18/Aug/2021:16:09:30 +0800] "GET /inc/new_sms.php?now=1629274170398 HTTP/1.1" 200 33 "http://localhost:88/general/index.php" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727)" "-"

X-Forwarded-For和 REMOTE_ADDR的区别

REMOTE_ADDR代表着客户端的IP,但是这个客户端是相对服务器而言的,也就是实际上与服务器相连的机器的IP(建立tcp连接的那个),这个值是不可伪造的,如果没有代理的话,这个值就是用户实际的IP值,有代理的话,REMOTE_ADDR会被设置为代理机器的IP值。
正如前面所说,有了代理就获取不了用户的真实IP,由此X-Forwarded-For应运而生,它是一个非正式协议,在请求转发到代理的时候代理会添加一个X-Forwarded-For头,将连接它的客户端IP(也就是你的上网机器IP)加到这个头信息里,这样末端的服务器就能获取真正上网的人的IP了。

🌰🌰🌰

假设用户的请求顺序如下:
网民电脑ip->代理服务器1–>代理服务器2–>目标服务器
REMOTE_ADDR 就是: 代理服务器2的IP值
**X-Forwarded-For **就是:网民电脑IP,代理1的IP,代理2的IP
在这里只有REMOTE_ADDR是可信的,其他从客户端获取的数据都是不可信的,都是可伪造的。

🥚💦

服务器端开了nginx反向代理的时候,每次获取的都是反向代理的IP,需要nginx在配置反向代理的时候做一定设置并且修改代码。

1
2
3
proxy_set_header            Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

反向代理nginx的配置中将REMOTE_ADDR赋给了X-Real-IP,从X-Real-IP中来获取用户的IP

nginx获取post数据

$request_body是nginx的内置变量,可以记录post的数据

1
192.168.79.132 - - [25/Aug/2021:14:06:38 +0800] "POST /logincheck.php HTTP/1.1" 200 1000 "http://192.168.77.175:8668/" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" "-" "UNAME=admin&PASSWORD=&encode_type=1"

日志分析

GoAccess

Github地址 官网

中文站点

安装

1
sudo apt-get install goaccess

安装好的版本是1.4的,够用了后续用centos搭建的时候,再补充编译安装吧。

使用定义好的日志格式在终端输出

1
goaccess oa.access.log -c

预定义的选项包括:通用日志格式,联合日志格式,包含虚拟主机,W3C 格式以及亚马逊 CloudFront(分布式下载)。

image-20210820163337623

空格选中,回车继续,q退出,选择通用日志格式(CLF)

image-20210820163450514

终端输出:

image-20210820163616304

终端热键:

F1h主帮助页面。

F5重绘主窗口。

q退出程序,当前窗口或者崩溃了的模块。

oENTER扩展选中的模块或打开窗口。

0-9Shift + 0激活选中的模块。

c设置或者改变配色方案。

滚动功能:
j在已扩展模块中向下滚动。

k在已扩展模块中向上滚动。

^ f在当前模块中向滚动一页。

^ b在当前模块中向滚动一页。

TAB切换模块(向后)。#和官网手册上写的不一样

SHIFT + TAB切换模块(向后)。 #测试无效

g移动到第一个选项或者屏幕顶部。

G移动到第最后一个选项或者屏幕底部。

s给活跃模块的选项排序。
image-20210820165332356

**/**在所有模块中搜索(支持正则)。

n找到下次发生事件的位置。

自定义 日志/日期 格式

GoAccess 可以解析虚拟的任意 Web 日志格式。

配置文件位于:%sysconfdir%/goaccess.conf 或者 ~/.goaccessrc

注意: `%sysconfdir%` 可能是 /etc/, /usr/etc/ 或者 /usr/local/etc/

time-format 参数 time-format 后跟随一个空格符,指定日志的时间格式,包含普通字符与特殊格式说明符的任意组合。他们都由百分号 (%)开始。参考 man strftime%T 或者 %H:%M:%S.

注意: 如果给定的时间戳以**微秒**计算,则必须在 *time-format* 中使用参数 `%f` 。

date-format 参数 date-format 后跟随一个空格符,指定日志的日期格式,包含普通字符与特殊格式说明符的任意组合。他们都由百分号 (%)开始。参考 man strftime

注意: 如果给定的时间戳以微秒计算,则必须在 *time-format* 中使用参数 `%f` 。

log-format 参数 log-format 后跟随一个空格符或者制表分隔符(\t),用于指定日志字符串格式。

朋友发给我一个他自己写的配置🤡

1
2
3
4
5
6
7
8
9
10
11
12
13
log_format  access_json_log escape=json '{"@timestamp":"$time_local",'
'"http_host":"$http_host",'
'"clientip":"$remote_addr",'
'"request":"$request",'
'"status":"$status",'
'"size":"$body_bytes_sent",'
'"upstream_addr":"$upstream_addr",'
'"upstream_status":"$upstream_status",'
'"upstream_response_time":"$upstream_response_time",'
'"request_time":"$request_time",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"http_x_forwarded_for":"$http_x_forwarded_for"}';

看起来是个狠人

那就写个配置文件练习一下

1
2
3
time-format %H:%M:%S
date-format %d/%b/%Y
log_format {"%^":"%d:%t %^","%^":"%^","%^":"%h","%^":"%r","%^":"%s","%^":"%b","%^":"%^","%^":"%^","%^":"%^","%^":"%^","%^":"%^","%^":"%u","%^":"%^"}

我感觉我这种做法太笨蛋🤓🤓,其实最后一个XFF按照官网手册应该是~h的,但不知道为什么写上去就报错,后续再研究一下吧。

特殊格式说明符

%x 匹配 time-format 和 date-format 变量的日期和时间字段。用于使用时间戳来代替日期和时间两个独立变量的场景。

%t 匹配 time-format 变量的时间字段。

%d 匹配 date-format 变量的日期字段。

%v 根据 canonical 名称设定的服务器名称(服务区或者虚拟主机)。

%e 请求文档时由 HTTP 验证决定的用户 ID。

%h 主机(客户端IP地址,IPv4 或者 IPv6)。

%r 客户端请求的行数。这些请求使用分隔符(单引号,双引号)引用的部分可以被解析。否则,需要使用由特殊格式说明符(例如:**%m**, %U, %q%H)组合格式去解析独立的字段。

  • 注意: 既可以使用 **%r** 获取完整的请求,也可以使用 **%m**, **%U**, **%q** and **%H** 去组合你的请求,但是不能同时使用。

%m 请求的方法。

%U 请求的 URL。

  • 注意: 如果查询字符串在 **%U**中,则无需使用 **%q**。但是,如果 URL 路径中没有包含任何查询字符串,则你可以使用 **%q** 查询字符串将附加在请求后面。

%q 查询字符串。

%H 请求协议。

%s 服务器回传客户端的状态码。

%b 回传客户端的对象的大小。

%R HTTP 请求的 “Referer” 值。

%u HTTP 请求的 “UserAgent” 值。

%D 处理请求的时间消耗,使用微秒计算。

%T 处理请求的时间消耗,使用带秒和毫秒计算。

%L 处理请求的时间消耗,使用十进制数表示的毫秒计算。

%^ 忽略此字段。

%~ 继续解析日志字符串直到找到一个非空字符(!isspace)。

~h 在 X-Forwarded-For (XFF) 字段中的主机(客户端 IP 地址,IPv4 或者 IPv6)。

针对 XFF, GoAccess 使用了一个特殊符号,即由一个波浪号+主机说明符构成,然后紧跟由大括号封装起来的 XFF 限定字段(例:**~h{,"}**)。

举例如下, ~h{," } 用于解析 “11.25.11.53, 17.68.33.17” 字段由一对双引号,一个逗号和一个空格限定。

输出HTML页面

静态:

1
sudo goaccess access.log -p .goaccessrc -o /var/www/html/report.html

这里输出路径开了kali2021,Apache服务。

-p:指定要使用的自定义配置文件

-o:输出到指定扩展名文件中(Html、Json、CSV)

动态:

1
sudo goaccess access.log -p .goaccessrc -o /var/www/html/report.html --real-time-html

生成实时 HTML 报告的过程和生成静态报告的过程非常相似。实时报告仅仅需要使用参数 --real-time-html

输出结果:

image-20210820183543494

Linux 命令分析

常用命令

xargs命令的作用,是将标准输入转为命令行参数。

具体用法详见:xargs 命令教程

cut命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。

  • -d :自定义分隔符,默认为制表符。
  • -f :与-d一起使用,指定显示哪个区域。

sort将文本文件内容加以排序。

  • [-k field1[,field2]] 按指定的列进行排序。
  • -r 以相反的顺序来排序。

uniq用于检查及删除文本文件中重复出现的行列

-c或–count 在每列旁边显示该行重复出现的次数。

image-20210823193719130

wc将计算指定文件的行数、字数,以及字节数

  • -l或–lines 显示行数。

定位具体的IP地址或文件名

1
2
find . access.log | xargs grep "ip"
find . access.log | xargs grep "filename"

查找文件名包含access.log以后,对每个文件搜索一次是否包含字符串的内容

顺便一说:奇安信的《网络安全应急响应》这里好像写错了

IP驱动

查看访问次数最多的前10个IP

1
cat oa.access.log | cut -f1 -d " " | sort | uniq -c | sort -k 1 -rn |head -10

先把IP字段提取出来,去重排列,计数根据计数结果也就是第一列排序。

image-20210823195053834

顺便再一说:奇安信的《网络安全应急响应》这里少了个n参数。

查看每一个IP访问量:

1
awk '{++S[$1]} END {for (a in S) print a,S[a]}' oa.access.log

查看特定的ip访问的url

1
rep ^127.0.0.1 oa.access.log| awk '{print $1,$7}'

时间驱动

查看xxx时间点这一个小时内IP访问量:

1
awk '{print $4,$1}' oa.access.log | grep 23/Aug/2021:15 | awk '{print $2}'| sort | uniq | wc -l

目的驱动(访问的url等)

去掉搜索引擎统计当天的页面:

1
awk '{print $12,$1}' oa.access.log | grep ^\"Mozilla | awk '{print $2}' |sort | uniq| wc -l

统计日志文件中的爬虫

1
grep -E 'Googlebot|Baiduspider' log_file | awk '{ print $1 }' | sort | uniq

统计相关扫描器

1
cat log_file | grep -v -E 'python|java|awvs' | sort | uniq -c | sort -r -n | head -n 100

统计HTTP状态码

1
cat log_file |awk '{print $9}'|sort|uniq -c|sort -rn|more

访问URL统计

1
cat log_file |awk '{print $7}'|sort|uniq -c|sort -rn|more

URL访问量统计

1
cat log_file | awk '{print $7}' | egrep '\?|&' | sort | uniq -c | sort -rn | more

参考链接