์šฐ๋ฆฌ๋Š” ELK์™€ Exchange์™€ ์นœ๊ตฌ์ž…๋‹ˆ๋‹ค. 2 ๋ถ€

์šฐ๋ฆฌ๋Š” ELK์™€ Exchange์™€ ์นœ๊ตฌ์ž…๋‹ˆ๋‹ค. 2 ๋ถ€

Exchange์™€ ELK ์นœ๊ตฌ๋ฅผ ์‚ฌ๊ท€๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋ฅผ ๊ณ„์†ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—). ์ด ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋งค์šฐ ๋งŽ์€ ์ˆ˜์˜ ๋กœ๊ทธ๋ฅผ ์ฃผ์ € ์—†์ด ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ƒ๊ธฐ์‹œ์ผœ ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” Exchange๊ฐ€ Logstash ๋ฐ Kibana ๊ตฌ์„ฑ ์š”์†Œ์™€ ์ž‘๋™ํ•˜๋„๋ก ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ELK ์Šคํƒ์˜ Logstash๋Š” ๋กœ๊ทธ๋ฅผ ์ง€๋Šฅ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋ฌธ์„œ ํ˜•์‹์œผ๋กœ Elastic์— ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ค€๋น„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ, ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ Kibana์—์„œ ๋‹ค์–‘ํ•œ ์‹œ๊ฐํ™”๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์ด ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์„ค์น˜

๋‘ ๋‹จ๊ณ„๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  • OpenJDK ํŒจํ‚ค์ง€ ์„ค์น˜ ๋ฐ ๊ตฌ์„ฑ
  • Logstash ํŒจํ‚ค์ง€ ์„ค์น˜ ๋ฐ ๊ตฌ์„ฑ

OpenJDK ํŒจํ‚ค์ง€ ์„ค์น˜ ๋ฐ ๊ตฌ์„ฑ

OpenJDK ํŒจํ‚ค์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜์—ฌ ํŠน์ • ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์••์ถ•์„ ํ’€์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ๊ฒฝ๋กœ๋ฅผ Windows ์šด์˜ ์ฒด์ œ์˜ $env:Path ๋ฐ $env:JAVA_HOME ๋ณ€์ˆ˜์— ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ELK์™€ Exchange์™€ ์นœ๊ตฌ์ž…๋‹ˆ๋‹ค. 2 ๋ถ€

์šฐ๋ฆฌ๋Š” ELK์™€ Exchange์™€ ์นœ๊ตฌ์ž…๋‹ˆ๋‹ค. 2 ๋ถ€

Java ๋ฒ„์ „์„ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

PS C:> java -version
openjdk version "13.0.1" 2019-10-15
OpenJDK Runtime Environment (build 13.0.1+9)
OpenJDK 64-Bit Server VM (build 13.0.1+9, mixed mode, sharing)

Logstash ํŒจํ‚ค์ง€ ์„ค์น˜ ๋ฐ ๊ตฌ์„ฑ

Logstash ๋ฐฐํฌํŒ์ด ํฌํ•จ๋œ ์•„์นด์ด๋ธŒ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ ๋”ฐ๋ผ์„œ. ์•„์นด์ด๋ธŒ๋Š” ๋””์Šคํฌ ๋ฃจํŠธ์— ์••์ถ•์„ ํ’€์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํด๋”์— ์••์ถ• ํ’€๊ธฐ C:Program Files ๊ทธ๋Ÿด ๊ฐ€์น˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. Logstash๋Š” ์ •์ƒ์ ์œผ๋กœ ์‹œ์ž‘์„ ๊ฑฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํŒŒ์ผ์— ๋“ค์–ด๊ฐ€์•ผํ•ฉ๋‹ˆ๋‹ค jvm.options Java ํ”„๋กœ์„ธ์Šค์— RAM ํ• ๋‹น์„ ๋‹ด๋‹นํ•˜๋Š” ์ˆ˜์ • ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„ RAM์˜ ์ ˆ๋ฐ˜์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋ณด๋“œ์— 16GB RAM์ด ์žˆ๋Š” ๊ฒฝ์šฐ ๊ธฐ๋ณธ ํ‚ค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

-Xms1g
-Xmx1g

๋‹ค์Œ์œผ๋กœ ๊ต์ฒดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

-Xms8g
-Xmx8g

๋˜ํ•œ ํ•ด๋‹น ํ–‰์„ ์ฃผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. -XX:+UseConcMarkSweepGC. ๋” ์•Œ์•„๋ณด๊ธฐ ์—ฌ๊ธฐ์—. ๋‹ค์Œ ๋‹จ๊ณ„๋Š” logstash.conf ํŒŒ์ผ์— ๊ธฐ๋ณธ ๊ตฌ์„ฑ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

input {
 stdin{}
}
 
filter {
}
 
output {
 stdout {
 codec => "rubydebug"
 }
}

์ด ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด Logstash๋Š” ์ฝ˜์†”์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ์ด๋ฅผ ๋นˆ ํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด ์ „๋‹ฌํ•œ ํ›„ ๋‹ค์‹œ ์ฝ˜์†”์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด Logstash์˜ ๊ธฐ๋Šฅ์ด ํ…Œ์ŠคํŠธ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๋Œ€ํ™”ํ˜• ๋ชจ๋“œ์—์„œ ์‹คํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

PS C:...bin> .logstash.bat -f .logstash.conf
...
[2019-12-19T11:15:27,769][INFO ][logstash.javapipeline    ][main] Pipeline started {"pipeline.id"=>"main"}
The stdin plugin is now waiting for input:
[2019-12-19T11:15:27,847][INFO ][logstash.agent           ] Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[2019-12-19T11:15:28,113][INFO ][logstash.agent           ] Successfully started Logstash API endpoint {:port=>9600}

Logstash๋Š” ํฌํŠธ 9600์—์„œ ์„ฑ๊ณต์ ์œผ๋กœ ์‹œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰ ์„ค์น˜ ๋‹จ๊ณ„: Logstash๋ฅผ Windows ์„œ๋น„์Šค๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. NSSM:

PS C:...bin> .nssm.exe install logstash
Service "logstash" installed successfully!

๊ฒฐํ•จ ํ—ˆ์šฉ

์›๋ณธ ์„œ๋ฒ„์—์„œ ์ „์†ก๋  ๋•Œ ๋กœ๊ทธ์˜ ์•ˆ์ „์„ฑ์€ ์˜๊ตฌ ๋Œ€๊ธฐ์—ด ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ์˜ํ•ด ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค.

์›๋ฆฌ

๋กœ๊ทธ ์ฒ˜๋ฆฌ ์ค‘ ๋Œ€๊ธฐ์—ด์˜ ๋ ˆ์ด์•„์›ƒ์€ ์ž…๋ ฅ โ†’ ๋Œ€๊ธฐ์—ด โ†’ ํ•„ํ„ฐ + ์ถœ๋ ฅ์ž…๋‹ˆ๋‹ค.

์ž…๋ ฅ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ๋กœ๊ทธ ์†Œ์Šค๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ์ด๋ฅผ ํ์— ์“ด ๋‹ค์Œ ๋ฐ์ดํ„ฐ๊ฐ€ ์†Œ์Šค์— ์ˆ˜์‹ ๋˜์—ˆ๋‹ค๋Š” ํ™•์ธ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

๋Œ€๊ธฐ์—ด์˜ ๋ฉ”์‹œ์ง€๋Š” Logstash์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋˜๊ณ  ํ•„ํ„ฐ์™€ ์ถœ๋ ฅ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ†ตํ•ด ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ์ถœ๋ ฅ์—์„œ ๋กœ๊ทธ๊ฐ€ ์ „์†ก๋˜์—ˆ๋‹ค๋Š” ํ™•์ธ์„ ๋ฐ›์œผ๋ฉด Logstash๋Š” ํ์—์„œ ์ฒ˜๋ฆฌ๋œ ๋กœ๊ทธ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. Logstash๊ฐ€ ์ค‘์ง€๋˜๋ฉด ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ๋ชจ๋“  ๋ฉ”์‹œ์ง€์™€ ํ™•์ธ์„ ๋ฐ›์ง€ ๋ชปํ•œ ๋ฉ”์‹œ์ง€๋Š” ๋Œ€๊ธฐ์—ด์— ๋‚จ์•„ ์žˆ์œผ๋ฉฐ Logstash๋Š” ๋‹ค์Œ์— ์‹œ์ž‘ํ•  ๋•Œ ํ•ด๋‹น ๋ฉ”์‹œ์ง€๋ฅผ ๊ณ„์† ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์กฐ์ •

ํŒŒ์ผ์˜ ํ‚ค๋กœ ์กฐ์ • ๊ฐ€๋Šฅ C:Logstashconfiglogstash.yml:

  • queue.type: (๊ฐ€๋Šฅํ•œ ๊ฐ’ โ€‹โ€‹- persisted ะธ memory (default)).
  • path.queue: (๊ธฐ๋ณธ์ ์œผ๋กœ C:Logstashqueue์— ์ €์žฅ๋˜๋Š” ๋Œ€๊ธฐ์—ด ํŒŒ์ผ์ด ์žˆ๋Š” ํด๋” ๊ฒฝ๋กœ).
  • queue.page_capacity: (์ตœ๋Œ€ ๋Œ€๊ธฐ์—ด ํŽ˜์ด์ง€ ํฌ๊ธฐ, ๊ธฐ๋ณธ๊ฐ’์€ 64MB).
  • queue.drain: (true/false - Logstash๋ฅผ ์ข…๋ฃŒํ•˜๊ธฐ ์ „์— ๋Œ€๊ธฐ์—ด ์ฒ˜๋ฆฌ ์ค‘์ง€๋ฅผ ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ํ™œ์„ฑํ™”ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์„œ๋ฒ„ ์ข…๋ฃŒ ์†๋„์— ์ง์ ‘์ ์ธ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.)
  • queue.max_events: (ํ์˜ ์ตœ๋Œ€ ์ด๋ฒคํŠธ ์ˆ˜, ๊ธฐ๋ณธ๊ฐ’์€ 0(๋ฌด์ œํ•œ)).
  • queue.max_bytes: (์ตœ๋Œ€ ๋Œ€๊ธฐ์—ด ํฌ๊ธฐ(๋ฐ”์ดํŠธ), ๊ธฐ๋ณธ๊ฐ’ - 1024mb(1gb)).

๊ตฌ์„ฑ๋œ ๊ฒฝ์šฐ queue.max_events ะธ queue.max_bytes์„ ์„ ํƒํ•˜๋ฉด ์ด๋Ÿฌํ•œ ์„ค์ • ๊ฐ’์— ๋„๋‹ฌํ•˜๋ฉด ๋ฉ”์‹œ์ง€๊ฐ€ ๋Œ€๊ธฐ์—ด์— ๋” ์ด์ƒ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ง€์† ๋Œ€๊ธฐ์—ด์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ ์—ฌ๊ธฐ์—.

๋Œ€๊ธฐ์—ด ์„ค์ •์„ ๋‹ด๋‹นํ•˜๋Š” logstash.yml ๋ถ€๋ถ„์˜ ์˜ˆ:

queue.type: persisted
queue.max_bytes: 10gb

์กฐ์ •

Logstash ๊ตฌ์„ฑ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ˆ˜์‹  ๋กœ๊ทธ ์ฒ˜๋ฆฌ์˜ ๋‹ค์–‘ํ•œ ๋‹จ๊ณ„, ์ฆ‰ ์ˆ˜์‹ (์ž…๋ ฅ ์„น์…˜), ๊ตฌ๋ฌธ ๋ถ„์„(ํ•„ํ„ฐ ์„น์…˜), Elastic์œผ๋กœ ์ „์†ก(์ถœ๋ ฅ ์„น์…˜)์„ ๋‹ด๋‹นํ•˜๋Š” ์„ธ ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์—์„œ๋Š” ๊ฐ๊ฐ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž…๋ ฅ

Filebeat ์—์ด์ „ํŠธ๋กœ๋ถ€ํ„ฐ ์›์‹œ ๋กœ๊ทธ๊ฐ€ ํฌํ•จ๋œ ์ˆ˜์‹  ์ŠคํŠธ๋ฆผ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ž…๋ ฅ ์„น์…˜์— ํ‘œ์‹œ๋˜๋Š” ๊ฒƒ์€ ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์ž…๋‹ˆ๋‹ค.

input {
  beats {
    port => 5044
  }
}

์ด ๊ตฌ์„ฑ ํ›„์— Logstash๋Š” ํฌํŠธ 5044๋ฅผ ์ˆ˜์‹ ํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๊ณ  ๋กœ๊ทธ๋ฅผ ์ˆ˜์‹ ํ•  ๋•Œ ํ•„ํ„ฐ ์„น์…˜์˜ ์„ค์ •์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ฒฝ์šฐ SSL์˜ filebit์—์„œ ๋กœ๊ทธ๋ฅผ ์ˆ˜์‹ ํ•˜๊ธฐ ์œ„ํ•ด ์ฑ„๋„์„ ๋ž˜ํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Beats ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ค์ •์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด์„ธ์š”. ์—ฌ๊ธฐ์—.

ํ•„ํ„ฐ

์ฒ˜๋ฆฌ์— ๊ด€์‹ฌ์ด ์žˆ๋Š” Exchange์—์„œ ์ƒ์„ฑํ•˜๋Š” ๋ชจ๋“  ํ…์ŠคํŠธ ๋กœ๊ทธ๋Š” ๋กœ๊ทธ ํŒŒ์ผ ์ž์ฒด์— ์„ค๋ช…๋œ ํ•„๋“œ๊ฐ€ ์žˆ๋Š” csv ํ˜•์‹์ž…๋‹ˆ๋‹ค. csv ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ธฐ ์œ„ํ•ด Logstash๋Š” ์„ธ ๊ฐ€์ง€ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋ถ€ํ•˜๋‹ค, csv ๋ฐ grok. ์ฒซ ๋ฒˆ์งธ๊ฐ€ ๊ฐ€์žฅ ะฑั‹ัั‚ั€ั‹ะน, ๊ทธ๋Ÿฌ๋‚˜ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋กœ๊ทธ๋งŒ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๋Š” ๋ฐ ๋Œ€์ฒ˜ํ•ฉ๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ ๋ ˆ์ฝ”๋“œ๋ฅผ ๋‘ ๊ฐœ๋กœ ๋ถ„ํ• ํ•ฉ๋‹ˆ๋‹ค(ํ•„๋“œ ๋‚ด๋ถ€์— ์‰ผํ‘œ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—). ์ด๋กœ ์ธํ•ด ๋กœ๊ทธ๊ฐ€ ์ž˜๋ชป ๊ตฌ๋ฌธ ๋ถ„์„๋ฉ๋‹ˆ๋‹ค.

โ€ฆ,"MDB:GUID1, Mailbox:GUID2, Event:526545791, MessageClass:IPM.Note, CreationTime:2020-05-15T12:01:56.457Z, ClientType:MOMT, SubmissionAssistant:MailboxTransportSubmissionEmailAssistant",โ€ฆ

์˜ˆ๋ฅผ ๋“ค์–ด IIS์™€ ๊ฐ™์€ ๋กœ๊ทธ๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ํ•„ํ„ฐ ์„น์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

filter {
  if "IIS" in [tags] {
    dissect {
      mapping => {
        "message" => "%{date} %{time} %{s-ip} %{cs-method} %{cs-uri-stem} %{cs-uri-query} %{s-port} %{cs-username} %{c-ip} %{cs(User-Agent)} %{cs(Referer)} %{sc-status} %{sc-substatus} %{sc-win32-status} %{time-taken}"
      }
      remove_field => ["message"]
      add_field => { "application" => "exchange" }
    }
  }
} 

Logstash ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์กฐ๊ฑด๋ฌธ, ๋”ฐ๋ผ์„œ filebeat ํƒœ๊ทธ๊ฐ€ ์ง€์ •๋œ ๋กœ๊ทธ๋งŒ dissect ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. IIS. ํ”Œ๋Ÿฌ๊ทธ์ธ ๋‚ด์—์„œ ํ•„๋“œ ๊ฐ’์„ ์ด๋ฆ„๊ณผ ์ผ์น˜์‹œํ‚ค๊ณ  ์›๋ž˜ ํ•„๋“œ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. message, ๋กœ๊ทธ ํ•ญ๋ชฉ์ด ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ, ์˜ˆ๋ฅผ ๋“ค์–ด ๋กœ๊ทธ๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ด๋ฆ„์„ ํฌํ•จํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋กœ๊ทธ๋ฅผ ์ถ”์ ํ•˜๋Š” ๊ฒฝ์šฐ csv ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์œผ๋ฉฐ ๋ณต์žกํ•œ ํ•„๋“œ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

filter {
  if "Tracking" in [tags] {
    csv {
      columns => ["date-time","client-ip","client-hostname","server-ip","server-hostname","source-context","connector-id","source","event-id","internal-message-id","message-id","network-message-id","recipient-address","recipient-status","total-bytes","recipient-count","related-recipient-address","reference","message-subject","sender-address","return-path","message-info","directionality","tenant-id","original-client-ip","original-server-ip","custom-data","transport-traffic-type","log-id","schema-version"]
      remove_field => ["message", "tenant-id", "schema-version"]
      add_field => { "application" => "exchange" }
    }
}

ํ”Œ๋Ÿฌ๊ทธ์ธ ๋‚ด์—์„œ ํ•„๋“œ ๊ฐ’์„ ์ด๋ฆ„๊ณผ ์ผ์น˜์‹œํ‚ค๊ณ  ์›๋ž˜ ํ•„๋“œ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. message (๋˜ํ•œ ํ•„๋“œ tenant-id ะธ schema-version)์—๋Š” ๋กœ๊ทธ ํ•ญ๋ชฉ์ด ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ, ์˜ˆ๋ฅผ ๋“ค์–ด ๋กœ๊ทธ๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ด๋ฆ„์ด ํฌํ•จ๋˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•„ํ„ฐ๋ง ๋‹จ๊ณ„๋ฅผ ์ข…๋ฃŒํ•˜๋ฉด Kibana์—์„œ ์‹œ๊ฐํ™”ํ•  ์ค€๋น„๊ฐ€ ๋œ ์ฒซ ๋ฒˆ์งธ ๊ทผ์‚ฌ์น˜์˜ ๋ฌธ์„œ๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์‚ฌํ•ญ์ด ๋ˆ„๋ฝ๋ฉ๋‹ˆ๋‹ค.

  • ์ˆซ์ž ํ•„๋“œ๋Š” ํ…์ŠคํŠธ๋กœ ์ธ์‹๋˜๋ฏ€๋กœ ํ•ด๋‹น ํ•„๋“œ์— ๋Œ€ํ•œ ์ž‘์—…์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ํ•„๋“œ time-taken IIS ๋กœ๊ทธ ๋ฐ ํ•„๋“œ recipient-count ะธ total-bites ๋กœ๊ทธ ์ถ”์ .
  • ํ‘œ์ค€ ๋ฌธ์„œ ํƒ€์ž„์Šคํƒฌํ”„์—๋Š” ๋กœ๊ทธ๊ฐ€ ์„œ๋ฒ„ ์ธก์— ๊ธฐ๋ก๋œ ์‹œ๊ฐ„์ด ์•„๋‹ˆ๋ผ ๋กœ๊ทธ๊ฐ€ ์ฒ˜๋ฆฌ๋œ ์‹œ๊ฐ„์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
  • ๋ถ„์•ผ recipient-address ํŽธ์ง€ ์ˆ˜์‹ ์ž๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ถ„์„์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ํ•˜๋‚˜์˜ ๊ฑด์„ค ํ˜„์žฅ์ฒ˜๋Ÿผ ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ œ ๋กœ๊ทธ ์ฒ˜๋ฆฌ ํ”„๋กœ์„ธ์Šค์— ์•ฝ๊ฐ„์˜ ๋งˆ๋ฒ•์„ ์ถ”๊ฐ€ํ•  ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.

์ˆซ์ž ํ•„๋“œ ๋ณ€ํ™˜

ํ•ด๋ถ€ ํ”Œ๋Ÿฌ๊ทธ์ธ์—๋Š” ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค convert_datatype, ํ…์ŠคํŠธ ํ•„๋“œ๋ฅผ ๋””์ง€ํ„ธ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

dissect {
  โ€ฆ
  convert_datatype => { "time-taken" => "int" }
  โ€ฆ
}

์ด ๋ฐฉ๋ฒ•์€ ํ•„๋“œ์— ํ™•์‹คํžˆ ๋ฌธ์ž์—ด์ด ํฌํ•จ๋  ๊ฒฝ์šฐ์—๋งŒ ์ ํ•ฉํ•˜๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์€ ํ•„๋“œ์˜ Null ๊ฐ’์„ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉฐ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

๋กœ๊ทธ๋ฅผ ์ถ”์ ํ•˜๋ ค๋ฉด ์œ ์‚ฌํ•œ ๋ณ€ํ™˜ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. recipient-count ะธ total-bites ๋น„์–ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ•„๋“œ๋ฅผ ๋ณ€ํ™˜ํ•˜๋ ค๋ฉด ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค ๋Œ์—ฐ๋ณ€์ด:

mutate {
  convert => [ "total-bytes", "integer" ]
  convert => [ "recipient-count", "integer" ]
}

receive_address๋ฅผ ๊ฐœ๋ณ„ ์ˆ˜์‹ ์ž๋กœ ๋ถ„ํ• 

์ด ๋ฌธ์ œ๋Š” mutate ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

mutate {
  split => ["recipient_address", ";"]
}

ํƒ€์ž„์Šคํƒฌํ”„ ๋ณ€๊ฒฝ

๋กœ๊ทธ ์ถ”์ ์˜ ๊ฒฝ์šฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ๋งค์šฐ ์‰ฝ๊ฒŒ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ, ์ด๋Š” ํ˜„์žฅ์—์„œ ๊ธ€์„ ์“ฐ๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. timestamp ํ•„๋“œ์—์„œ ํ•„์š”ํ•œ ํ˜•์‹์œผ๋กœ ๋‚ ์งœ ๋ฐ ์‹œ๊ฐ„ date-time:

date {
  match => [ "date-time", "ISO8601" ]
  timezone => "Europe/Moscow"
  remove_field => [ "date-time" ]
}

IIS ๋กœ๊ทธ์˜ ๊ฒฝ์šฐ ํ•„๋“œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒฐํ•ฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. date ะธ time mutate ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•œ ์‹œ๊ฐ„๋Œ€๋ฅผ ๋“ฑ๋กํ•˜๊ณ  ์ด ํƒ€์ž„์Šคํƒฌํ”„๋ฅผ timestamp ๋‚ ์งœ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜์—ฌ:

mutate { 
  add_field => { "data-time" => "%{date} %{time}" }
  remove_field => [ "date", "time" ]
}
date { 
  match => [ "data-time", "YYYY-MM-dd HH:mm:ss" ]
  timezone => "UTC"
  remove_field => [ "data-time" ]
}

์‚ฐ์ถœ

์ถœ๋ ฅ ์„น์…˜์€ ์ฒ˜๋ฆฌ๋œ ๋กœ๊ทธ๋ฅผ ๋กœ๊ทธ ์ˆ˜์‹ ์ž์—๊ฒŒ ๋ณด๋‚ด๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. Elastic์œผ๋กœ ์ง์ ‘ ์ „์†กํ•˜๋Š” ๊ฒฝ์šฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํƒ„์„ฑ ๊ฒ€์ƒ‰, ์ƒ์„ฑ๋œ ๋ฌธ์„œ๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•œ ์„œ๋ฒ„ ์ฃผ์†Œ ๋ฐ ์ธ๋ฑ์Šค ์ด๋ฆ„ ํ…œํ”Œ๋ฆฟ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

output {
  elasticsearch {
    hosts => ["127.0.0.1:9200", "127.0.0.2:9200"]
    manage_template => false
    index => "Exchange-%{+YYYY.MM.dd}"
  }
}

์ตœ์ข… ๊ตฌ์„ฑ

์ตœ์ข… ๊ตฌ์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

input {
  beats {
    port => 5044
  }
}
 
filter {
  if "IIS" in [tags] {
    dissect {
      mapping => {
        "message" => "%{date} %{time} %{s-ip} %{cs-method} %{cs-uri-stem} %{cs-uri-query} %{s-port} %{cs-username} %{c-ip} %{cs(User-Agent)} %{cs(Referer)} %{sc-status} %{sc-substatus} %{sc-win32-status} %{time-taken}"
      }
      remove_field => ["message"]
      add_field => { "application" => "exchange" }
      convert_datatype => { "time-taken" => "int" }
    }
    mutate { 
      add_field => { "data-time" => "%{date} %{time}" }
      remove_field => [ "date", "time" ]
    }
    date { 
      match => [ "data-time", "YYYY-MM-dd HH:mm:ss" ]
      timezone => "UTC"
      remove_field => [ "data-time" ]
    }
  }
  if "Tracking" in [tags] {
    csv {
      columns => ["date-time","client-ip","client-hostname","server-ip","server-hostname","source-context","connector-id","source","event-id","internal-message-id","message-id","network-message-id","recipient-address","recipient-status","total-bytes","recipient-count","related-recipient-address","reference","message-subject","sender-address","return-path","message-info","directionality","tenant-id","original-client-ip","original-server-ip","custom-data","transport-traffic-type","log-id","schema-version"]
      remove_field => ["message", "tenant-id", "schema-version"]
      add_field => { "application" => "exchange" }
    }
    mutate {
      convert => [ "total-bytes", "integer" ]
      convert => [ "recipient-count", "integer" ]
      split => ["recipient_address", ";"]
    }
    date {
      match => [ "date-time", "ISO8601" ]
      timezone => "Europe/Moscow"
      remove_field => [ "date-time" ]
    }
  }
}
 
output {
  elasticsearch {
    hosts => ["127.0.0.1:9200", "127.0.0.2:9200"]
    manage_template => false
    index => "Exchange-%{+YYYY.MM.dd}"
  }
}

์œ ์šฉํ•œ ๋งํฌ :

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€