HTTP 액세스 로그를 구문 분석하여 1초 내에 429로 응답한 모든 요청을 가져옵니다.

HTTP 액세스 로그를 구문 분석하여 1초 내에 429로 응답한 모든 요청을 가져옵니다.

nginx의 일반적인 access.log 파일

000.00.000.001 - - [28/Jun/2021:06:37:02 +0100] "POST /abc/cba/ HTTP/1.1" 429 1157 "data..."
000.00.000.002 - - [28/Jun/2021:06:37:02 +0100] "POST /abc/cba/ HTTP/1.1" 200 741 "-" "data..."
000.00.000.001 - - [28/Jun/2021:06:37:02 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.001 - - [28/Jun/2021:06:37:02 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.001 - - [28/Jun/2021:06:37:02 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.001 - - [28/Jun/2021:06:37:02 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.003 - - [28/Jun/2021:06:37:03 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.003 - - [28/Jun/2021:06:37:03 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.003 - - [28/Jun/2021:06:37:03 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.003 - - [28/Jun/2021:06:37:03 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.003 - - [28/Jun/2021:06:37:03 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.004 - - [28/Jun/2021:06:37:03 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.004 - - [28/Jun/2021:06:37:03 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."
000.00.000.004 - - [28/Jun/2021:06:37:03 +0100] "POST /abc/cba/ HTTP/1.1" 429 741 "-" "data..."

문제는 응답 코드가 429이고 언제든지 1초 내에 생성되는 모든 IP 주소를 로그 파일에서 어떻게 얻을 수 있느냐는 것입니다. 나는 awk를 사용하여 해결책을 찾으려고 노력하고 있지만 누군가 나에게 힌트를 줄 수 있다면 아직 성공하지 못했습니다. 주어진 예제의 출력은 다음과 같습니다:

28/Jun/2021:06:37:02:
000.00.000.001
28/Jun/2021:06:37:03:
000.00.000.003
  1. 5개 이상의 요청을 하는 IP만
  2. 응답 상태 429가 있습니다
  3. 특정 초가 아닌 시간에 나타나는 응답이 있는 경우 초 단위로 그룹화

답변1

이게 당신이 하고 싶은 일인가요?

$ awk -F'[[ ]+' '$9==429{print $4, $1}' file | uniq -c | awk '$1>4{print $2 ":\n" $3}'
28/Jun/2021:06:37:02:
000.00.000.001
28/Jun/2021:06:37:03:
000.00.000.003

예를 들어 첫 번째 따옴표 세트의 내용이 "POST /abc/cba/ HTTP/1.1"예제 입력과 같이 항상 3개의 공백으로 구분된 문자열로 구성되지 않는 경우 다음과 같이 조정하세요.

$ awk -F'[[ ]+' '{sub(/"[^"]*"/,"")} $6==429{print $4, $1}' file | uniq -c | awk '$1>4{print $2 ":\n" $3}'
28/Jun/2021:06:37:02:
000.00.000.001
28/Jun/2021:06:37:03:
000.00.000.003

어떤 이유로 awk 전용 솔루션을 선호하는 경우:

$ awk -F'[[ ]+' '$9==429{cnt[$4":\n"$1]++} END{for (key in cnt) if (cnt[key]>4) print key}' file
28/Jun/2021:06:37:02:
000.00.000.001
28/Jun/2021:06:37:03:
000.00.000.003

위의 모든 스크립트는 모든 Unix 시스템의 모든 셸에서 필수 POSIX 도구를 사용하여 간단히 작동합니다.

관련 정보