Fakultas Ilmu Komputer UI

Commit f4eefecf authored by Fata Nugraha's avatar Fata Nugraha
Browse files

Tried to claim stress testing + data seeding

parent 10a7888e
Pipeline #16359 passed with stages
in 1 minute and 46 seconds
---
layout: post
title: Automating Log Generation
date: 2019-05-02 04:00:00 +0700
author: fata
---
Karena proyek kami adalah pembuatan manajemen log, kami perlu memiliki suatu mekanisme untuk
men-generate log yang akan digunakan untuk proses development.
<!--more-->
Kami membuat service baru untuk melakukan hal ini. Service ini disamakan dengan environment
deployment yaitu berisi Snort (sebagai IDS) dan Barnyard2 (sebagai spooler).
Secara garis besar cara service ini bekerja adalah buat log, simpan sebagai format `pcap`, dan
jalankan `snort` untuk membaca `pcap` tersebut, lalu `barnyard2` akan mengirim log dan dump packet
yang mentrigger rule dari `snort`.
Langkah pertama, yaitu kami harus membuat packet network yang mentrigger rule dari snort. Untuk
pekerjaan ini kami menggunakan library bernama `scapy`. Salah satu packet yang di-generate menggunakan
scapy untuk mentrigger event "OS-LINUX x86 Linux mountd overflow" sebagai berikut:
```py
class Attack:
source = None
dest = None
def __init__(self, source, dest):
self.source, self.dest = source, dest
def as_packet(self):
ether = Ether(dst=self.dest.mac_address, src=self.source.mac_address)
ip = IP(src=self.source.ip_address, dst=self.dest.ip_address)
return ether / ip
class ExploitAttack(Attack):
# OS-LINUX x86 Linux mountd overflow (exploit.rules)
def as_packet(self):
return (
super().as_packet()
/ UDP(sport=42000, dport=635)
/ Raw(load=b"\xEBV^VVV1\xD2\x88V\x0B\x88V\x1E")
)
```
Langkah kedua cukup simpan log ini sebagai pcap, lalu jalankan snort untuk membaca pcap tersebut.
```py
def read_pcap(pcap):
key = os.urandom(20).hex()
log_dirname = "/log/%s/" % key
os.makedirs(log_dirname)
pcap_file_name = os.path.join(log_dirname, "log.pcap")
pcap.save(pcap_file_name)
snort = subprocess.Popen(
[
"snort",
"-de",
"-r",
pcap_file_name,
"-l",
log_dirname,
"-c",
"/etc/snort/snort.conf",
"-h",
'["172.61.0.0/16"]',
],
stdout=subprocess.PIPE,
)
snort.wait()
# ...snip...
```
Langkah ketiga, jalankan spooler `Barnyard2` untuk mengirim log.
```py
# ...snip...
barnyard2 = subprocess.Popen(
[
"barnyard2",
"-c",
"/etc/barnyard2/barnyard2.conf",
"-o",
os.path.join(log_dirname, "snort.log"),
],
stdout=subprocess.PIPE,
)
barnyard2.wait()
```
Hasil:
![frontend](/assets/images/2019-05-02-automating-log-generation/screenshot.png)
Namun, hal ini tidak cukup untuk mensimulasikan keadaan dunia nyata, dimana setiap saat
ada log yang digenerate. Maka yang kami lakukan adalah mengotomasi pembuatan log diatas
dengan membuat satu thread yang membuat log setiap detik.
Masalah pertama yang kami hadapi untuk mengotomasi pembuatan log adalah cukup lamanya
waktu yang dibutuhkan untuk menjalankan snort dan barnyard, maka untuk mengotomasi
kami tidak menggunakan snort dan barnyard, namun langsung mengirim log ke service
logstash dengan bantuan library `socket`.
```py
class Generator(threading.Thread):
# ...snip...
def generate_random_logs(self):
for i in range(random.randint(*self.event_per_round)):
src = Host(ip_generator())
dest = Host("172.20.1." + str(random.randint(1, 254)))
packet = RandomAttack(src, dest).as_packet()
now = datetime.utcnow().replace(tzinfo=timezone.utc)
alert = alert_generator()
yield BarnyardLog(
now,
alert["priority"],
alert["gid"],
alert["sid"],
1,
alert["class_type"],
"log-generator-1",
alert["msg"],
packet,
)
def send_logs(self, logs):
for log in logs:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((self.receiver_host, self.receiver_port))
s.send(log.to_representation() + b"\n")
s.close()
def run(self):
while not self.stopped:
logs = self.generate_random_logs()
self.send_logs(logs)
time.sleep(max(0.05, random.random() * self.max_sleep))
# ...snip...
```
Selain itu karena kami harus mengirim log dengan format barnyard, kami harus
membuat log serializer yang menyerupai format barnyard2 yang kami gunakan (format syslog).
```py
class BarnyardLog(object):
def __init__(
self, timestamp, priority, gid, sid, rev, class_type, sensor_name, msg, packet
):
self.timestamp = timestamp.astimezone(tz=timezone.utc)
self.priority = priority
self.gid = gid
self.sid = sid
self.rev = rev
self.class_type = class_type
self.msg = msg
self.packet = packet
self.sensor_name = sensor_name
def get_header(self):
timestamp = re.sub(r"\.\d*\+00:00", "Z", self.timestamp.isoformat())
return f"<68> {timestamp} {self.sensor_name}"
def get_preamble(self):
return f"[SNORTIDS[LOG]: [{self.sensor_name}] ]"
def get_snort_header(self):
timestamp = self.timestamp.isoformat().replace("T", " ")
timestamp = re.sub(r"\d{3}\+00:00", "+000", timestamp)
return (
f"{timestamp} {self.priority} [{self.gid}:{self.sid}:{self.rev}] {self.msg}"
)
def get_class_type(self):
return self.class_type
def get_packet_dump(self):
packet = self.packet.__class__(bytes(self.packet))
return dump_packet(packet)
def to_representation(self):
fields = [
self.get_preamble(),
self.get_snort_header(),
self.get_class_type(),
*self.get_packet_dump(),
]
result = " || ".join(fields)
return f"{self.get_header()} | {result} |".encode()
```
Dengan otomasi ini, selain untuk men-seed data yang cukup berkualitas, dapat kami gunakan juga
untuk melakukan stress testing pada keseluruhan sistem dengan mengontrol berapa banyak log yang dikirim
tiap detik.
......@@ -9,6 +9,8 @@ Pemilihan design pattern yang tepat membuat solusi dari permasalahan semakin ele
Dalam post ini akan dibahas penggunaan pattern Observer dan Chain of Responsibility pada fitur
Realtime World Map dalam proyek kami.
![visualisation](/assets/images/2019-05-02-design-patterns/visualisation.png)
<!--more-->
## Observer
......@@ -37,8 +39,6 @@ Observer cukup menunggu adanya perubahan yang diterima oleh subject dan menampil
sesuai log yang dikirimkan oleh subject. Untuk menampilkan visualisasi yang berbeda beda kami
menggunakan pattern selanjutnya yaitu Chain of Responsibility
![visualisation](/assets/images/2019-05-02-design-patterns/visualisation.png)
## Chain of Responsibility
Dalam fitur ini kita baru memiliki 5 jenis visualisasi. Yaitu satu peta dan 4 widget yang menampilkan
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment