@iamproz2911 # Week6: Nflog API [6th week] Nflog Ulogd ## Nội dung Yêu cầu triển khai: ![image](https://hackmd.io/_uploads/HJ_9wvHD1x.png) 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. ![image](https://hackmd.io/_uploads/HkMxuvSwye.png) ## 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.). ![image](https://hackmd.io/_uploads/Sy7M_DSvyg.png) Ở đâ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. ![image](https://hackmd.io/_uploads/B1GX_DSv1l.png) 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: ![image](https://hackmd.io/_uploads/r1C7OwHP1e.png) 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: ![image](https://hackmd.io/_uploads/BkOruPBDyx.png) Hoặc có thể là dạng bảng: ![image](https://hackmd.io/_uploads/rkuIODHDye.png) 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: ![image](https://hackmd.io/_uploads/r14q_Drw1x.png) Cấu hình Rules tương tự trong Iptables để thu thập log về 2 group20-22 ![image](https://hackmd.io/_uploads/Bkio_wSD1l.png) Detect Stack và Check Valid Repo: ![image](https://hackmd.io/_uploads/SJvhuDrv1l.png) 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: ![image](https://hackmd.io/_uploads/rkmpOwBP1g.png) List Log: Dạng DataFrame Không có thông tin về MAC nên sẽ hiển thị là N/A ![image](https://hackmd.io/_uploads/HJGCuPHD1e.png) Hoặc có thể list ra dạng bảng: ![image](https://hackmd.io/_uploads/BywyFwHDkl.png) Tiếp theo, mình sẽ làm 2 kiểu Logemu, Gprint: ![image](https://hackmd.io/_uploads/rJMWYvrD1x.png) Thêm 2 rules mới vào để log về group ![image](https://hackmd.io/_uploads/BJgGYwSwyg.png) Detect Stack và Check Valid Repo: ![image](https://hackmd.io/_uploads/BJiGKwBPke.png) List logemu ra dạng bảng: ![image](https://hackmd.io/_uploads/HkUQKwrvyx.png) List log detail cho Gprint vì Gprint chứa khá nhiều thông tin. ![image](https://hackmd.io/_uploads/H1fNtvBvkl.png) ## 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.