Splunk 명령어

Splunk 검색 명령어

데이터 나열, 변환 table, rename, fields, dedup
통계 계산 stats, top, rare, len(x)
차트 시각화 timechart, chart
비교분석 eval, case, cidrmatch, if, like, match
다중문자열과 시간 mvindex, split, substr, round, ruldecode, strftime, strptime, now

차트 시각화 명령어는 로그들이 텍스트로 되어 있기 때문에, visual 하게 보는 것이 로그에 대한 이해도를 높일 수 있기에 사용하는 명령어로, 보고서 쓸 때나 대시보드 구성할 때 많이 사용함

 

Splunk 검색 실습

검색하려고 할 때, 먼저 시간을 체크(전체시간으로 설정)

검색창에 필드명을 정확히 모를땐 키워드만 입력해도 충분히 찾을 수 있음

검색 > category*

 

검색 > 400

=> 데이터 길이가 400이거나, 오류코드가 400인 경우 등 400이 있는 것은 모두 찾음

=> 오류코드가 400인 경우를 원한다면 status=400(필드명과 필드값)을 입력해줘야함

 

검색 > status=400 categoryId=Null

=> status와 categoryId 사에에 and, && 연산자가 있는 것임

=> 두 개의 조건 모두 만족해야 검색됨

=> 클라이언트가 값을 넣을 때 categoryId를 설정하지 않아서 400 오류가 발생했음을 파악

=> 하나의 문장을 검색하고 싶을 때, access denied 같은 경우, "access denied"로 검색해야 함

      큰따옴표를 사용하지 않으면 access && denied 가 검색되는 것임

 

검색 > 401 OR 402 OR 403

=> 만약 401나 402나 403을 검색하고 싶을 때, 401 OR 402 OR 403을 검색하면 됨(연산자 사용 시 대문자 사용)

=> 관계연산자가 소문자인 경우 검색결과 X

=> 우선순위의 경우 괄호 사용 가능

 

[검색 정리]

● 키워드로 검색 시 대소문자 구별 하지 않음

- error / ERROR 모두 가능

● 문자열을 검색하기 위해서는 큰따옴표 사용

- "access denied"

● 연산자 사용 시 반드시 대문자 사용

- 401 or 402 (X)

- 401 OR 402 (O)

- 연속하여 작성하면 AND 연산자가 생략된 것(401 402 403)

● 괄호를 이용하여 우선순위 지정 가능

- 401 AND (402 OR 403)

● 시간 점검 필수!!

● 자동완성기능 사용 추천!!


table

- 검색 결과를 테이블 형태로 보여주는 것

- 필드명은 대소문자를 구분해야 함

- 여러 개의 필드는 쉼표 또는 띄어쓰기로 구분

 

검색 > index=main sourcetype=access_combined_wcookie | table clientip, method, productId, status

=> 저장소를 인덱스라고 하는데, 저장소 이름 중에 main이라는 것이 있음.

=> main에서 sourcetype 중에서 access_combined_wcookie를 검색

=> 검색결과를 테이블 형태로 확인, 그때 clientip와 method, productID, status를 출력

 

rename

- 필드명을 다른 이름으로 변경

- 필드명을 띄어쓰기로 구분하고 싶으면 원하는 필드명을 따옴표로 표시

 

검색 > index=main sourcetype=access_combined_wcookie | table clientip, action, productId, status | rename action AS "Customer Action", productId AS ProductID, status AS "HTTP Status"

 

sort

- 검색 결과를 정렬

- 필드명을 띄어쓰기로 구분하고 싶으면 원하는 필드명을 따옴표로 표시

 

검색 > index=main sourcetype=access_combined_wcookie | table clientip, action, productId, status | sort action, -productId

=> action에 대해서 오름차순, productId에 대해서는 내림차순

=> +action / action 모두 오름차순(+ 생략 가능)

=> 기본 action으로 오름차순이고, 중복이 되는 데이터에 대해서는 productId를 기준으로 내림차순 정렬

 

dedup

- 검색 결과에서 중복값 제거

- 지정한 필드 기준으로 실행

- 두 개 이상 필드에서 중복을 제거하려면 쉼표로 구분

- 해당 필드에 존재하는 값을 확인하고 싶을 때 사용

 

검색 > index=main sourcetype=access_combined_wcookie status=404

검색 > index=main sourcetype=access_combined_wcookie status=404 | dedup host

=> 이 컴퓨터에는 404 코드가 잡힘

=> 몇 건이 있었어가 아니라 그냥 그런 일이 있었어


stats

- 통계함수를 이용하여 데이터 계산

함수명 설명
count(X) 개수를 반환
dc(X) 중복을 제거한 개수 반환
sum(X) 총합 반환
avg(X) 평균 반환
list(X) 목록으로 만들어 반환
values(X) 중복을 제거한 목록 반환
max(X), median(X), min(X) 최대, 중앙, 최소값 반환
var(X) 분산값 반환
stdev(X) 표준편자 반환

 

검색 > index=main sourcetype="access_combined_wcookie"

=> 1665가 의미하는 게 뭘까? 

=> > 이 부분 눌러서 확인하면 bytes 값임을 확인할 수 있음

 

검색 > index=main sourcetype="access_combined_wcookie" | stats sum(bytes), avg(bytes), max(bytes), median(bytes), min(bytes) by clientip

=> clientip를 기준으로 합계, 평균, 최댓값, 중간값, 최솟값을 검색

=> 통계치 구하기

=> 이 ip는 bytes가 왜 이렇게 많지? 이벤트보기로 해당 ip만 볼 수 있음

=> clientip들이 평균 얼마만큼의 데이터를 송수신하고 있는지 확인

 

top

- 지정한 필드에서 가장 많이 나오는 값을 보여주는 명령어

- 검색 결과를 파이프로 입력받아 계산한 후 결과 반환

- showperc와 showcount의 기본값이 T이므로 지정하지 않더라도 비율과 개수를 보여줌

limit - 반환되는 결과 개수를 지정
- 숫자를 지정하지 않으면 기본적으로 10개로 설정
- 전체 값을 모두 보려면 limit=0 설정
showperc - 해당 값이 차이하는 비율을 보여줌
- 기본값 T
showcount - 해당 값의 개수를 보여줌
- 기본값 T
useother Top10 외 다른 숫자의 크기를 알고 싶다면 T 입력

 

rare

- top과 반대의 결과인 빈도가 적은 값의 순서를 추출

- 희귀한 사이트로 가는 것, 빈도수가 낮은 사이트 방문, 얘는 왜 이 사이트를 방문했는가? 

 

검색 > * | top useother=T clientip by method

검색 > * | rare useother=T clientip by method

=> top과 rare 결과의 차이!!

=> top 결과를 보면 method를 기준으로 clientip가 count 만큼 사용함을 확인(count가 많음)

=> rare 결과를 보면 많이 안 쓴 것들을 보여줌(ex. GET 메소드를 59개 사용, POST는 30개)


차트시각화

- 원본 로그 데이터로 차트 그리기는 불가능

- 데이터를 차트로 만들려면 먼저 관련 데이터 추출

- 시각화 원본 데이터를 통계 테이블로 변환

 

timechart

- 시간에 따른 통계 테이블 생성

- 시간 필드가 X축, 실제 데이터가 Y축에 표시되는 차트 시각화 형식으로 출력

- 시간에 따른 통계의 추세를 표시할 때 사용

- Span : 시간 계산 단위 설정

- Count : 전체 개수를 계산하는데 12시간 단위로 총 숫자를 구하여 보여줌

 

검색 > index=main sourcetype="access_combined_wcookie" | timechart span=12h count(clientip) as "Access Count"

=> 테이블로 만들어 놓은 것을 차트화 시킬 수 있음

=> 차트 모양도 바꿀 수 있고, 형식, 격자 레이아웃도 사용할 수 있음

 

[사내망의 로그들에 대해서]

HTTP 로그를 분석하여 이상징후를 탐색

DNS 로그를 분석하여 이상징후를 탐색

EndPoint 로그를 분석하여 이상징후를 탐색

=> 비교분석 명령어와 다중문자열과 시간 명령어를 엄청 많이 쓰게 됨


eval

- 검사 결과 값의 변환, 검증을 수행하며 함수 실행 결괏값을 반환

 

ex) eval status_code=if(status==200, "OK", "Error")

=> if 조건문(status가 200이면 OK 출력, 아니면 Error status_code에 저장)

 

ex) eval list="mozilla"

=> list(필드명X, 변수명O)

=> 변수명 앞에는 eval이 있음

 

case(X,"Y", ...)

- 여러 개 조건을 검증할 때 사용

- 두 개의 인자가 한 그룹으로 동작

 

ex) eval description=case(error==404, "Not found", error==500, "internal Server Error")

=> error가 404면 Not found를, 500이면 Internal Server Error를 descripsion 변수에 넣음

 

ex) eval quarter=case(date_month==“January”, “1Q”, date_month==“April”, “2Q”)

=> date_month가 January이면 1Q를,  April이면 2Q를 quarter 변수에 넣음

 

cidrmatch("X",Y)

- Y가 네트워크 범위 X에 존재하는지 확인

- 반환값은 참/거짓

 

ex) eval local=cidrmatch(“10.0.0.0/8”, “10.10.0.100”)

=> 10.10.0.100이 10.0.0.0/8 대역에 포함되므로 True 반환

 

ex) | where (cidrmatch(“10.0.0.0/8”, ip) OR (cidrmatch(“172.16.0.0/12”, ip) OR (cidrmatch(“192.16.0.0/16”, ip)

=> ip가 주어지진 않았지만 ip가 X 범위에 포함된다면 True 반환, 3가지 값을 OR 연산을 해서 최종 참/거짓 반환

 

if(X,Y,Z)

- X가 참이면 Y, 거짓이면 Z 실행

ex) | eval ip1="10.10.0.100", ip2="100.10.0.100" | eval network1=if(cidrmatch("10.10.0.0/24", ip1),"local", "external"), network2=if(cidrmatch("10.10.0.0/24", ip2),"local", "external") | table ip1, network1, ip2, network2

=> 변수에 값 저장

=> cidrmatch는 참/거짓 반환하므로 network1에는 local 저장

=> cidrmatch는 참/거짓 반환하므로 network2에는 external 저장

 

like(X,"Y")

- X필드에서 일부 문자열 Y를 검색

- X에서 Y찾기

- like 함수의 와일드 카드는 %

 

ex) …| where like(field, “addr%”)

=> 변수 field가 addr로 시작하는지 검색

 

match(X,"Y")

- like 함수는 일부가 맞으면 참을 반환하지만 match는 함수명과 정확히 일치하는지를 비교

 

ex) match(filename, “malicious.exe”)

=> filename이 malicious.exe이면 참, 아니면 거짓 반환

=> 문자열 비교에 대소문자 구분 X

 

ex) match(filename, “(.jpg|.gif|.png)$”)

=> $ 앞의 문자로 끝난다는 의미

=> | 다중 선택 의미

=> filename이 .jpg, .gif, .png로 끝나는지 확인 (or)

=> 확장자 검사

 

ex) match(method, "(GET|POST|-)")

=> method가 GET, POST, - 인지 확인 (or)


split(X,"Y")

- 구분자 Y를 이용해서 X를 분할해 다중값 형식으로 변환

- 구분자로 분리한 문자열은 여러 개의 토큰이 발생하므로 주로 mvindex()에서 사용

- 이벤트에서 특정 값을 추출할 때 사용

 

ex) split(uri,"/")

/data/utility/tool/GoogleToolbar.exe

=> data utility tool GoogleToolbar.exe

=>  [0]      [1]    [2]             [3]

 

mvindex(X,Y,Z)

- 필드 X에 있는 Y번째 값을 반환 (Z생략 가능)

- Y : 0(첫번째 값), -1(인덱스 뒤부터 시작), -2(끝에서 두번째)

- Z는 선택, Z를 지정하면 함수는 Y부터 Z까지 값을 반환

 

ex) mvindex(split(uri,"/"),-1)

/data/utility/tool/GoogleToolbar.exe

=> data utility tool GoogleToolbar.exe

=>  [0]      [1]    [2]             [3]

=>   0                -2              -1      : Y

=> 분할되는 개수가 유동적이기 때문에 인덱싱 값을 유추하기 어려움

=> 그래서 첫번째(0) 또는 가장 마지막 위치(-1) 또는 마지막에서 2번째 위치(-2) 이렇게 원하는 위치를 뽑을 수 있음

 

substr(X,Y,Z)

- 세번째 인자 Z가 없다면 필드 X의 Y부터 문자열 끝까지 반환

- Z가 주어지면 Y부터 Z개의 문자열 반환

 

ex) *| eval passwd_str="lightdm:x:107:117:Light Display M a n a g e r :/var/lib/lightdm:/bin/false"

| eval uid=mvindex(split(passwd_str,":"),0)

| eval subuid1=substr(uid,2)

| eval subuid2=substr(uid,2,4)

| table uid, subuid1, subuid2

=> passwd_str를 : 를 기준으로 분할하여 첫번째 것을 uid에 저장

      lightdm   x   107   117   Light Display M a n a g e r    /var/lib/lightdm   /bin/false

      uid = lightdm

=> uid에서 2번째부터 문자열 끝까지 subuid1에 저장

      subuid1 = ightdm

=> uid에서 2번째부터 4개의 문자열을 subuid2에 저장

      subuid2 = ight

 

round(X,Y)

- X를 Y자릿수 기준으로 반올림

- 나누기 계산을 할 경우 소수점 자리가 급격히 늘어나는 것을 방지

 

strftime(X,Y)

- 유닉스 타임을 일반시간으로 변환

- 유닉스타임 X를 지정한 Y형식으로 출력

- 유닉스 타임(에포크 타임) 계산법은 1970년 1월 1일 0시를 기준으로 초 계산

 

striptime(X,Y)

- 일반시간을 유닉스 타임으로 변환

- Y 형식으로 된 X 시간 문자열을 입력받아 유닉스 타임을 반환