Kami mengumpulkan log firewall Mikrotik dalam database

Selamat siang

Saya ingin memberi tahu Anda betapa mudah dan alami Anda dapat mengonfigurasi server pengumpulan metadata lalu lintas jaringan untuk router Mikrotik.

Tujuan: Tujuannya adalah untuk menyimpan log firewall "dikunyah" dalam database untuk analisis lebih lanjut.

Berarti: Setiap distribusi Linux baru dengan rsyslogd v8 dan lebih tinggi cocok untuk implementasi, mungkin sintaks yang diusulkan akan bekerja pada v7 juga. Kami juga membutuhkan DBMS, saya memilih mariadb. Pertumbuhan basis data akan bervariasi dari jumlah aturan yang dicatat, karena ukuran drive sesuai keinginan Anda, dalam kasus saya, 30-40 aturan dicatat, yaitu sekitar 1200 ribu baris per hari. Selama bulan menggunakan database, termasuk indeks, itu tumbuh menjadi 3,8 GB.

Mekanika: Router mengirim log ke server jauh melalui UDP. Dengan menggunakan ekspresi reguler, server rsyslog membersihkan serangkaian informasi yang tidak perlu, menghasilkan insert SQL dan mengirimkannya ke DBMS. DBMS, menggunakan pemicu sebelum penyisipan, melakukan pembersihan tambahan dan pemisahan bidang yang tidak dapat diuraikan dalam rsyslog.

Konfigurasikan RSYSLOG


Mengedit file /etc/rsyslog.conf
Tambahkan baris berikut di sana:

module(load="ommysql") module(load="imudp") input(type="imudp" port="514") 

Dengan demikian, kami memuat modul yang diperlukan dan membuka port UDP 514.

Baris log dari Mikrotik terlihat seperti ini:

 20180927155341 BLOCKSMKNETS forward: in:ether6 - LocalTORF out:VLAN55 - RT_INET, src-mac 00:15:17:31:b8:d7, proto TCP (SYN), 192.168.0.234:2457->192.168.6.14:65535, len 60 

Seperti yang Anda lihat, banyak tambahan untuk penyimpanan dalam database dan pemilihan yang jelas akan sulit.
Secara teori, saya perlu menambahkan data seperti:

 20180927155341 ether6 VLAN5 192.168.0.234 2457 192.168.6.14 65535 00:15:17:31:b8:d7 TCP SYN forward BLOCKSMKNETS 60 

Saya tidak bisa mendapatkan baris seperti itu hanya dengan menggunakan satu rsyslog. Pelanggan tetap Rsyslog menggunakan POSIX ERE / BRE, jadi tidak ada cara untuk menerapkan fitur seperti lookahead atau lookbehind.

Ada alat yang memungkinkan Anda untuk men-debug pelanggan tetap, coba, mungkin Anda dapat memisahkan port dari alamat, serta nama antarmuka dari dalam: dan keluar:. Perlu diingat bahwa beberapa protokol olahraga dan olahraga hilang.

Secara umum, output saya adalah sebagai berikut:

 20180927155341 in:ether6 out:VLAN5 192.168.0.234:2457 192.168.6.14:65535 00:15:17:31:b8:d7 TCP (SYN) forward BLOCKSMKNETS 60 

Ada dokumentasi tentang cara memasak pelanggan tetap rsyslog.

Dalam bentuk terakhir, file konfigurasi untuk menerima log dari Mikrotik /etc/rsyslog.d/20-remote.conf akan terlihat seperti ini:

 $template tpl_traflog,"insert into traflog.traffic (datetime, inif, outif, src, dst, smac, proto, flags, chain, logpref, len) values ('%timereported:::date-mysql%', '%msg:R,ERE,0,DFLT,0:in:[a-zA-Z]+[0-9]+|in:<[a-zA-Z]+-[a-zA-Z]+>--end%', '%msg:R,ERE,0,BLANK,0:out:[a-zA-Z]+[0-9]+|out:<[a-zA-Z]+-[a-zA-Z]+>--end%', '%msg:R,ERE,0,DFLT,0:([0-9]+\.){3}[0-9]+[:]?([0-9]+)?--end%', '%msg:R,ERE,0,DFLT,1:([0-9]+\.){3}[0-9]+[:]?([0-9]+)?--end%', '%msg:R,ERE,0,BLANK:([0-f]+:){5}[0-f]+--end%', '%msg:R,ERE,0,BLANK:\b[AX]{3,4}\b--end%', '%msg:R,ERE,0,BLANK:\([AZ]+\)|\(([AZ]+\,){1,3}[AZ]+\)--end%', '%msg:R,ERE,0,DFLT:[ax]+--end%', '%msg:F,32:2%', '%msg:R,ERE,0,DFLT:[0-9]+$--end%' )",SQL if ($fromhost-ip == '192.168.0.230') and ($syslogtag contains "firewall") then {action(type="ommysql" server="localhost" serverport="3306" db="traflog" uid="rsyslogger" pwd="rsyslogger" template="tpl_traflog") stop} 

Di baris pertama, deskripsi templat (templat) adalah sebaris kode SQL untuk mentransfernya ke DBMS.
Baris kedua adalah kondisi ketika tindakan akan terjadi, yaitu catatan dalam DBMS.
Kondisinya terlihat seperti ini: jika sumber log = 192.168.0.230 ( if ($fromhost-ip == '192.168.0.230') ) Dan jika baris msg berisi "firewall" (dan ($ syslogtag berisi "firewall")), maka gunakan modul ommysql dengan parameter koneksi ( then {action(type="ommysql" server="localhost" serverport="3306" db="traflog" uid="rsyslogger" pwd="..." ) kami memanggil template tpl_traflog ( template="tpl_traflog") ), dan setelah itu kami berhenti memproses baris lebih lanjut ( stop} ).

Ada kemungkinan bahwa dalam kasus Anda ada sesuatu yang salah, itu mungkin karena nama antarmuka atau awalan log, mungkin sesuatu yang lain. Untuk debugging, kami akan melakukan yang berikut, mengomentari baris kedua, menambahkan templat baru dan dua ketentuan baru:

 $template tpl_traflog_test,"%timereported:::date-mysql% %msg:R,ERE,0,DFLT,0:in:[a-zA-Z]+[0-9]+|in:<[a-zA-Z]+-[a-zA-Z]+>--end% %msg:R,ERE,0,BLANK,0:out:[a-zA-Z]+[0-9]+|out:<[a-zA-Z]+-[a-zA-Z]+>--end% %msg:R,ERE,0,DFLT,0:([0-9]+\.){3}[0-9]+[:]?([0-9]+)?--end% %msg:R,ERE,0,DFLT,1:([0-9]+\.){3}[0-9]+[:]?([0-9]+)?--end% %msg:R,ERE,0,BLANK:([0-f]+:){5}[0-f]+--end% %msg:R,ERE,0,BLANK:\b[AX]{3,4}\b--end% %msg:R,ERE,0,BLANK:\([AZ]+\)|\(([AZ]+\,){1,3}[AZ]+\)--end% %msg:R,ERE,0,DFLT:[ax]+--end% %msg:F,32:2% %msg:R,ERE,0,DFLT:[0-9]+$--end%\n" if ($fromhost-ip == '192.168.0.230') then {action(type="omfile" file="/var/log/remote/192.168.0.230.log" )} if ($fromhost-ip == '192.168.0.230') then {action(type="omfile" file="/var/log/remote/192.168.0.230.log" template="tpl_traflog_test" ) stop} 

Mulai ulang logger.

Templat tpl_traflog_test mirip dengan tpl_traflog, tetapi tanpa SQL INSERT.

Kondisi pertama menambahkan baris yang tidak diproses% msg% ke file /var/log/remote/192.168.0.230.log, karena templat tidak ditentukan.

Kondisi kedua menambahkan baris yang diproses ke file yang sama.
Jadi akan lebih mudah untuk membandingkan.
Selanjutnya, siapkan database.

Kami menyiapkan DB


Kami akan menurunkan pengaturan DBMS, semuanya standar di sini.

Kami memulai konsol mysql dan menjalankan kode berikut:

 --   create database traflog character set utf8 collate utf8_bin; use traflog; --  create table traffic (id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, datetime DATETIME, inif VARCHAR(20), outif VARCHAR(20), src VARCHAR(21), sport INT(5), dst VARCHAR(21), dport INT(5), smac VARCHAR(17), proto VARCHAR(4), flags VARCHAR(11), chain VARCHAR(8), logpref VARCHAR(24), len INT(5)) ENGINE=MYISAM; --  create user rsyslogger@localhost identified by '...'; grant all privileges on traflog.* to rsyslogger@localhost; 

Tabel sudah siap, pengguna siap.

Sekarang tambahkan pemicu, itu akan melakukan apa yang gagal logger memisahkan alamat dari port, membersihkan nama-nama antarmuka, menghapus tanda kurung dari bendera:

 --   traffic DELIMITER // create TRIGGER delim_ip_port_flags BEFORE insert ON traffic FOR EACH ROW begin set NEW.inif = REGEXP_REPLACE ((NEW.inif), 'in:', '' ); set NEW.outif = REGEXP_REPLACE ((NEW.outif), 'out:', '' ); set NEW.sport = REGEXP_REPLACE ((NEW.src), '([0-9]+\.){3}[0-9]+:|([0-9]+\.){3}[0-9]+', '' ); set NEW.src = REGEXP_REPLACE ((NEW.src), ':[0-9]+', '' ); set NEW.dport = REGEXP_REPLACE ((NEW.dst), '([0-9]+\.){3}[0-9]+:|([0-9]+\.){3}[0-9]+', '' ); set NEW.dst = REGEXP_REPLACE ((NEW.dst), ':[0-9]+', '' ); set NEW.flags = REGEXP_REPLACE ((NEW.flags), '\\(|\\)', '' ); end // delimiter ; 

REGEXP_REPLACE mencari parameter kedua setelah titik desimal (musim reguler) dan menggantinya dengan parameter ketiga, dalam kasus kami tidak ada tanda kutip, oleh karena itu, hanya menghapus apa yang ditemukannya.

Mari kita membuat sisipan uji, mirip dengan bagaimana pencatat akan melakukan:

 --   insert into traffic (datetime, inif, outif, src, dst, smac, proto, chain, logpref) values (20180730075437, 'in:ether6', 'out:VLAN55', '192.168.0.234:4997', '192.168.6.18:65535', '00:15:17:31:b8:d7', 'TCP', '(SYN)', 'forward', 'BLOCKSMKNETS'); 

Mari kita lihat apa yang terjadi:

 select * from tarffic; 

Jika semuanya benar, maka pindah. Jika tidak, cari kesalahannya.

Tambahkan setidaknya satu indeks. Saya bukan ahli dalam membuat indeks, tetapi seperti yang saya pahami, di mysql lebih tepat menggunakan indeks dengan bidang gabungan yang berbeda untuk kueri yang berbeda, karena satu kueri hanya dapat menggunakan satu indeks (atau apakah saya salah?). Jika Anda mengerti, lakukan sesuai keinginan Anda.
Saya sering harus membuat permintaan dengan awalan tertentu, jadi saya menambahkan indeks ini:
 --  create index traffic_index on traffic (datetime,logpref,src); 

Selesai

Sekarang Anda harus mulai mengirim pada router, tambahkan pengaturan server log jauh dan bertindak untuk itu, tambahkan opsi log ke salah satu aturan firewall, tambahkan awalan tidak lebih dari 24 karakter.

Di konsol Mikrotik, tampilannya seperti ini:

 /system logging action set 3 remote=192.168.0.94 src-address=192.168.0.230 add name=remote2 remote=192.168.0.19 syslog-facility=local6 target=remote /system logging add action=remote topics=error,account,critical,event,info add action=remote2 topics=firewall /ip firewall filter ... add action=drop chain=input comment="drop ssh brute forcers" dst-port=22,8291 log=yes log-prefix=DROP_SSH_BRUTE protocol=tcp src-address-list=ssh_blacklist ... 

Di mana 192.168.0.230 adalah alamat router, 192.168.0.19 adalah alamat server log untuk log firewall, dan 192.168.0.94 adalah server log lain, saya memiliki log sistem Mikrotik di sana, kami tidak memerlukannya sekarang. Pengaturan kami adalah remote2.

Selanjutnya, lihat apa yang termasuk dalam file:

 tail -f /var/log/remote/192.168.0.230.log 

Baris dari router harus dimasukkan ke dalam file, kecuali jika aturan Anda dipicu cukup sering.

Jika beberapa bidang tidak ada, yaitu urutan datetime, inif, outif, src, dst, smac, proto, flag, chain, logpref, len tidak diikuti, maka Anda dapat mencoba mengubah parameter dalam template debugging dari logger, ganti BLANK dengan DLFT. Kemudian, alih-alih kekosongan bidang apa pun, beberapa surat akan muncul, saya tidak ingat yang mana. Jika ini terjadi, maka ada yang salah dengan jadwal reguler dan Anda harus memperbaikinya.

Jika semuanya berjalan sebagaimana mestinya, maka matikan kondisi pengujian dan templat.

Anda juga perlu menjalankan konfigurasi default di /etc/rsyslog.d/ di bawah ini, saya menamainya menjadi 50-default.conf sehingga log jarak jauh tidak dituangkan ke log sistem / var / log / message
Mulai ulang logger.

Mari kita tunggu sebentar sampai database kita penuh. Lalu kita bisa memulai seleksi.

Beberapa pertanyaan untuk contoh:

Untuk melihat ukuran basis data dan jumlah baris:
 MariaDB [traflog]> select table_schema as "database", round(sum(data_length + index_length)/1024/1024,2) as "size Mb", TABLE_ROWS as "count rows" from information_schema.tables group by table_schema; +--------------------+---------+------------+ | database | size Mb | count rows | +--------------------+---------+------------+ | information_schema | 0.17 | NULL | | traflog | 3793.39 | 21839553 | +--------------------+---------+------------+ 2 rows in set (0.48 sec) 

Hampir 4GB telah tumbuh dalam sebulan, tetapi itu tergantung pada jumlah dan properti aturan firewall yang dicatat

Jumlah awalan yang dicatat
Jumlah awalan yang dicatat tidak sama dengan jumlah aturan, beberapa aturan bekerja dengan satu awalan, tetapi masih berapa total awalan? dan berapa banyak aturan yang telah dibuat untuk mereka?:

 MariaDB [traflog]> select logpref,count(logpref) from traffic group by logpref order by count(logpref) desc; +----------------------+----------------+ | logpref | count(logpref) | +----------------------+----------------+ | ACCEPT_TORF_INET | 14582602 | | ACCEPT_SMK_PPP | 1085791 | | DROP_FORWARD_INVALID | 982374 | | REJECT_BNK01 | 961503 | | ACCEPT_MMAX_TORF | 802455 | | ACCEPT_TORF_PPP | 736803 | | SMTP_DNAT | 689533 | | ACCEPT_SMK_INET | 451411 | | ACCEPT_INET_TORF | 389857 | | BLOCK_SMKNETS | 335424 | | DROP_SMTP_BRUTE | 285850 | | ACCEPT_ROZN_TORF | 154811 | | ACCEPT_TORF_MMAX | 148393 | | DROP_ETHALL_ETHALL | 80679 | | ACCEPT_SMTP | 48921 | | DROP_SMTP_DDOS | 32190 | | RDP_DNAT | 28757 | | ACCEPT_TORF_ROZN | 18456 | | SIP_DNAT | 15494 | | 1CWEB_DNAT | 6406 | | BLOCKSMKNETS | 5789 | | DROP_SSH_BRUTE | 3162 | | POP_DNAT | 1997 | | DROP_RDP_BRUTE | 442 | | DROP_BNK01 | 291 | | DROPALL | 138 | | ACCEPT_RTP_FORWARD | 90 | | REJECT_SMTP_BRUTE | 72 | | L2TP_INPUT_ACCEPT | 33 | +----------------------+----------------+ 29 rows in set (2 min 51.03 sec) 

ACCEPT_TORF_INET berada di depan, dengan awalan ini Anda dapat menemukan semua orang yang pergi ke Internet dari jaringan lokal kami, protokol dan port dicatat, waktunya akan tiba dan akses akan ditutup untuk beberapa. Ada data referensi untuk pekerjaan bug di masa mendatang.

Pemimpin tombak Smtp
Mari kita lihat siapa yang hari ini mencoba untuk masuk ke server smtp:

 MariaDB [traflog]> select src,count(dport) from traffic where logpref='SMTP_DNAT' and datetime > '2018101600000000' group by src order by count(dport) desc limit 10; +----------------+--------------+ | src | count(dport) | +----------------+--------------+ | 191.96.249.92 | 12440 | | 191.96.249.24 | 4556 | | 191.96.249.61 | 4537 | | 185.255.31.122 | 3119 | | 178.57.79.250 | 226 | | 185.36.81.174 | 216 | | 185.234.219.32 | 211 | | 89.248.162.145 | 40 | | 45.125.66.157 | 32 | | 188.165.124.31 | 21 | +----------------+--------------+ 10 rows in set, 1 warning (21.36 sec) 

Jelas, simpul 191.96.249.92 adalah pemenang hari ini. Mari kita lihat di aturan mana dia masih muncul:

 MariaDB [traflog]> select src,dport,count(dport),logpref from traffic where src='191.96.249.92' group by logpref order by count(dport) desc; +---------------+-------+--------------+-----------------+ | src | dport | count(dport) | logpref | +---------------+-------+--------------+-----------------+ | 191.96.249.92 | 25 | 226989 | SMTP_DNAT | | 191.96.249.92 | 25 | 170714 | DROP_SMTP_BRUTE | | 191.96.249.92 | 25 | 2907 | DROP_SMTP_DDOS | | 191.96.249.92 | 25 | 2061 | ACCEPT_SMTP | +---------------+-------+--------------+-----------------+ 4 rows in set (10 min 44.21 sec) 

Yang ini mengkhususkan hanya pada smtp, ~ 1% dari hit untuk mencoba menebak kata sandi atau mencoba mengirim sampah, sisanya pergi ke pemandian.

Permintaan butuh 10 menit, ini banyak, indeks saat ini tidak cocok untuk itu, atau Anda dapat memformulasikan ulang permintaan, tetapi sekarang kami tidak akan membicarakannya.

Di masa depan, direncanakan untuk mengacaukan antarmuka web dengan kueri dan formulir standar.
Vektor diberikan, saya harap artikel ini bermanfaat.

Terima kasih semuanya!

Referensi:

Dokumentasi rsyslog
Dokumentasi Mysql
Dokumentasi logging mikrotik

Terima kasih kepada komunitas LOR untuk tipsnya.

UPD.1
Menambahkan bidang bendera ke database, sekarang Anda dapat melacak durasi koneksi dengan menangkap SYN, FIN.
Memperbaiki beberapa bug di rsyslog tetap, serta pemicu mysql.

Anehnya, aturan default defconf: drop invalid menjatuhkan semua paket akhir koneksi TCP, sebagai akibatnya, semua node yang mencoba untuk menutup koneksi dalam sains gagal, mengirim beberapa FIN. Apakah ini benar

Saya menambahkan aturan yang memungkinkan TCP traversal dengan ACK, flag FIN.

Di bawah SQL spoiler, prosedur yang menunjukkan waktu koneksi TCP dalam lima menit terakhir
koneksi_list ()
 DROP PROCEDURE IF EXISTS connections_list; DELIMITER // CREATE PROCEDURE connections_list() BEGIN DECLARE logid BIGINT UNSIGNED; DECLARE done INT DEFAULT FALSE; DECLARE datefin DATETIME; DECLARE datesyn DATETIME; DECLARE conntime TIME; DECLARE connsport INT; DECLARE conndport INT; DECLARE connsrc VARCHAR(21); DECLARE conndst VARCHAR(21); DECLARE cur CURSOR FOR SELECT id,datetime,src,sport,dst,dport FROM conn_syn_fin WHERE flags='SYN'; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE; DROP TABLE IF EXISTS conn_syn_fin; DROP TABLE IF EXISTS connless; CREATE temporary TABLE connless(datestart DATETIME,dateend DATETIME,duration TIME,src VARCHAR(21),sport INT,dst VARCHAR(21),dport INT); CREATE temporary TABLE conn_syn_fin (SELECT * from traffic WHERE datetime > now() - interval 5 minute and src in (select src from traffic where datetime > now() - interval 5 minute and logpref='TCP_FIN' and flags like '%FIN%') and (flags like '%SYN%' or flags like '%FIN%') order by id); OPEN cur; read_loop: LOOP FETCH cur INTO logid,datesyn,connsrc,connsport,conndst,conndport; IF done THEN LEAVE read_loop; END IF; set datefin=(SELECT datetime FROM conn_syn_fin WHERE id>logid and src=connsrc and sport=connsport and flags like '%FIN%' and dst=conndst and dport=conndport limit 1); set conntime=(SELECT timediff(datefin,datesyn)); INSERT INTO connless (datestart,dateend,duration,src,sport,dst,dport) value (datesyn,datefin,conntime,connsrc,connsport,conndst,conndport); END LOOP; CLOSE cur; select * from connless; END; // DELIMITER ; 


Sebagai hasil dari prosedur, dua tabel sementara akan dibuat.
Tabel conn_syn_fin berisi entri log dengan bendera SYN dan FIN, kemudian pencarian dilakukan menggunakan kursor dalam tabel ini.
Tabel connless berisi daftar koneksi, terbuka dan selesai, selesai memiliki durasi terbuka, masing-masing, no.
Perhatikan waktu pengambilan sampel dikurangi lima menit dari waktu saat ini. Permintaan saya lambat. Perlahan-lahan ia pergi melalui pencarian kursor, memproses sekitar 10 catatan per detik, mencoba mempercepatnya dalam segala hal, tetapi waktu eksekusi selalu hampir sama.
Perhatikan juga bahwa prosedur ini hanya untuk tujuan demonstrasi. Jika Anda perlu menentukan pilihan untuk src / sport / dst / dport tertentu, lebih baik membuat prosedur terpisah yang serupa dengan yang ini. Jika Anda adalah master sql, maka Anda dapat menulis kueri Anda dengan lebih baik.

panggil koneksi_list ();
 MariaDB [traflog]> call connections_list(); +---------------------+---------------------+----------+---------------+-------+-----------------+-------+ | datestart | dateend | duration | src | sport | dst | dport | +---------------------+---------------------+----------+---------------+-------+-----------------+-------+ | 2019-03-20 14:12:19 | 2019-03-20 14:13:14 | 00:00:55 | 192.168.0.81 | 41868 | 87.250.250.207 | 443 | | 2019-03-20 14:12:25 | NULL | NULL | 192.168.0.65 | 49311 | 52.5.23.125 | 443 | | 2019-03-20 14:12:31 | 2019-03-20 14:12:51 | 00:00:20 | 192.168.0.104 | 54433 | 217.69.139.42 | 443 | | 2019-03-20 14:12:31 | 2019-03-20 14:12:51 | 00:00:20 | 192.168.0.104 | 54434 | 217.69.139.42 | 443 | | 2019-03-20 14:12:32 | NULL | NULL | 192.168.0.119 | 37977 | 209.85.233.95 | 443 | ... | 2019-03-20 14:17:12 | NULL | NULL | 192.168.0.119 | 39331 | 91.213.158.131 | 443 | | 2019-03-20 14:17:13 | NULL | NULL | 192.168.0.90 | 63388 | 87.240.185.236 | 443 | +---------------------+---------------------+----------+---------------+-------+-----------------+-------+ 399 rows in set (33.17 sec) Query OK, 0 rows affected (33.18 sec) 



Setelah prosedur selesai, tabel sementara conn_syn_fin dan connless tetap, Anda dapat melihatnya secara lebih terperinci jika Anda menemukan sesuatu yang mencurigakan atau tidak dapat diandalkan. Setelah memulai prosedur, tabel lama dihapus dan yang baru muncul. Tulis jika Anda menemukan kesalahan.

Source: https://habr.com/ru/post/id427159/


All Articles