@iamproz2911
# Week6: Nflog API
[6th week] Nflog Ulogd
## Nội dung
Yêu cầu triển khai:

Dựa vào Sequence Diagram hãy xây dựng API của Nflog để thu thập và báo cáo các thao tác của người dùng khi tương tác với WebOS trên Raspberry.
Chỉ ra các vi phạm vào chính sách tường lửa của người dùng.
## Ý tưởng
ý tưởng của mình là gộp tất cả các file lại và trình bày data theo dạng bảng
Đầu tiên mình sẽ lấy các trường chung của các loại file log (json pcap oprint gprint logemu)
Mình sẽ chọn ra 4 cột của bảng như sau
Time IP SRC IP DST Protocol MAC Address
Bây giờ mình sẽ lấy các trường chung riêng các file sau đó sẽ ánh xạ qua cái bảng trên như thế này
Đối với syslogemu:
Log file của syslogemu có dạng như sau
Jan 3 21:35:48 iamproz2911 pingclear! IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=192.168.98.212 DST=192.168.98.212 LEN=28 TOS=00 PREC=0x00 TTL=64 ID=58524 PROTO=ICMP TYPE=8 CODE=0 ID=61500 SEQ=0 MARK=0
Jan 3 21:35:48 iamproz2911 pingclear! IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=192.168.98.212 DST=192.168.98.212 LEN=28 TOS=00 PREC=0x00 TTL=64 ID=35819 PROTO=ICMP TYPE=8 CODE=0 ID=61500 SEQ=15744 MARK=0
vậy mình sẽ lấy
Jan 3 21:35:48 : Time
SRC=192.168.98.212 : IP SRC
DST=192.168.98.212 : IP DST
PROTO=ICMP : Protocol
MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 : MAC Address
Đối với Json:
Log file dạng như sau:
{"timestamp": "2025-01-03T21:35:48.371888+0700", "dvc": "Netfilter", "raw.pktlen": 28, "raw.pktcount": 1, "oob.prefix": "pingclear!", "oob.time.sec": 1735914948, "oob.time.usec": 371888, "oob.mark": 0, "oob.ifindex_in": 1, "oob.hook": 1, "raw.mac_len": 14, "oob.family": 2, "oob.protocol": 2048, "raw.label": 0, "raw.type": 772, "raw.mac.addrlen": 6, "ip.protocol": 1, "ip.tos": 0, "ip.ttl": 64, "ip.totlen": 28, "ip.ihl": 5, "ip.csum": 20299, "ip.id": 58524, "ip.fragoff": 0, "icmp.type": 8, "icmp.code": 0, "icmp.echoid": 61500, "icmp.echoseq": 0, "icmp.csum": 49927, "oob.in": "lo", "oob.out": "", "src_ip": "192.168.98.212", "dest_ip": "192.168.98.212", "mac.saddr.str": "00:00:00:00:00:00", "mac.str": "00:00:00:00:00:00:00:00:00:00:00:00:08:00"}
{"timestamp": "2025-01-03T21:35:48.371991+0700", "dvc": "Netfilter", "raw.pktlen": 28, "raw.pktcount": 1, "oob.prefix": "pingclear!", "oob.time.sec": 1735914948, "oob.time.usec": 371991, "oob.mark": 0, "oob.ifindex_in": 1, "oob.hook": 1, "raw.mac_len": 14, "oob.family": 2, "oob.protocol": 2048, "raw.label": 0, "raw.type": 772, "raw.mac.addrlen": 6, "ip.protocol": 1, "ip.tos": 0, "ip.ttl": 64, "ip.totlen": 28, "ip.ihl": 5, "ip.csum": 43004, "ip.id": 35819, "ip.fragoff": 0, "icmp.type": 8, "icmp.code": 0, "icmp.echoid": 61500, "icmp.echoseq": 15744, "icmp.csum": 17098, "oob.in": "lo", "oob.out": "", "src_ip": "192.168.98.212", "dest_ip": "192.168.98.212", "mac.saddr.str": "00:00:00:00:00:00", "mac.str": "00:00:00:00:00:00:00:00:00:00:00:00:08:00"}
vậy mình sẽ lấy
"timestamp": "2025-01-03T21:35:48.371991+0700" : Time
"src_ip": "192.168.98.212" : IP SRC
"dest_ip": "192.168.98.212" : IP DST
ip.protocol": 1: Protocol
"mac.str": "00:00:00:00:00:00:00:00:00:00:00:00:08:00" : MAC Address
Đối với PCAP:
Log file có dangj:
21:35:48.372040 IP 192.168.98.212 > 192.168.98.212: ICMP echo request, id 61500, seq 0, length 8
21:35:48.372047 IP 192.168.98.212 > 192.168.98.212: ICMP echo request, id 61500, seq 15744, length 8
21:35:50.387977 IP 192.168.98.212 > 192.168.98.212: ICMP echo request, id 61500, seq 62206, length 8
21:35:50.387984 IP 192.168.98.212 > 192.168.98.212: ICMP echo request, id 61500, seq 15491, length 8
21:35:52.372115 IP 192.168.98.212 > 192.168.98.212: ICMP echo reply, id 61500, seq 34565, length 8
vậy mình sẽ lấy
21:35:50.387977 : Time
192.168.98.212 : IP SRC
192.168.98.212: IP DST (trước dấu > là ip nguồn còn sau dấu là ip đích , ví dụ: 192.168.98.212 > 192.168.98.212 thì cái trước sẽ là ip nguồn cái sau dấu > là ip ddichs)
ICMP : Protocol (Sau dấu : )
Trường hợp này không có thì sẽ hiển thị là N/A: MAC Address
Đối với Gprint:
log có dạng như sau:
timestamp=2025/01/03-21:35:48,raw.pktlen=28,raw.pktcount=1,oob.prefix=pingclear!,oob.time.sec=1735914948,oob.time.usec=372051,oob.mark=0,oob.ifindex_in=1,oob.hook=1,raw.mac_len=14,oob.family=2,oob.protocol=2048,raw.label=0,raw.type=772,raw.mac.addrlen=6,ip.saddr=192.168.98.212,ip.daddr=192.168.98.212,ip.protocol=1,ip.tos=0,ip.ttl=64,ip.totlen=28,ip.ihl=5,ip.csum=20299,ip.id=58524,ip.fragoff=0,icmp.type=8,icmp.code=0,icmp.echoid=61500,icmp.echoseq=0,icmp.csum=49927,oob.protocol=2048
vậy mình sẽ lấy
timestamp=2025/01/03-21:35:48 : Time
ip.saddr=192.168.98.212 : IP SRC
ip.daddr=192.168.98.212: IP DST
ip.protocol=1: Protocol
Trường hợp này không có thì sẽ hiển thị là N/A: MAC Address
Đối với Oprint
log của nó trình bày theo dạng thẳng xuống như sau:
===>PACKET BOUNDARY
raw.mac=default
raw.pkt=default
raw.pktlen=28
raw.pktcount=1
oob.prefix=pingclear!
oob.time.sec=1735914948
oob.time.usec=372098
oob.mark=0
oob.ifindex_in=1
oob.hook=1
raw.mac_len=14
oob.family=2
oob.protocol=2048
raw.label=0
raw.type=772
raw.mac.saddr=default
raw.mac.addrlen=6
raw=default
ip.saddr=212.98.168.192
ip.daddr=212.98.168.192
ip.protocol=1
ip.tos=0
ip.ttl=64
ip.totlen=28
ip.ihl=5
ip.csum=20299
ip.id=58524
ip.fragoff=0
icmp.type=8
icmp.code=0
icmp.echoid=61500
icmp.echoseq=0
icmp.csum=49927
oob.protocol=2048
oob.in=lo
oob.out=
ip.saddr.str=192.168.98.212
ip.daddr.str=192.168.98.212
print=pingclear! IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=192.168.98.212 DST=192.168.98.212 LEN=28 TOS=00 PREC=0x00 TTL=64 ID=58524 PROTO=ICMP TYPE=8 CODE=0 ID=61500 SEQ=0 MARK=0
vậy mình sẽ lấy
timestamp=2025/01/03-21:35:48 : Time
ip.saddr=212.98.168.192 : IP SRC
ip.daddr=212.98.168.192 : IP DST
PROTO=ICMP : Protocol
MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00: MAC Address
## Ulogd
Cài đặt stack phù hợp cho Ulogd, tạo các group và các log file tương ứng với các group.
```
stack=log25:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,print1:PRINTPKT,emu1:LOGEMU
stack=log20:NFLOG,base1:BASE,xml1:XML
stack=log21:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,mac2str1:HWHDR,json1:JSON
stack=log22:NFLOG,base1:BASE,pcap1:PCAP
stack=log23:NFLOG,base1:BASE,gp1:GPRINT
stack=log24:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,print1:PRINTPKT,op1:OPRINT
[log25]
group=25
[log20]
group=20
[log21]
group=21
[log22]
group=22
[log23]
group=23
[log24]
group=24
```
## Iptables
Tạo Rules Iptables để nhận log cảnh báo
iptables -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j NFLOG --nflog-prefix "pingclear!" --nflog-group 19
Tương ứng tiếp cho các group19->23. Ở đây lấy chung Protocol để kiểm tra tiện hơn.

## Nflog API
Đầu tiên mình sẽ detect ra được những cái stack sử dụng trong trong ulogd.conf.
Dùng Python để phân tích cấu hình của ulogd, thu thập và hiển thị các log từ các plugin khác nhau (như PCAP, JSON, syslogEMU, v.v.).

Ở đây set cứng các tham số plugin như pcap1, emu1...
Kiểm tra sự tồn tại của file cấu hình (/etc/ulogd.conf).
Đọc từng dòng trong file cấu hình và xử lý:
Nếu dòng bắt đầu với stack=, tìm kiếm tên của stack và các plugin kèm theo.
Nếu có file= hoặc directory=, tìm kiếm đường dẫn của các file log hoặc thư mục.

Code detect ra các plugin và nhóm log trong file conf được sử dụng.
Sau đó có tùy chọn trích dẫn đường dẫn các file đã tìm thấy trong cấu hình:

Phương thức display_logs:
Kiểm tra xem có logs hay không.
Duyệt qua các stack và plugin, xác định xem log có ở dạng file hay thư mục.
Gọi các phương thức phù hợp để thu thập log từ file, thư mục hoặc PCAP.
Cuối cùng, hiển thị các log dưới dạng bảng.
Các phương thức thu thập log từ file hoặc thư mục:
collect_log_file: Đọc log từ một file đơn lẻ và xử lý dựa trên loại plugin.
collect_directory_logs: Duyệt qua tất cả các file trong thư mục có phần mở rộng phù hợp với plugin (ví dụ: .json, .xml).
collect_pcap_file: Dùng tcpdump để đọc và phân tích một file PCAP.
List các file log ra dưới dạng DataFrame:
Triển khai dưới dạng DataFrame bằng Pandas Python:

Hoặc có thể là dạng bảng:

Khi có log file mới được cập nhật vào file config, khởi động lại chương trình để có thể đọc được cái plugin đăng kí trong ulogd.conf. Và không có yêu cầu RealTime.
## Demo
Dùng 2 plugin là Pcap và Json để để thu thập log
Cấu hình trong ulogd:

Cấu hình Rules tương tự trong Iptables để thu thập log về 2 group20-22

Detect Stack và Check Valid Repo:

Code detect ra 2 stack sử dụng trong bài, cũng như là đường dẫn file chính xác.
Dùng Hping3 để tạo log trong iptables
Hping3 –icmp --flood 10.10.16.57
Sau khi kiểm tra Iptables nhận thấy có các thông số về log được lưu:

List Log:
Dạng DataFrame
Không có thông tin về MAC nên sẽ hiển thị là N/A

Hoặc có thể list ra dạng bảng:

Tiếp theo, mình sẽ làm 2 kiểu Logemu, Gprint:

Thêm 2 rules mới vào để log về group

Detect Stack và Check Valid Repo:

List logemu ra dạng bảng:

List log detail cho Gprint vì Gprint chứa khá nhiều thông tin.

## Nhận xét:
Mình đã triển khai các bước để thu thập log trong Ulogd, các stack được cấu hình đúng, đã thu thập được log và hiển thị trong file.
Xây dựng code detect tự động và list file ra các định dạng khác nhau tùy với cơ chế của loại file đó.
Các kết quả cho thấy code hoạt động tốt và detect cũng như kiểm tra link file hợp lệ, đầu ra cho kết quả trực quan và rõ ràng.