banner
 .::Defense::. Ký sự các vụ DDoS đến HVA - Phần 6 Go to original post Author: Hoàng Ngọc Diêu (conmale) - Translator:  - Entry Date: 11/02/2009 11:54:55
Trưa 14/10:
Đã đến giờ ăn trưa. Gần bốn giờ ròng rã vùi đầu trong đống công việc, tôi hầu như quên bẵng chuyện HVA. Giờ này chắc JAL đã hồi âm. Tôi hâm nóng mớ thức ăn mang theo cho buổi trưa và log vào diễn đàn HVA (vừa ăn vừa táy máy server). Đúng như dự tưởng, tôi nhận được hai thông điệp từ JAL và một mớ thông điệp khác có dạng "giúp em hack yahoo pass". Tôi lầm bầm "suối ngày cứ yahoo pass, yim pass, không biết chán sao trời" và tôi để chúng qua một bên.

Đại khái trong thông điệp JAL "phán" rằng: "lão cần làm gì thì cứ làm". Vậy thì không có vấn đề gì. Tôi thử xem tình hình server lúc này ra sao bằng một số lệnh thông thường sau khi log vào HVA server. Chà, giờ này bên VN mới có 9 giờ sáng mà đã vào diễn đàn khá đông. Đành phải vậy thôi:
Code:


kill -SIGTERM `cat /var/run/httpd.pid` && rm -f /var/run/httpd.pid && rm -f /var/lock/subsys/httpd


Để cho chắc ăn, tôi phóng tiếp:
Code:


ps -ef | grep httpd


Hèm, sạch sẽ đâu đó, không còn một mảnh httpd "vương vấn". Hai lệnh trên có mục đích gì? Lệnh thứ nhất thật ra là một lệnh tổng hợp ba việc khác nhau. Phần thứ nhất của lệnh này dùng lệnh cat để xác định parent pid (process id) của httpd đang chạy trên máy để lệnh kill có thể kết thúc nó với tín hiệu SIGTERM -38-. Phần thứ nhì và thứ ba của lệnh này chỉ đơn giản xoá bỏ giá trị httpd.pid và httpd trên máy để lần sau httpd mới được khởi tạo, nó không bị "bối rối". Lệnh thứ nhì đi theo chỉ đơn giản dùng để xác nhận không còn process nào thuộc httpd đang chạy.

Tôi thử khởi động httpd mới xuyên qua một init script (xem lại chú thích 24) tôi tạo ra, đặc biệt dùng cho httpd mới và các thư viện cũng như hồ sơ cấu hình nó cần dùng. Ôi chao, không khởi động được, nó càm ràm không tìm thấy ba modules. Tôi nghĩ là tôi kỹ lưỡng đến thế mà vẫn sót lại vài cái modules "thừa hưởng" từ hồ sơ cấu hình cũ. Trong nháy mắt, chúng biến khỏi hồ sơ cấu hình. A lê hấp, khởi động lại xem sao.... thông điệp ngắn gọn và "tròn trĩnh":
Code:


HVA webserver is sucessfully started


hiện ra trên màn hình.

Tôi nôn nóng mở thêm hai console đến HVA server nữa, một dùng cho cái "đuôi" tail đến firewall log, một cho cái "đuôi" tail đến webserver error log, một cái nữa cho "đuôi" tail đến webserver access log và cái cuối cùng dùng để chạy lệnh lai rai như top, ps, netstat dùng để theo dõi tình hình chung. Cái màn hình 21 inches gắn thêm vào laptop bị HVA "lấn chiếm" gần hết (may mà tay xếp hơi bị... mù về unix nên hắn không hề để ý xem mấy cái console này là cho việc công hay việc tư những lúc hắn đi ngang qua bàn làm việc của tôi ).

Bạn đoán thử cái "tail" nào tôi đổ dồn ngay cặp mắt vào trước tiên? Đúng rồi, cái "tail" đến web server error log. Tôi mở trình duyệt trên máy của tôi, trỏ đến HVA forum và... nhấn F5 lia lịa. access log ghi nhận truy cập từ trình duyệt của tôi đều đặn và cần mẫn như một ông thư ký già. Trong khi đó, error log hoàn toàn im ắng. Im ắng thế này là tốt lắm. Bạn có thể thắc mắc chỉ có mấy cái "child exit" do segfault mà làm gì quan trọng đến thế?. Sở dĩ tôi chú trọng đến cái log này vì những lỗi thông báo segfault, theo tôi còn nghiêm trọng hơn những cú "x-flash" đang "đấm thùi thụi" vào HVA server.

Hãy thử mở rộng hơn một chút về tính nghiêm trọng ở đây. Trọn bộ quy trình hệ thống nhận một request từ client đến giai đoạn child process bị SEGFAULT tiêu phí rất nhiều tài nguyên của máy chủ nhưng lại bị hủy đi một cách vô lý vì không thể ấn định memory cho nó (share memory trong trường hợp này vì mmap báo lỗi trong lúc debug), đây là chuyện dễ hiểu. Chuyện đáng đề cập hơn nữa là ảnh hưởng phát tán đến trọn bộ dịch vụ của webserver như sau:
- phí tài nguyên dùng để tường trình lỗi liên tục vào error log (gia tăng công tác input / ouput)
- vì dùng php làm công nghệ bên dưới để tải diễn đàn HVA và php không phải là "thread safe" nên buộc web server phải dùng cơ cấu prefork (xem lại chú thích 35). prefork ở đây có nghĩa là khi server khởi động, nó tạo sẵn một số lượng process để xử lý các truy cập đã được socket đón nhận trên cổng HTTP. Mỗi process này chỉ được tiếp nhận một lượng truy cập nào đó rồi bị huỷ (dựa trên giá trị ấn định MaxRequestsPerChild) và process mới lại được tạo ra để tiếp tục phục vụ. Nếu các truy cập đều chất lượng và không hề bị SEGFAULT thì process ấy chỉ bị hủy khi tới giới hạn đã định và nó sẽ... thọ hơn. Nếu có một SEGFAULT xảy ra và không cần biết là process này đã phục vụ bao nhiêu request, nó cũng bị kết liễu, chết non, yểu mệnh... tuỳ cách bạn gọi. Server buộc phải tạo thêm process để tiếp tục phục vụ và đây là "cái chậm sơ bộ".

Vậy "cái chậm chi tiết" là sao? Trên một hệ thống *nix, việc đóng mở các sockets, tạo process, phân bố tài nguyên là do kernel lo và mỗi hoạt động này phải đi theo một nguyên tắc nhất định. Đặc biệt trên Linux và trên kernel series 2.4.x, vấn đề điều tác ưu tiên cho mỗi process tùy tính chất và quy chế dành cho process này -40-. Khi web server đòi hỏi tạo một process, không phải lúc nào đòi hỏi này cũng được thực hiện ngay lập tức. Kernel phải thực hiện mọi yêu cầu theo đúng trình tự không thì hệ thống sẽ biến thành cái ổ nhện. Thời gian và tài nguyên để máy chủ tạo process với nhịp độ như trên chắc chắn sẽ không còn hiệu quả để phục vụ cho clients. Server load sẽ lên cao, số lượng công việc sẽ dồn đống, tài nguyên dần dần sẽ cạn kiệt và đến một lúc nào đó, không những dịch vụ chết mà cả máy chủ cũng sẽ chết vì quá tải.

Sở dĩ người dùng truy cập HVA server thường xuyên cảm thấy chậm là vì một phần bị những quả "x-flash" kia chen chân, một phần request của họ bị mất tăm theo những cái SEGFAULT. Trong những trường hợp này, trình duyệt lại phải gởi request (retry) và nếu không may thì request lần này cũng có số phận không khác gì lần trước. Nếu tầng IP đã giới hạn mức truy cập và tầng application lại bị SEGFAULT thì cơ hội người dùng hợp lệ truy cập đến HVA ở tình trạng thành công lại càng giảm sút. Lý do: mức giới hạn ở tầng IP dùng để giảm thiểu tầng số xâm nhập của "x-flash" (để bảo tồn tài nguyên cho máy chủ) trực tiếp giảm thiểu tầng số truy cập của người dùng hợp lệ. Bạn có thể hình dung trường hợp một vận động trường mở toang hai cánh cổng cho 100 người vào cùng một lúc gồm cả "người ngay, kẻ gian" và làm như thế thì số lượng người tràn vào nhanh nhưng lại khó kiểm soát. Nếu đóng bớt một cánh cổng thì chỉ còn có 50 người có thể vào cùng một lúc và làm như thế thì dễ kiểm soát hơn nhưng cũng làm ảnh hưởng đến những "người ngay".

Cho đến lúc này, sau gần 30 phút theo dõi sát tình hình các truy cập xảy ra trên máy, trên logs, trên socket status... tôi có thể xác định rằng segfault đã hoàn toàn được loại trừ. Bởi php không "thread-safe" nên mỗi request đi vào, web server phải tạo một process hẳn hòi để phục vụ. Tôi điều chỉnh cho web server khởi tạo sẵn 50 processes để chờ tiếp nhận requests. Lúc này số lượng truy cập đến HVA forum bắt đầu gia tăng (giờ này đã gần 10 giờ sáng giờ VN). Dựa trên số lượng access từ access log của web server, tôi ước chừng cứ mỗi 20 giây có một request đến server. Tôi cho phép 256 "MaxRequestsPerChild", như vậy phải sau 85 phút thì một child process mới bị huỷ. 50 child processes đứng chờ sẵn kia với tình hình này thì quá dư nhưng liệu có đủ đáp ứng trong khoản thời gian cao điểm vào ban đêm? Như đã giải thích ở trên về quy chế tạo process, một request đi vào nếu không có sẵn process để phục vụ ngay thì khả năng trình duyệt tiếp tục gởi request đến (vì bị timeout). Vậy trong hoàn cảnh web server cực kỳ bận rộn vào ban đêm thì cần bao nhiêu process nằm sẵn để "nhận công tác" là thích hợp?

Tôi nhẩm tính trong đầu, vào khoảng thời gian 2 giờ cao điểm ban đêm sẽ có khoảng 12000 x-flash requests như đã phân tích ở bài đầu:
(12000 requests / 120 phút) / 60 giây = 1.6 request mỗi giây

Trong 2 giờ, web server sẽ tiếp nhận requests và tạo ra bao nhiêu processes? Thử xem:
- 1 process được tiếp nhận 256 request rồi bị huỷ
- 12000 requests trong 120 phút (7200 giây) = 1.6 requests cho mỗi giây.
12000 requests / 256 max request per child process = 47 processes

Thử ước tính server load sẽ là bao nhiêu nếu nó phải tạo 47 processes trong 2 giờ?
( 15 phút x 47 processes ) / 120 = 5.8 processes
5.8 / 15 = 0.38
(xem thêm chú thích 43)

Con số process quá lớn nhưng nếu tính tra mức server load trung bình ở mức 0.86 thì nó lại ở mức bình thường. Hơn nữa con số process trên cũng không đáng ngạc nhiên vì số request đến HVA server quá cao do x-flash và những dạng tấn công khác. Ở bước này, điều tôi cần kiến tạo là bảo đảm HVA webserver không bị chậm vì liên tục có quá nhiều request đi vào khiến nó không kịp thời tạo process để phục vụ và sẽ đi đến tình trạng giảm sút hiệu xuất. Điều kế tiếp tôi cần kiến tạo là nắm chắc web service và các modules không bị memory leak. Thật ra, dựa trên logic đã được thiết lập sẵn, web service có khả năng tự điều tác việc tắt bỏ và tái tạo các process hết sức nhịp nhàng và quân bình. Tuy nhiên, đối với một site đang bị DoS nặng nề như HVA thì giá trị mặc định không còn thích hợp nữa. Tôi không muốn server phải bị "chết" vì quá tải, tôi cũng chẳng muốn người dùng hợp lệ phải "khổ sở" với vấn đề truy cập. Nếu tôi có một chuỗi 10 máy chủ (chẳng hạn) thì sự thể đã khác, nhưng tôi phải máy mó trong giới hạn cho phép. Tôi tin rằng các con số này sẽ phải điều chỉnh nhiều lần cho đến khi chúng mang giá trị thích hợp nhất cho HVA server.

Đến đây, tôi hy vọng bạn đã nhận ra được một điểm quan trọng sau khi theo dõi diễn tiến từ đầu câu chuyện đến giai đoạn này: "đỡ" các cú DoS không chỉ ở socket level mà còn phải tối ưu hoá dịch vụ ở mức cao nhất có thể được. Cản lọc ở socket level là phương pháp giảm thiểu biên độ và trường độ của các truy cập đến máy chủ với mục đích bảo tồn tài nguyên và hoạt động của nó. Tuy nhiên, việc nâng cao khả năng phục vụ của chính dịch vụ mình muốn bảo vệ cần được quan tâm không kém gì việc cản lọc. Mối tương quan và sự bình quân của hai vấn đề trên chính là chìa khoá của sự bền bỉ và hiệu xuất của máy chủ.

Bước kế tiếp trong giai đoạn điều chỉnh và kiện toàn web service là bước ứng dụng một bộ phận cản lọc trên tầng ứng dụng (application layer). Hẳn bạn đã nghe đến cái tên mod_security -41-, một module được dùng rộng rãi cho một số web server. Bạn có thể hỏi nhưng mod_security đâu phải là một mod chuyên chống DoS, tại sao lại dùng để chống DoS?. Câu trả lời rất đơn giản: nó dùng để cản cụ thể những gì firewall ở tầng IP không thể cản hết được.

Các cơ chế cản lọc đã được ứng dụng trên HVA server cho đến giai đoạn này là những cản lọc nặng tính hiệu xuất bởi vì chúng loại bỏ những gói tin vi phạm một cách âm thầm, tầng dịch vụ web server không hề biết đến và cũng không cần biết đến. Tuy các cơ chế này có tính hiệu xuất cao nhưng những ứng dụng cản lọc tầng thấp (đã nêu trên) không thể hoàn toàn loại bỏ những gói tin vi phạm đi vào. Dựa trên các thông tin thu thập được từ các log files, cơ chế cản ở IP layer cho đến lúc này có hiệu năng chừng 65-75% (tính theo kiểu khách quan). Vậy có khoảng 30% các gói tin tấn công vẫn có cơ hội đi vào và tiêu phí tài nguyên của máy chủ.

mod_security được chọn làm tấm "bình phong" để cản lọc phần còn lại của các gói tin vi phạm này. Ở đây tôi không tiện giới thiệu cụ thể các filtering rules đã được dùng cho mod_security nhưng điều tổng quát tôi có thể giới thiệu với bạn là mod_security có khả năng kiểm soát các request đến HTTP dựa trên phương pháp regex -42-. Nó có thể bắt gặp và cản trở những request vi phạm trong một biên độ khá rộng và linh động. Biết rằng những công cụ dùng để lọc và cản trở gói tin ở application layers đòi hỏi nhiều tài nguyên của máy chủ nhưng trong trường hợp này:
- mod_security chỉ đảm đương 30% các gói tin vi phạm còn lại
- ước lượng tài nguyên dành cho mod_security để xử lý 30% các gói tin vi phạm này ít hơn rất nhiều số lượng tài nguyên web server và database server phải phục vụ nếu cứ để các gói tin mặc nhiên đi vào.
- mod_security còn loại bỏ hàng loạt các dạng tấn công mang tính nguy hại khác đến web services.

Bởi lẽ mod_security làm "tấm bình phong" cho web service, mọi requests trước khi đi vào tới web service đều bị mod_security chặn lại và xét duyệt. Bước này làm gia tăng thời gian đáp ứng request cho người dùng hợp lệ. Đây là cái giá phải trả để bảo tồn cho tài nguyên và sự an toàn của máy chủ. Tuy nhiên, "chậm" hơn một chút ở bước này hoàn toàn có thể chấp nhận được vì nếu không có nó bảo vệ, hàng loạt requests vào được bên trong web service rồi tiếp tục đụng đến csdl và những thứ nhì nhằng bên trong thì cái chậm ở mức này khó có thể đo lường được nếu máy chủ đang bị tấn công. Sau một khoảng thời gian nào đó, người dùng sẽ không những thấy chậm mà còn có thể đi đến tình trạng không thể truy cập được máy chủ nữa vì nó quá bận rộn.

Mọi chuyện xem như tạm ổn, tôi quyết định tái khởi động web server và để bảo đảm dịch vụ web này ứng hiệu với những điều tôi vừa áp đặt, tôi không dùng graceful restarting mà ép buộc nó hoàn toàn ngưng hoạt động, tắt bỏ trọn bộ các process và khởi động lại từ đầu. Tôi gởi JAL một PM thông báo tình hình. Nhìn đồng hồ, tôi biết hôm nay mình không còn bao nhiêu thời gian để táy máy với HVA server nữa. Điều tôi muốn tìm hiểu nhưng không có thời gian theo dõi là tổng số server load -43- trước, sau và trong khi HVA "bị" tấn công sau khi đã trang bị tất cả những cơ chế thắt chặt từ lúc khởi đầu cho đến bây giờ. Thế nên tôi "whip" ra một đoạn shell script như sau:
Code:


#!/bin/bash

# 60 sec x 180 min
i=10800
while [ ${i} -gt 0 ]; do
w | grep load | awk '{print$1, $10, $11, $12}' >> /tmp/load
sleep 120
let i=$i-120
done


rồi thêm đoạn script này vào cronjob của server để nó chạy từ lúc 7 giờ tối trở đi. Hy vọng sáng hôm sau khi tôi vào server sẽ có sẵn một hồ sơ có tên là load nằm chễm chệ trong /tmp chờ tôi xem xét. Tôi sẽ dùng thông tin trong hồ sơ này để "vẽ" một cái biểu đồ để xem lúc cao điểm vào ban đêm, server load sẽ lên tới bao nhiêu. Tôi cũng muốn xem mức gia tăng của server load có tính chất thế nào (gia tăng đột biến hay gia tăng leo thang...). Từ đó sẽ hình thành các bước thắt chặt và tối ưu khác nếu có thể được. À, bạn thắc mắc đoạn script ở trên làm gì? . Nó làm một chuyện hết sức đơn giản như sau: cứ trước khi script nó ngủ một giấc 120 giây, nó bèn:
- chạy lệnh w (để lấy thông tin server load)
- thông tin này được awk tuyển lọc chỉ lấy cột số 1, 10, 11 và 12
- sau khi lấy được thông tin này, nó bèn chép vào dòng kế tiếp trong hồ sơ load trong thư mục /tmp
- trừ bớt trên bộ đếm i giá trị thời gian mỗi lần nó ngủ 120 giây.
- nó lặp lại y hệt các bước 90 lần trong 3 giờ đồng hồ rồi tự... kết liễu (vì đã hoàn tất vòng lặp).

Tôi lẩm nhẩm "để xem sự thể ra sao!"

Các bạn có thể theo dõi tiếp phần 7 tại http://hvaonline.net/hvaonline/posts/list/181.html

Chú thích:

-38- Tín hiệu gởi đi để xử lý process bằng lệnh kill. Tùy ứng dụng của mỗi *nix flavour. Trên linux nói chung, để biết các tín hiệu có thể dùng được thử lệnh kill -l. Mỗi tín hiệu (signal) này được gởi đi sẽ được hàm signal() của hệ thống điều tác mà xử lý. Xem thêm man kill và các tài liệu liên quan (được đề cập đến trong phần cuối của kill manual).

-39- memory leak, tình trạng rò rỉ bộ nhớ nói theo kiểu nôm na. Tình trạng memory sau khi đã dùng xong không thể lấy lại được để tái dụng cho những hoạt động khác trên hệ thống nói theo kiểu kỹ thuật hơn một chút. Memory được dùng như chỗ chứa thông tin để một chương trình nào đó hoạt động. Có những thông tin chỉ cần chỗ chứa tạm thời và ngắn hạn. Sau khi đã tính toán xong và đã xử dụng xong giá trị tính toán, "chỗ chứa" này không được cần nữa, nội dung trong "chỗ chứa" được xoá bỏ và "chỗ chứa" này được trưng dụng cho những việc khác. Memory leak là tình trạng "chỗ chứa" không còn được dùng nữa nhưng không thể xoá để trưng dụng cho việc khác, nhu liệu bị memory leak cứ tiếp tục đòi thêm "chỗ chứa" nhưng không hề trả lại những "chỗ chứa" cũ không còn cần tới.

-40- process policy hay là quy chế điều tác process. Linux điều tác process dựa trên căn bản "time slice", có nghĩa là các process được đưa vào "queue" (sắp hàng) và tuần tự được đưa vào tình trạng "runable" (có thể được chạy), mỗi process sẽ được cơ hội vào chế độ "runnable". Tình trạng runnable này được "scheduler" (người sắp xếp thứ tự) sắp xếp và quyết định, nó xét mọi process nằm trong queue hiện có và quyết định process nào đáng được ưu tiên nhất thì process này có ưu tiên cao nhất. Thông thường khi một hệ thống có nhiều process (xem như) có cùng ưu tiên như nhau thì process nào đứng đầu trong running queue thường được chọn để chạy. Tuy nhiên, trong khi một processs đang chạy, ưu tiên của các process còn lại trong queue có thể lại được thay đổi tuỳ theo tình hình lúc ấy và rốt cuộc mọi process đều có cơ hội để chạy (còn được biết với thuật ngữ "round-robin"), chỉ có chờ lâu hay không mà thôi.

-41- mod_security ở http://www.modsecurity.org. mod_security là một nhu liệu open source do Ivan Ristic viết. Nó có tính năng gần giống như tổng hợp của một intrusion detection system và một application layer firewall. Dù không đa năng nhưng những nhu liệu chuyên về cản lọc hay phát hiện nhưng mod_security là một nhu liệu tuyệt vời để hỗ trợ thêm vào những cơ chế bảo vệ hiện có trên hệ thống. mod_security làm việc như một tấm bình phong, cản lọc mọi request trước khi thật sự đi vào web server.

-42- regex hay regular expression. Đối với những ai có nhu cầu phải tiếp cận với những vấn đề cần phải dùng "pattern matching" thì regex không có gì là mới mẻ. Tuy nhiên, đối với những ai chưa từng có cơ hội hay nhu cầu phải dùng đến regex thì tôi muốn giới thiệu nó đến bạn như một phương tiện hết sức cần thiết và quan trọng cho phương diện phân tích và ứng dụng bảo mật. Bạn muốn thu thập những thông tin hữu ích nhất và quan trọng nhất theo ý muốn từ hàng "tấn" log files? Đọc thêm về regex, một trang tutorial rất hay ở: http://www.regular-expressions.info/tutorial.html

-43- server load là giá trị trung bình của số lượng công việc đi xuyên qua "job queue" được xử lý trong khoảng 1 phút, 5 phút và 15 phút. Ví dụ, server load có giá trị là 0.5 1.0 0.8 có nghĩa là:
- trong 1 phút có: 0.5 job / 1 phút = 0.5
- trong 5 phút có: 5 jobs / 5 phút = 1.0
- trong 15 phút có: 12 jobs / 15 phút = 0.8
Đây là các con số rất bình thường cho một máy chủ không bận rộn.
[digg] [delicious] [google] [yahoo] [technorati] [reddit] [stumbleupon]
Other posts in the same group:

Ký sự các vụ DDoS đến HVA - Phần 6
Go to top Go to original post  

Powered by JForum - Extended by HVAOnline
 hvaonline.net  |  hvaforum.net  |  hvazone.net  |  hvanews.net  |  vnhacker.org
1999 - 2013 © v2012|0504|218|