Nginx 服务器日志配置 – 解决使用CDN记录真实用户IP(包括宝塔)

关于nginx的日志配置,之前写过一:http://www.vuln.cn/2989 ,今天又用到发现其中还有很多点没有提及到,所以再写一篇记录全面一点。

修改的配置文件位置

该怎么改网上的教程已经很多,但是到底在哪个文件的什么地方修改,如何生效这才是根本问题。

我们需要修改是的nginx.conf 根配置文件

使用lnmp的服务器一般配置文件在:/usr/local/nginx/conf/nginx.conf,宝塔的配置文件我发现有两个地方有nginx.conf配置文件:/www/server/nginx/conf/nginx.conf/www/server/nginx/src/conf/nginx.conf。有效的配置文件是:/www/server/nginx/conf/nginx.conf

在以下位置添加修改的配置:

未分类

其中需要注意的是log_format main,这里的main,需要在vhost中各站点的日志配置的地方要带上,表示使用这个配置,如图:

未分类

修改以上两个位置即可让配置生效。

参数配置

通过抓包可以看到,cdn节点在溯源请求服务器地址的时候会将用户客户端的ip带上,以X-Forwarded-ForCF-Connecting-IP两个参数的形式,如图:

未分类

如果客户端加一个x-forwarded-for参数来尝试篡改,实际上该参数会有两个ip,后面的一个ip永远是真实ip,前面是伪造的:“8.8.8.8,163.160.73.253”

所以在配置日志参数时,可以将X-Forwarded-For参数的值放到第一位,nginx模块中的变量为$http_x_forwarded_for,所以最终的格式为以下,其中保留了原始的$remote_addr,否则真实ip请求网站无法获取ip。

 log_format  main  '"$http_x_forwarded_for"-$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"'; 

综合以上的配置,最终日志格式完美记录真实ip与cdn节点的ip:

未分类

nginx配置文件-安全配置-静止ip访问服务器

1、listen 指令后面有一个参数default_server ,这个参数是在 0.8.21 版本以后才有的,而之前是default 指令。Nginx 的虚拟主机是通过HTTP请求中的Host值来找到对应的虚拟主机配置,如果找不到呢?那 Nginx 就会将请求送到指定了 default_server 的 节点来处理,如果没有指定为 default_server 的话,就跑到 localhost 的节点,如果没有 localhost 的节点,那只好 404 了。

2、server_name _; 这里指定的不是什么特别的名字,它只是一个无效的域名。从来不会匹配任何真实名字相匹配。

一、80端口访问时:

这里介绍修改配置文件nginx.conf两种方法:
1)在server段里插入如下正则:
listen       80;
server_name  www.yuyangblog.net;
if ($host != 'www.yuyangblog.net'){
   return 403;
}


2)添加一个server
新加的server(注意是新增,并不是在原有的server基础上修改)
server {
  listen 80 default;
  server_name _;
  return 403;
}

二、443端口访问时:

必须要提供 ssl证书,才能 正确执行 ip 屏蔽 操作。

server
{
    listen 443 ssl default_server;
    ssl_certificate      path_to_your_fullchain.cer;
    ssl_certificate_key  paht_to_your_key;
    return 301 https://demo.com;
    #other return way
    #return  400;  # ban ip access to https server ,return 444, 404 is also OK

}

firewalld对指定IP开放指定端口的配置

1.打开firewalld防火墙

systemctl start firewalld.service

2.添加防火墙规则(对指定ip开放指定端口)
(以下红色字体需要根据实际情况修改)

#(1) Postgresql端口设置。允许192.168.142.166访问5432端口
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="5432" accept"
#(2)redis端口设置。允许192.168.142.166访问6379端口
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="6379" accept"
#(3)beanstalkd端口设置。允许192.168.142.166访问11300端口
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="11300" accept"

3.重启防火墙,使配置生效

systemctl restart firewalld.service

4.查看配置结果,验证配置

firewall-cmd --list-all

5.删除规则

示例:

firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.142.166" port protocol="tcp" port="11300" accept"
systemctl restart firewalld.service

wordpress IP验证不当漏洞修复

wordpress /wp-includes/http.php文件中的wp_http_validate_url函数对输入IP验证不当,导致黑客可构造类似于012.10.10.10这样的畸形IP绕过验证,进行SSRF。

解决方案:

在网站目录中找到这个wp-includes/http.php文件,编辑http.php

查找

$same_host = strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] );

替换成

if ( isset( $parsed_home['host'] ) ) { $same_host = ( strtolower( $parsed_home['host'] ) === strtolower( $parsed_url['host'] ) || 'localhost' === strtolower( $parsed_url['host'] ) ); } else { $same_host = false; };

查找

if ( 127 === $parts[0] || 10 === $parts[0] || 0 === $parts[0]

改成

if ( 127 === $parts[0] || 10 === $parts[0] || 0 === $parts[0] || 0 === $parts[0]

最后保存退出即可修复

使用nginx后如何在web应用中获取用户ip及原理解释

问题背景

在实际应用中,我们可能需要获取用户的ip地址,比如做异地登陆的判断,或者统计ip访问次数等,通常情况下我们使用request.getRemoteAddr()就可以获取到客户端ip,但是当我们使用了nginx作为反向代理后,使用request.getRemoteAddr()获取到的就一直是nginx服务器的ip的地址,那这时应该怎么办?

part1:解决方案

我在查阅资料时,有一本名叫《实战nginx》的书,作者张晏,这本书上有这么一段话“经过反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址”。这句话的意思是说,当你使用了nginx反向服务器后,在web端使用request.getRemoteAddr()(本质上就是获取$remote_addr),取得的是nginx的地址,即$remote_addr变量中封装的是nginx的地址,当然是没法获得用户的真实ip的,但是,nginx是可以获得用户的真实ip的,也就是说nginx使用$remote_addr变量时获得的是用户的真实ip,如果我们想要在web端获得用户的真实ip,就必须在nginx这里作一个赋值操作,如下:
proxy_set_header X-real-ip $remote_addr;
其中这个X-real-ip是一个自定义的变量名,名字可以随意取,这样做完之后,用户的真实ip就被放在X-real-ip这个变量里了,然后,在web端可以这样获取:
request.getAttribute("X-real-ip")
这样就明白了吧。

part2:原理介绍

这里我们将nginx里的相关变量解释一下,通常我们会看到有这样一些配置

server {
        listen       88;
        server_name  localhost;
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        location /{
            root   html;
            index  index.html index.htm;
                            proxy_pass                  http://backend; 
           proxy_redirect              off;
           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            X-Forwarded-For $http_x_forwarded_for;
        }

我们来一条条的看

1. proxy_set_header X-real-ip $remote_addr;
这句话之前已经解释过,有了这句就可以在web服务器端获得用户的真实ip
但是,实际上要获得用户的真实ip,不是只有这一个方法,下面我们继续看。

2. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
我们先看看这里有个X-Forwarded-For变量,这是一个squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,如果有做X-Forwarded-For设置的话,每次经过proxy转发都会有记录,格式就是client1, proxy1, proxy2,以逗号隔开各个地址,由于他是非rfc标准,所以默认是没有的,需要强制添加,在默认情况下经过proxy转发的请求,在后端看来远程地址都是proxy端的ip 。也就是说在默认情况下我们使用request.getAttribute(“X-Forwarded-For”)获取不到用户的ip,如果我们想要通过这个变量获得用户的ip,我们需要自己在nginx添加如下配置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
意思是增加一个$proxy_add_x_forwarded_for到X-Forwarded-For里去,注意是增加,而不是覆盖,当然由于默认的X-Forwarded-For值是空的,所以我们总感觉X-Forwarded-For的值就等于$proxy_add_x_forwarded_for的值,实际上当你搭建两台nginx在不同的ip上,并且都使用了这段配置,那你会发现在web服务器端通过request.getAttribute(“X-Forwarded-For”)获得的将会是客户端ip和第一台nginx的ip。

那么$proxy_add_x_forwarded_for又是什么?
$proxy_add_x_forwarded_for变量包含客户端请求头中的”X-Forwarded-For”,与$remote_addr两部分,他们之间用逗号分开。
举个例子,有一个web应用,在它之前通过了两个nginx转发,即用户访问该web通过两台nginx。
在第一台nginx中,使用
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
现在的$proxy_add_x_forwarded_for变量的”X-Forwarded-For”部分是空的,所以只有$remote_addr,而$remote_addr的值是用户的ip,于是赋值以后,X-Forwarded-For变量的值就是用户的真实的ip地址了。

到了第二台nginx,使用
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
现在的$proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,$remote_addr部分的值是上一台nginx的ip地址,于是通过这个赋值以后现在的X-Forwarded-For的值就变成了“用户的真实ip,第一台nginx的ip”,这样就清楚了吧。

最后我们看到还有一个$http_x_forwarded_for变量,这个变量就是X-Forwarded-For,由于之前我们说了,默认的这个X-Forwarded-For是为空的,所以当我们直接使用proxy_set_header X-Forwarded-For $http_x_forwarded_for时会发现,web服务器端使用request.getAttribute(“X-Forwarded-For”)获得的值是null。如果想要通过request.getAttribute(“X-Forwarded-For”)获得用户ip,就必须先使用proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;这样就可以获得用户真实ip。

ps:变量名太长,自己感觉看着好晕,打字打的我眼睛都花了,希望解释清楚了,如果有疑问可以和我交流,共同学习。

CentOS/Linux下设置IP地址

CentOS/Linux下设置IP地址

1、临时修改

1.1 修改IP地址

# ifconfig eth0 192.168.100.100

1.2 修改网关地址

# route add default gw 192.168.100.1 dev eth0

1.3 修改DNS

# echo “nameserver 8.8.8.8” >> /etc/resolv.conf

这个时候就可以上网了,上网的IP地址为192.168.100.100,网关地址为192.168.100.1。但是这样的设置是临时性的,一旦重启网卡或者重启服务器,除了1.3的操作其他均会被还原,这样的方式只适合临时IP修改,想要永久性修改网卡配置文件,就需要修改相应的文件

2、永久性修改

2.1 修改IP地址

修改/etc/sysconfig/network-scripts/ifcfg-eth0文件,如果有多张网卡,则修改相应的网卡

# vi /etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0 #网卡对应的设备别名
BOOTPROTO=static #网卡获得ip地址的方式(默认为dhcp,表示自动获取)
HWADDR=00:07:E9:05:E8:B4 #网卡MAC地址(物理地址)
IPADDR=192.168.100.100 #IP地址
NETMASK=255.255.255.0 #子网掩码
ONBOOT=yes #系统启动时是否激活此设备

2.2 修改网关地址

修改/etc/sysconfig/network文件

# vi /etc/sysconfig/network

NETWORKING=yes #表示系统是否使用网络,no表示不能使用网络
HOSTNAME=doiido #设置本机的主机名,要和/etc/hosts中设置的主机名相同
GATEWAY=192.168.100.1 #设置网关的IP地址
这个时候已经可以ping通IP地址,但是还无法ping通域名,因此需要修改DNS

2.3 修改DNS

修改/etc/resolv.conf文件

# vi /etc/resolv.conf

nameserver 8.8.8.8 #google域名服务器
nameserver 114.144.114.114 #国内域名服务器

2.4 重启网卡

# service network restart

正在关闭接口 eth0: [确定]
关闭环回接口: [确定]
弹出环回接口: [确定]
弹出界面 eth0: [确定]

这个时候,系统就可以正常的上网了

#注:其实网关地址和DNS也是可以写在ifcfg-eth0中,但是为了规范起见,将他们分开写

使用awk分析nginx访问日志access.log的ip

access.log为nginx的访问日志,默认路径在

/var/log/nginx/access.log

分析access.log的ip命令如下:

awk '{print $1}' access.log |sort|uniq -c|sort -n
  1. 命令里使用awk过滤出访问的ip

  2. 使用sort对ip排序

  3. 对排序后的ip进行统计,统计每一个ip访问数

  4. 最后使用sort 对访问数进行排序,排序为升序。

通过Wireshark抓取直连设备的IP地址

1、ARP协议简介

说到网络中的IP地址就不得不说APR协议。何为ARP?全名叫做Address Resolution Protocol(地址解析协议)。网络中的设备发送消息时将包含目标IP地址信息存入本设备APR缓存中并保留一段时间,下次请求时直接查询ARP缓存以节约资源。地址解析协议是建立在网络中各个主机互相信任的基础上的,网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其记入本机ARP缓存;由此攻击者就可以向某一主机发送伪ARP应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个ARP欺骗。ARP命令可用于查询本机ARP缓存中IP地址和MAC地址的对应关系、添加或删除静态对应关系等。相关协议有RARP、代理ARP。NDP用于在IPv6中代替地址解析协议。

ARP缓存是个用来储存IP地址和MAC地址的缓冲区,其本质就是一个IP地址–>MAC地址的对应表,表中每一个条目分别记录了网络上其他主机的IP地址和对应的MAC地址。每一个以太网或令牌环网络适配器都有自己单独的表。当地址解析协议被询问一个已知IP地址节点的MAC地址时,先在ARP缓存中查看,若存在,就直接返回与之对应的MAC地址,若不存在,才发送ARP请求向局域网查询。

为使广播量最小,ARP维护IP地址到MAC地址映射的缓存以便将来使用。ARP缓存可以包含动态和静态项目。动态项目随时间推移自动添加和删除。每个动态ARP缓存项的潜在生命周期是10分钟。新加到缓存中的项目带有时间戳,如果某个项目添加后2分钟内没有再使用,则此项目过期并从ARP缓存中删除;如果某个项目已在使用,则又收到2分钟的生命周期;如果某个项目始终在使用,则会另外收到2分钟的生命周期,一直到10分钟的最长生命周期。静态项目一直保留在缓存中,直到重新启动计算机为止。(以上出自https://baike.baidu.com/item/ARP/609343?fr=aladdin)

2、抓取直连设备IP

未分类

环境:将被获取的设备服务器B和计算机A相连(可直接用网线直连)
在A设备上将网口的所有IP信息清除(即改为DHCP),此步骤不做也可以,建议不要省略

未分类

网线连接后,打开安装好的wirshark软件,在过滤规则中输入 arp(只显示arp的数据包)

未分类

如果是直连的话,服务器B在关机状态下此界面是没有任何数据包显示的,接下来,只需要打开服务器B设备,就会获取直连网络中的ARP数据包。在数据包中就有服务器B的IP等信息了

未分类

who has XX.XX.XX.XX ? Tell BB.BB.BB.BB

此处BB.BB.BB.BB就是需要获取的地址。也包括此设备的MAC地址。

统计apache等web日志文件里访问量前十的ip并排序

处理方法:

# cat access.log | awk  '{print $1}' | sort | uniq -c | sort -n -r | head -10

日志格式不同参数$1需要稍作修改。

一些常用的查询

当前WEB服务器中联接次数最多的ip地址

#netstat -ntu |awk '{print $5}' |sort | uniq -c| sort -nr

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

#cat access.log |cut -d ' ' -f 1 |sort |uniq -c | sort -nr | awk '{print $0 }' | head -n 10 |less

查看日志中出现100次以上的IP

# cat access.log |cut -d ' ' -f 1 |sort |uniq -c | awk '{if ($1 > 100) print $0}'|sort -nr |less

查看最近访问量最高的文件

# cat access.log |tail -10000|awk '{print $7}'|sort|uniq -c|sort -nr|less

查看日志中访问超过100次的页面

# cat access.log | cut -d ' ' -f 7 | sort |uniq -c | awk '{if ($1 > 100) print $0}' | less

统计某url,一天的访问次数

# cat access.log|grep '12/Aug/2009′|grep '/images/index/e1.gif'|wc|awk '{print $1}'

前五天的访问次数最多的网页

#cat access.log|awk '{print $7}'|uniq -c |sort -n -r|head -20

从日志里查看该ip在干嘛

#cat access.log | grep 218.66.36.119| awk '{print $1″t"$7}' | sort | uniq -c | sort -nr | less

列出传输时间超过 30 秒的文件

#cat access.log|awk '($NF > 30){print $7}' |sort -n|uniq -c|sort -nr|head -20

列出最最耗时的页面(超过60秒的)

#cat access.log |awk '($NF > 60 && $7~/.php/){print $7}' |sort -n|uniq -c|sort -nr|head -100

Nginx配置禁止IP直接HTTP/HTTPS访问

这样配置可以禁止IP直接HTTP/HTTPS访问,也使未绑定的域名无法访问。

#http
server 
{
  listen 80 default_server;
  server_name _;
  return 500;
}

#https
server 
{
  listen 443 ssl default_server;
  server_name _;
  ssl_certificate      /yourpath/ssl.crt;
  ssl_certificate_key  /yourpath/ssl.key;
  return 500;
}

需要配置秘钥 否则会到时全部ssl配置失效 不知道为啥

yum install -y openssl
openssl genrsa -des3 -passout pass:x -out ssl.pass.key 2048
openssl rsa -passin pass:x -in ssl.pass.key -out ssl.key
openssl req -new -key ssl.key -out ssl.csr
…… 一路回车 ……
openssl x509 -req -days 3650 -in ssl.csr -signkey ssl.key -out ssl.crt