實時採集並分析Nginx日誌, 自動化封禁風險IP方案
文章地址: https://blog.piaoruiqing.com/2019/11/17/block-ip-by-analyzing-nginx-logs/
前言
本文分享了自動化採集、分析Nginx日誌並實時封禁風險IP的方案及實踐.
閱讀這篇文章你能收穫到:
- 日誌採集方案.
- 風險IP評估的簡單方案.
- IP封禁策略及方案.
閱讀本文你需要:
- 熟悉編程.
- 熟悉常用Linux命令.
- 瞭解Docker.
背景
分析nginx訪問日誌時, 看到大量404的無效請求, URL都是隨機的一些敏感詞. 而且近期這些請求越來越頻繁, 手動批量封禁了一些IP後, 很快就有新的IP進來.
因此萌生了通過自動化分析Nginx日誌實時封禁IP的想法.
需求
序號 | 需求 | 備註 |
---|---|---|
1 | Nginx日誌收集 | 方案有很多, 筆者選擇了最適合個人服務器的方案: filebeat +redis |
2 | 日誌實時分析 | 實時消費redis 的日誌, 解析出需要的數據進行分析 |
3 | IP風險評估 | 對IP進行風險評估, 多個維度: 訪問次數、IP歸屬、用途等 |
4 | 實時封禁 | 針對風險IP進行不同時長的封禁 |
分析
從日誌中簡單總結幾個特徵:
序號 | 特徵 | 描述 | 備註 |
---|---|---|---|
1 | 訪問頻繁 | 每秒數次甚至數十次 | 正常的流量行爲也存在突發流量, 但不會持續很久 |
2 | 持續請求 | 持續時間久 | 同上 |
3 | 多數404 | 請求的URL可能大多數都不存在, 且存在敏感詞彙如admin、login、phpMyAdmin、backup等 | 正常流量行爲很少存在這種情況 |
4 | IP不正常 | 通過ASN能看出一些端倪, 一般這類請求的IP都不是普通的個人用戶. | 查詢其用途一般是COM(商業)、DCH(數據中心/網絡託管/傳輸)、SES(搜索引擎蜘蛛)等 |
備註: 這裏分析IP是通過ip2location的免費版數據庫, 後面會有詳細的描述.
方案
日誌採集
來源: 筆者的網站通過docker部署, Nginx作爲唯一入口, 記錄了全部訪問日誌.
採集: 由於資源有限, 筆者選擇了一款輕量的日誌採集工具Filebeat, 收集Nginx日誌並寫入Redis.
風險評估
Monitor服務根據URL、IP、歷史評分等進行風險評估, 計算出最終的危險係數.
IP封禁
Monitor發現危險IP後(危險係數超過閾值), 調用Actuator進行IP封禁, 封禁時長根據危險係數計算得出.
實施
日誌採集
Filebeat的用法很簡單, 筆者通過swarm進行部署, 其部署文件如下(爲防止代碼過長, 此處略去了其他服務):
version: '3.5'
services:
filebeat:
image: docker.elastic.co/beats/filebeat:7.4.2
deploy:
resources:
limits:
memory: 64M
restart_policy:
condition: on-failure
volumes:
- $PWD/filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
- $PWD/filebeat/data:/usr/share/filebeat/data:rw
- $PWD/nginx/logs:/logs/nginx:ro
environment:
TZ: Asia/Shanghai
depends_on:
- nginx
- image: 指定鏡像和版本.
- deploy.resources.limits.memory: 限制內存.
- $PWD/filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro: filebeat.yml是配置文件, 其中描述了日誌來源和去處.
$PWD
爲當前目錄, 即執行docker stack deploy
的目錄.ro
爲只讀權限. - $PWD/filebeat/data:/usr/share/filebeat/data:rw: 需要持久化data目錄, 這樣刪除docker重新部署也會記錄上一次讀取日誌的位置.
rw
爲讀寫權限. - $PWD/nginx/logs:/logs/nginx:ro: 將Nginx日誌目錄映射到Filebeat.
- environment.TZ: 時區
filebeat.yml
文件內容如下:
filebeat.inputs:
- type: log
enabled: true
paths:
- /logs/nginx/access.log
json.keys_under_root: true
json.overwrite_keys: true
output.redis:
hosts: ["redis-server"]
password: "{your redis password}"
key: "filebeat:nginx:accesslog"
db: 0
timeout: 5
-
filebeat.inputs: 定義輸入
-
paths: 日誌路徑
-
json.keys_under_root: 將日誌內容放到json的根節點(如果沒有設置, 整條數據會被放到一個二級節點下). 注: 筆者將nginx日誌配置爲json格式. 參考配置如下:
log_format main_json escape=json '{' '"@timestamp":"$time_iso8601",' '"http_host":"$http_host",' '"remote_addr":"$remote_addr",' '"request_uri":"$request_uri",' '"request_method":"$request_method",' '"server_protocol":"$server_protocol",' '"status":$status,' '"request_time":"$request_time",' '"body_bytes_sent":$body_bytes_sent,' '"http_referer":"$http_referer",' '"http_user_agent":"$http_user_agent",' '"http_x_forwarded_for":"$http_x_forwarded_for"' '}';
-
json.overwrite_keys: 覆蓋Filebeat生成的KEY, 此處爲了覆蓋
@timestamp
字段. -
output.redis: 定義輸出.
部署成功後查看redis數據:
風險評估
Monitor
服務使用Java編寫, 使用docker部署, 與Actuator
服務通過http交互.
風險評估需要綜合多個維度:
序號 | 維度 | 策略 |
---|---|---|
1 | IP歸屬地 | 中文網站的用戶羣體一般歸屬地都在中國, 若IP歸屬地爲國外就需要警惕了. |
2 | 用途 | 通過IP獲取其用途, DCH(數據中心/網絡託管/傳輸)、SES(搜索引擎蜘蛛)等提高危險評分. |
3 | 訪問資源 | 訪問資源不存在且路徑中含有敏感詞, 如admin、login、phpMyAdmin、backup等, 提高危險評分. |
4 | 訪問頻率及持續時間 | 頻繁且持久的請求, 考慮提高評分. |
5 | 歷史評分 | 歷史評分綜合到當前評分中. |
獲取IP歸屬地
IP歸屬地獲取比較容易, 有不少數據服務網站提供了免費套餐, 如IpInfo等. 也有免費版IP數據庫可以下載如ip2location等.
筆者使用了ip2location的免費版數據庫:
ip_from和ip_to是IP段起止, 存儲的格式是十進制, MySQL中可通過inet_aton('your ip')
函數將IP轉爲十進制. 如:
set @a:= inet_aton('172.217.6.78');
SELECT * FROM ip2location_db11 WHERE ip_from <= @a AND ip_to >= @a LIMIT 1;
ip_from | ip_to | country_code | country_name | region_name | city_name | latitude | longitude | zip_code | time_zone |
---|---|---|---|---|---|---|---|---|---|
2899902464 | 2899910655 | US | United States | California | Mountain View | 37.405992 | -122.07852 | 94043 | -07:00 |
- 數據量很大, 建議帶上
LIMIT 1
.
獲取AS、ASN及用途
多數網站提供的免費服務中都無法查詢ASN或沒有其用途. ASN數據也有免費的數據庫, 但是依舊沒有其用途及類型等. 此時筆者通過其它的方法曲線救國.
ip2location提供了免費版本的IP2Location™LITE IP-ASN
和IP2Proxy™LITE
數據庫.
IP2Location™LITE IP-ASN: 數據庫提供了確定自治系統和編號(ASN)的參考.
IP2Proxy™LITE: 數據庫包含被用作開放代理的IP地址. 該數據庫包括所有公共IPv4和IPv6地址的代理類型、國家、地區、城市、ISP、域、使用類型、ASN和最新記錄.
IP2Location™LITE IP-ASN中無法查詢到IP的使用類型, IP2Proxy™LITE數據較少中不一定會包含指定的IP. 但可以結合這兩個庫, 大致猜測IP的用途:
-
首先, 在IP2Proxy™LITE中查詢出IP的ASN.
set @a:= inet_aton('172.217.6.78'); SELECT * FROM ip2location_asn WHERE ip_from <= @a AND ip_to >= @a LIMIT 1;
ip_from ip_to cidr asn as 2899904000 2899904255 172.217.6.0/24 15169 Google LLC -
結合ASN和IP, 查詢相同ASN最接近指定IP的前後兩條記錄:
set @a:= inet_aton('172.217.6.78'); SELECT * FROM ip2proxy_px8 WHERE ip_from >= @a AND asn = 15169 ORDER BY ip_from ASC LIMIT 1; SELECT * FROM ip2proxy_px8 WHERE ip_from <= @a AND asn = 15169 ORDER BY ip_from DESC LIMIT 1;
ip_from ip_to region_name isp usage_type asn as 2899904131 2899904131 California Google LLC DCH 15169 Google LLC ip_from ip_to region_name isp usage_type asn as 2899904015 2899904015 California Google LLC DCH 15169 Google LLC -
計算查詢到的proxy記錄中IP與當前IP的差值的絕對值.
IP proxy IP abs(IP - proxy IP) 2899904078 2899904131 53 2899904078 2899904015 63 如果絕對值很接近, 那麼就認爲此IP的用途和proxy IP相同. 很接近的定義可以根據情況調整, 如絕對值在65535範圍內.
綜合評分
綜合評分的規則可根據實際場景進行調整
序號 | 評分項 | 評分規則(1-10分) |
---|---|---|
1 | IP歸屬地 | 如: 國內5分, 國外10分, 可根據地區再進行細分 |
2 | 用途 | 如: ISP/MOB計2分, COM計5分, DCH計10分 |
3 | 訪問資源 | 如: 404計5分, 存在敏感詞一律10分 |
4 | 訪問頻率及持續時間 | 根據一段時間內平均訪問次數計算分數 |
5 | 歷史評分 |
綜合上述1-5項, 進行計算, 可以簡單的相加, 也可加權計算.
IP封禁
筆者採用**iptables+ipset**的方式進行IP封禁. Actuator
服務使用node編寫, 運行在主機上, docker中的Monitor
通過http與其交互. 封禁IP部分代碼如下:
'use strict';
const express = require('express');
const shell = require('shelljs');
const router = express.Router();
router.post('/blacklist/:name/:ip', function (req, res, next) {
let name = req.params.name;
let ip = req.params.ip;
let timeout = req.query.timeout;
let cmd = `ipset -exist add ${name} ${ip} timeout ${timeout}`;
console.log(cmd);
shell.exec(cmd);
res.send('ok\n');
});
module.exports = router;
- name: 黑名單名稱.
- timeout: 超時時間, 單位: 秒.
目前, 還是有不少"頭鐵"的IP頻繁掃描筆者的網站, 在發現後幾秒內自動屏蔽掉, 目前效果比較理想.
結語
- 爬蟲、機器人、漏洞掃描等給網站造成了不必要的開銷甚至帶來風險, 不可忽視. 絕對安全很難做到, 但至少可以做到比別人安全.
- 封禁是相對暴力的手段, 一定要把握好尺度, 出現誤殺會導致網站流失用戶.
- 除了封禁外, 也可考慮"禍水東引", 將風險IP 302重定向到gitpage(備份站點), 這樣就算誤殺, 也不會造成用戶無法訪問的情況.
- 道路千萬條, 安全第一條
推薦閱讀:
- 開放API網關實踐(一) ——設計一個API網關
- 開放API網關實踐(二) —— 重放攻擊及防禦
- 開放API網關實踐(三) —— 限流
- Kubernetes(一) 跟着官方文檔從零搭建K8S
- Kubernetes(二) 應用部署
- Kubernetes(三) 如何從外部訪問服務
歡迎關注公衆號(代碼如詩):
本文發佈於樸瑞卿的博客, 允許非商業用途轉載, 但轉載必須保留原作者樸瑞卿 及鏈接:http://blog.piaoruiqing.com. 如有授權方面的協商或合作, 請聯繫郵箱: [email protected].