Pages

Iptables On Linux (phần 2)




 Phần 2


Case 2 – iptables và máy đơn có dịch vụ 
Trường hợp điển hình thứ nhì trong việc ứng dụng iptables để bảo vệ máy đơn có dịch vụ.
1. Trường hợp: 
Firewall cho một máy đơn có dịch vụ.
2. Nhu cầu: 
Bảo vệ máy đơn không bị thâm nhập vào những dịch vụ không dành cho công cộng và cho phép truy cập vào những dịch vụ được ấn định cụ thể.
3. Phương pháp kết nối: 
Bất cứ phương tiện nào, (cách tốt nhất) nên có IP tĩnh để có thể tạo dịch vụ công cộng ổn định.
Đòi hỏi tối thiểu:
Đã hoàn tất thành công quy trình kết nối vào Internet và các dịch vụ trên máy đã có thể truy cập được từ Internet.

4. Mô hình:
eth0 là NIC tiếp diện với Internet với IP tĩnh. Mô hình này thích hợp cho các máy đơn (dedicated server) với các dịch vụ thông thường như HTTP, SMTP, POP3, DNS và SSH (quản lý từ xa).
5. Nhóm luật: 
1. IF=`/sbin/route | grep -i 'default' | awk '{print$8}'`
2. IP=`/sbin/ifconfig $IF | grep "inet addr" | awk -F":" '{print$2}' | awk '{print $1}'`
3. IPT="/usr/local/sbin/iptables"
4. NET="any/0"
5. DNS="xxx.xxx.xxx.xxx yyy.yyy.yyy.yyy.yyy"
6. SERV_TCP="22 25 80 443 110"
7. SERV_UDP="53 123"
8. HI_PORTS="1024:65535"
9.
10. $IPT -F
11. $IPT -P INPUT DROP
12. $IPT -P OUTPUT DROP
13. $IPT -P FORWARD DROP
14.
15. for entry in $DNS; do
16. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $HI_PORTS -d $entry --dport 53 -m state --state NEW -j ACCEPT
17. $IPT -A INPUT -i $IF -p udp -s $entry --sport 53 -d $IP --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
18. done
19.
20. for port in $SERV_UDP; do
21. if test $port -eq 53
22. then
23. $IPT -A INPUT -i $IF -p udp -s $NET --sport $port -d $IP --dport $port -m state --state NEW,ESTABLISHED -j ACCEPT
24. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $port -m state --state ESTABLISHED -j ACCEPT
25. else
26. $IPT -A INPUT -i $IF -p udp -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT
27. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
28. fi
29. done
30.
31. for port in $SERV_TCP; do
32. $IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT
33. $IPT -A OUTPUT -o $IF -p tcp ! --syn -s $IP --sport $port -d $NET --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
34. $IPT -A INPUT -i $IF -p tcp ! --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state ESTABLISHED -j ACCEPT
35. done
36.
37. $IPT -A INPUT -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_INPUT: "
38. $IPT -A INPUT -i $IF -d $IP -j DROP
39. $IPT -A OUTPUT -o $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_OUTPUT: "
40. $IPT -A OUTPUT -i $IF -d $IP -j DROP
41. $IPT -A FORWARD -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_FORWARD: "
42. $IPT -A FORWARD -i $IF -d $IP -j DROP
6. Phân tích: 
– Dòng 1, 2, 3: Đã phân tích trong bài trước (case 1).
4. NET="any/0"
– Dòng 4: Ấn định giá trị của biến NET. Đối với iptables, việc ấn định NET=any/0 và ứng dụng trong firewall script không cần thiết (bị thừa) vì nếu không ấn định cụ thể giá trị source (-s) và destination (-d) thì được ngầm hiểu là any/0. Giá trị NET dùng ở đây với mục đích làm rõ các luật trên phương diện gói tin đến và đi.
5. DNS="xxx.xxx.xxx.xxx yyy.yyy.yyy.yyy.yyy"
– Dòng 5: Ấn định giá trị của biến DNS. Đây là một giá trị quan trọng cho trường hợp firewall trên máy đơn và có dịch vụ cho công cộng. Những dịch vụ cho công như web, mail… đều trực tiếp tương tác với cơ chế biên giải giữa IP và tên domain. Giá trị của biến DNS ở đây chính là các IP của một DNS server (biểu thị cho primary DNS và secondary DNS). DNS server này có thể là DNS do ISP cung cấp hoặc chính authoritative DNS –1– do bạn tạo ra. Các giá trị trong biến DNS này tách rời bởi khoảng trống (space) để tiện việc chạy lệnh sau này.
6. SERV_TCP="22 25 80 443 110"
– Dòng 6: Ấn định giá trị của biến SERV_TCP. Biến SERV_TCP chứa giá trị các cổng dịch vụ ở giao thức TCP được firewall mở và kiểm soát. Các giá trị này tách rời bởi khoảng trống. Bạn có thể thêm, bớt các giá trị tùy thích. Nên lưu ý cách ấn định giá trị các cổng trong biến SERV_TCP chỉ là một cách (trong nhiều cách), bạn có thể khai triển tùy thích, miễn sao iptables “biết được” những cổng nào cần mở và cần kiểm soát. Sử dụng phương thức này chỉ thích hợp cho các cổng dịch vụ có tính chất tương tự nhau và bạn muốn kiểm soát các cổng với chế độ tương tự nhau. Cách ứng dụng khác là ấn định mỗi luật một dòng thay vì nhóm lại trong vòng lặp.
7. SERV_UDP="53 123"
– Dòng 7: Ấn định giá trị của biến SERV_UDP. Tương tự như trên, biến SERV_UDP chứa các giá trị cổng dịch vụ ở giao thức UDP được firewall mở và kiểm soát. Riêng phần biến SERV_UDP này có chứa cổng 53 mang tính chất khá đặc biệt so với các cổng dịch vụ khác. Vấn đề này sẽ được bàn sâu hơn cho dòng 20, 21, 22. Tất nhiên bạn không phải quan tâm đến nó nếu bạn không cung cấp dịch vụ DNS từ máy chủ của mình.
8. HI_PORTS="1024:65535"
– Dòng 8: Ấn định giá trị của biến HI_PORTS. Trong bài viết cho case 1, giá trị này không được nêu lên và sử dụng một cách cụ thể. Trái lại, nó được sử dụng ở đây với mục đích làm rõ các luật bảo vệ và kiểm soát những gói tin ra / vào cần được huy động tới giá trị của biến HI_PORTS này. Cần nói thêm, giá trị của biến HI_PORTS trải dài từ cổng 1024 đến cổng 65535 là các cổng thuộc chuỗi “high ports” hay “unprivileged ports”. Mở một socket trong chuỗi cổng này không cần đến quyền hạn root (trên *nix nói chung) và đây là một trong những điểm quan trọng của việc áp đặt chuỗi HI_PORTS trong firewall script sau này.
– Dòng 10, 11, 12, 13: Đã phân tích trong bài trước (case 1).
15. for entry in $DNS; do
16. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $HI_PORTS -d $entry --dport 53 -m state --state NEW -j ACCEPT
17. $IPT -A INPUT -i $IF -p udp -s $entry --sport 53 -d $IP --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
18. done
– Dòng 15-18: Bốn dòng này thuộc một vòng lặp, đặc biệt dùng để xác lập các dòng luật cho phép máy đơn (ở trường hợp này) liên hệ đến các DNS servers (đã ấn định ở biến $DNS ở trên). Đây là nhóm luật hết sức quan trọng và sẽ được các chương trình cung cấp dịch vụ trên máy dùng đến thường xuyên cho nên việc xác định luật này đầu tiên là việc cần thiết.
– Diễn dịch nôm na vòng lặp của dòng 15, 16, 17 và 18 như sau: với mỗi giá trị thuộc biến $DNS, chạy hai dòng 16 và 17 cho đến khi không còn giá trị nào nữa.
16. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $HI_PORTS -d $entry --dport 53 -m state --state NEW -j ACCEPT
– Dòng 16 có ý nghĩa như sau: cho phép các gói tin với giao thức UDP đi ra ngoài bằng IP hiện có xuyên qua IF. Các gói tin này được khởi tạo từ một socket thuộc chuỗi HI_PORTS (nguồn –sport) và đi đến các địa chỉ DNS server đã ấn định trong biến $DNS đến cổng 53 (đích –dport). Thêm vào đó, các gói tin này phải ở tình trạng NEW (trong state table được iptables quản lý). Điều này có nghĩa firewall cho phép máy chủ –2– này khởi tạo các truy cập đến các DNS server đã ấn định (xxx.xxx.xxx.xxx và yyy.yyy.yyy.yyy).
17. $IPT -A INPUT -i $IF -p udp -s $entry --sport 53 -d $IP --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
– Dòng 17 có ý nghĩa như sau: cho phép các gói tin với giao thức UDP từ các DNS server đã ấn định được đi đến IP hiện có xuyên qua IF. Các gói tin này được phép trả lời từ cổng 53 của DNS server ấy. Các gói tin ở dạng trả lời này phải ở tình trạng ESTABLISHED (trong state table được iptables quản lý). Điều này có nghĩa firewall cho phép các DNS server đã được ấn định trả lời các truy cập được khởi tạo từ máy chủ. Các gói tin ở tình trạng NEW đến từ các DNS server sẽ bị từ chối.
20. for port in $SERV_UDP; do
21. if test $port -eq 53
22. then
23. $IPT -A INPUT -i $IF -p udp -s $NET --sport $port -d $IP --dport $port -m state --state NEW,ESTABLISHED -j ACCEPT
24. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $port -m state --state ESTABLISHED -j ACCEPT
25. else
26. $IPT -A INPUT -i $IF -p udp -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT
27. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
28. fi
29. done
– Dòng 20-29: tương tự như nhóm dòng 15-18, dòng 20-29 thuộc một vòng lặp để xác lập luật cho các cổng thuộc biến $SERV_UDP cho giao thức UDP. Trong vòng lặp này chứa một một cụm điều kiện cách (if / else) để thử nghiệm và ứng dụng đúng luật thích ứng cho cổng dịch vụ.
– Diễn dịch nôm na vòng lặp 20-29 như sau: với mỗi giá trị thuộc biến $SERV_UDP, chạy các dòng lệnh 23 và 24 nếu một trong những giá trị thuộc biến $SERV_UDP là 53. Nếu không thì chạy các dòng lệnh 26 và 27 cho đến khi không còn giá trị nào nữa.
23. $IPT -A INPUT -i $IF -p udp -s $NET --sport $port -d $IP --dport $port -m state --state NEW,ESTABLISHED -j ACCEPT
– Dòng 23 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi vào từ bất cứ nơi đâu từ cổng 53 đến cổng 53 của máy chủ. Các gói tin này phải đi đến $IP hiện có xuyên qua $IF và phải ở tình trạng NEW.
24. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $port -m state --state ESTABLISHED -j ACCEPT
– Dòng 24 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi ra từ cổng 53 của máy chủ đến cổng 53 của máy đã đòi hỏi truy cập và đã được firewall tiếp nhận ở dòng 22. Các gói tin đi ra ngoài này phải ở tình trạng ESTABLISHED.
26. $IPT -A INPUT -i $IF -p udp -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT
– Dòng 26 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi vào từ cổng nào đó thuộc dãy $HI_PORTS đến cổng đã ấn định trong biến $SERV_UDP của máy chủ. Các gói tin này phải ở tình trạng NEW.
27. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
– Dòng 27 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi ra từ cổng đã ấn định trong biến $SERV_UDP (và không phải là cổng 53) của máy chủ đến cổng nào đó thuộc dãy $HI_PORTS dùng để truy cập và đã được firewall tiếp nhận ở dòng 25. Các gói tin đi ra ngoài này phải ở tình trạng ESTABLISHED.
– Dòng 31-35: tương tự như nhóm dòng 20-29. Đây cũng là một vòng lặp dùng để xác lập luật cho các cổng thuộc biến $SERV_TCP cho giao thức TCP. Vòng lặp này không chứa cụm điều kiện cách như nhóm dòng 20-29 vì các cổng dịch vụ đã ấn định trong biến $SERV_TCP mang tính chất tương tự nhau –3-.
31. for port in $SERV_TCP; do
32. $IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT
33. $IPT -A OUTPUT -o $IF -p tcp ! --syn -s $IP --sport $port -d $NET --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
34. $IPT -A INPUT -i $IF -p tcp ! --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state ESTABLISHED -j ACCEPT
35. done
– Diễn dịch nôm na vòng lặp 31-35 như sau: với mỗi giá trị thuộc biến $SERV_TCP, chạy các dòng 32, 33 và 34 rồi lặp lại cho giá trị kế tiếp trong biến $SERV_TCP cho đến khi không còn giá trị nào khác.
– Dòng 32 có ý nghĩa như sau: các gói tin ở dạng TCP với cờ hiệu (TCP Flag) là SYN –4– đi vào từ bất cứ nơi nào từ một cổng ở dãy $HI_PORTS đến $IP hiện có xuyên qua $IF để đến cổng $port (giá trị hiện tại của vòng lặp) và ở tình trạng NEW thì tiếp nhận.
– Dòng 33 có ý nghĩa như sau: các gói tin ở dạng TCP không mang cờ hiệu là SYN đi từ $IP hiện có từ cổng $port (giá trị hiện tại của vòng lặp) trả lời cho gói tin yêu cầu truy cập ở trên (đi ra) và ở tình trạng ESTABLISHED thì tiếp nhận.
– Dòng 34 có ý nghĩa như sau: các gói tin ở dạng TCP với cờ hiệu không phải là SYN đi từ nơi gởi gói tin yêu cầu truy cập trên (tiếp tục) đi vào đến cổng $port của $IP hiện có và ở tình trạng ESTABLISHED thì tiếp nhận.
– Dòng 37-42: clean up rules. Đã phân tích ở case 1.
7. Tổng lượt dạng firewall trên: 
Đây là dạng firewall được thiết lập cho một máy đơn hỗ trợ dịch vụ. Điểm cốt lõi và khác biệt giữa dạng này và dạng máy đơn không dịch vụ (như ở case 1) là máy đơn hỗ trợ dịch vụ tiếp nhận yêu cầu truy cập và chỉ trả lời yêu cầu truy cập khi những yêu cầu thoả mãn những luật iptables đưa ra (ngoại trừ luật tạo ra ở dòng 16 và 17). Trong khi đó, máy đơn của case 1 mang vai trò yêu cầu truy cập và các dịch vụ bên chỉ có thể trả lời nếu máy đơn này đòi hỏi.
Thử xét luật ở dòng 16 và 17 thì thấy, máy chủ này cần phải khởi tạo một xuất truy cập đến DNS server (và chỉ cụ thể những DNS server được ấn định trong biến $DNS mà thôi). Các DNS server này cũng chỉ có thể trả lời yêu cầu từ máy chủ khi máy chủ “hỏi” và tất nhiên, các DNS server khác sẽ không có cơ hội “trả lời” vì chúng không nằm trong phạm vi cho phép. Điều này cho thấy, máy chủ của chúng ta tin tưởng vào thông tin mà DNS server đã ấn định cung cấp. iptables không thể hạn chế thông tin của các DNS server này cung cấp, ngay cả khi chúng bị hư hoại (poisoned cache chẳng hạn). Ví dụ, http://www.mypage.net giả định được biên giải thành 123.123.123.123 nhưng DNS server ấy bị nhân nhượng nên http://www.mypage.net được biên giải thành 124.124.124.124 chẳng hạn thì máy chủ của chúng ta vẫn tiếp nhận gói tin chứa các thông tin này (nếu như chúng thoả mãn các điều kiện iptables đặt ra trên cấp độ ip).
Dòng 23 và 24 có vài điểm cần phân tích. Luật đưa ra ở hai dòng này dùng để kiểm soát và thoả mãn giao thức giữa dịch vụ DNS chạy trên máy chủ của chúng ta và các DNS server khác (server to server). Bởi vậy, thông tin đi và đến xuyên qua cổng 53 từ hai phía (thay vì từ một cổng thuộc $HI_PORTS đến cổng 53 và ngược lại). Đó là lý do tại sao chúng ta phải dùng đến cụm điều kiện cách if / else ở đây. Điểm cốt lõi của hai dòng lệnh này là đưa ra luật kiểm soát cho dịch vụ DNS giữa server và server. Máy chủ cung cấp dịch vụ DNS hầu hết chỉ cần “lắng nghe” và “trả lời” trên cổng 53 UDP ngoại trừ trường hợp một yêu cầu nào đó quá lớn hoặc một yêu cầu cho zone transfer thì mới cần đến cổng 53 TCP –5
Dòng 26 và 27 tương tự như trên nhưng luật đưa ra dùng để kiểm soát gói tin giữa các clients từ bên ngoài và máy chủ (client to server). Tất nhiên các luật này không ứng dụng cho dịch vụ DNS vì đi đến hai dòng này đã thoát ra ngoài cụm điều kiện cách dùng cho DNS ở trên. Ở đây, thông tin đi xuyên qua cổng 53 của máy chủ và $HI_PORTS của máy con.
Dòng 32, 33, 34 có một số điểm lý thú cần bàn đến. Dựa trên tính “stateful” của giao thức TCP, iptables có thể kiểm soát các gói tin TCP sâu sát hơn UDP rất nhiều.
– Dòng 32 chỉ định rất cụ thể là các gói tin ở tình trạng NEW –6– và có tcp-flags là SYN,RST,ACK SYN thì mới được tiếp nhận. Điều này có nghĩa: một yêu cầu truy cập hoàn toàn mới bằng giao thức TCP thì phải có SYN bit và đối với iptables, gói tin khởi đầu cho một cuộc truy cập hoàn toàn mới vì nó chưa hề có trong bảng theo dõi của netfilter (conntrack table). Vậy nếu một gói tin muốn đi vào (truy cập) nhưng chưa hề có trong bảng theo dõi của netfilter (NEW) và không có SYN bit thì sao? Câu trả lời là tất nhiên iptables sẽ chặn nó lại như theo luật đưa ra ở dòng 32 và đây là điều tốt vì các truy cập hợp lệ (legitimate request) không thể có trường hợp một request mới mà không khởi đầu từ SYN. Trường hợp gói tin ở tình trạng NEW nhưng không có SYN bit rất hiếm thấy (ngoại trừ cố tình tạo ra gói tin ở dạng này để thử thâm nhập). Những gói tin ở trường hợp này đôi khi xuất hiện nếu bạn thiết kế hệ thống “high availability” –7– cho nhiều firewall và các firewall này vì lý do nào đó “lỡ” không chuyển giao các “state” của những gói tin hiện lưu hành xuyên qua firewall nên một gói tin nào đó đang ở tình trạng ESTABLISHED với firewall này có thể ở tình trạng NEW với firewall kia. Nếu iptables nằm trong vùng làm việc của các firewall trên thì thỉnh thoảng sẽ va phải một số gói tin như thế và đây là trường hợp (legitimate) rất ít xảy ra.
– Dòng 33 và 34 dùng để hỗ trợ dòng 32 và tiêu điểm của luật trên hai dòng này là dấu chấm thang (!) đi trước –syn. Chuyện gì sẽ xảy ra ở đây? Ở dòng 32, chúng ta ấn định các gói tin TCP đi vào mang SYN flag và ở tình trạng NEW thì được tiếp nhận, vậy sau khi được tiếp nhận thì chuyện gì tiếp tục xảy ra? Câu trả lời nằm ở dòng 33:
+ các gói tin đi ra ngoài để trả lời mà không mang SYN flag –8– và ở tình trạng ESTABLISHED thì được tiếp nhận. Điều cần nhấn mạnh ở đây là gói tin trả lời đi từ máy chủ của chúng ta không nên là gói tin mang SYN flag bởi vì không có lý do gì để máy chủ phải gởi yêu cầu truy cập đến một máy con nào đó trên Internet. Máy chủ chúng ta dùng để tiếp nhận và trả lời các yêu cầu truy cập cho nên luật ở dòng 33 ngầm chứa một quy định rất khắc khe: không những luật firewall cho máy chủ này chỉ tiếp nhận những yêu cầu đi vào một cách hợp lệ mà còn ngăn ngừa những lưu thông đi ra từ máy chủ một cách thiếu hợp lệ (thử hình dung vì lý do gì đó, máy chủ của chúng ta bị biến thành “zombie” và liên tục gởi SYN request đến các máy khác).
+ tình trạng ESTABLISHED kèm theo trong lệnh này càng nâng cao mức khắc khe. Đối với conntrack table lúc này, gói tin đi ra từ máy chủ để trả lời một yêu cầu truy cập nào đó phải thuộc dạng ESTABLISHED. –syn ở đây ứng dụng cụ thể cho gói tin thuộc giao thức TCP và –state ESTABLISHED ở đây ứng dụng cụ thể cho tính “stateful” của netfilter.
– Dòng 34 tiếp nối hai dòng lệnh trên. Ở giai đoạn này, gói tin đi vào máy chủ và thuộc xuất truy cập hiện tại phải ở tình trạng ESTABLISHED và không mang SYN flag nữa và đây chính là điều được dòng 33 áp đặt. Từ lúc này trở đi, trong suốt xuất truy cập, luật của dòng 33 và 34 điều tác và kiểm soát lưu thông giữa máy con và máy chủ của chúng ta. Cụ thể hơn:
+ nếu cũng từ một IP (cùng một client) gởi một gói tin mang SYN flag và hợp lệ thì nó sẽ được xếp loại NEW và được dòng lệnh 32 “xét xử”.
+ nếu cũng từ một IP (cùng một client) gởi một gói tin mang một TCP flag nào đó thiếu hợp lệ và không nằm trong tình trạng được theo dõi bởi conntrack table thì nó bị loại trừ bởi các dòng trong nhóm 37-42 hoặc được quy chế mặc định của firewall xử (còn nhớ -P?).
8. Mở rộng: 
Mở rộng? rộng thế nào? Khó có thể trả lời câu hỏi này thoả đáng vì không có sự cố hoặc nhu cầu thì khó biết được giải pháp? (no solution for unknown problem). Tuy nhiên có vài vấn đề có thể mở rộng một cách tổng quát và ứng dụng cho đa số các trường hợp.
8.1 Vấn đề chung cho mọi giao thức:
8.1.1 Vấn đề các gói tin ở tình trạng INVALID:
Như đã phân tích các tình trạng NEW,RELATED,ESTABLISHED,VALID trong bảng theo dõi của netfilter ở bị chú số 6 (bên dưới). Các gói tin ở tình trạng NEW,RELATED,ESTABLISHED có thể được tiếp nhận tùy theo hoàn cảnh. Tuy nhiên, gói tin ở tình trạng INVALID trên bình diện SPI (xem chú thích về SPI ở case 1), không thể được tiếp nhận với bất cứ lý do nào. Bởi vậy, hai dòng luật như sau có thể đưa vào phía trên dòng 15:
$IPT -A INPUT -m state --state INVALID -m limit --limit 1/s -j LOG --log-prefix "INVALID_STATE: "
$IPT -A INPUT -m state --state INVALID -j DROP
Dòng trên dùng để log và dòng kế tiếp chính thức cản các gói tin thuộc dạng này. Điểm cần chú ý ở đây là hai dòng lệnh trên không quy định cụ thể loại giao thức nào (bằng thông số -p) cho nên các luật này ứng hiệu cho mọi giao thức. Dòng trên cản phần lớn các gói tin “lạc loài” đi vào firewall với chủ đích hoặc vô tình. Cách áp đặt luật này phía trên dòng 15 không những log và cản các gói tin vi phạm cụ thể mà còn mang tính hiệu năng. Các gói tin vi phạm sẽ bị cản ngay tại vị trí này thay vì tiếp tục đi xuống cho đến khi nào trùng với một luật xử lý nào đó, nếu không thì chúng sẽ tiếp tục đi xuống đến tận chuỗi “clean-up” rule (rồi cũng sẽ bị log và cản). Để duy trì tính an toàn, chúng không nên được phép đi vào.
8.1.2 Vấn đề mạo danh IP của máy chủ:
Kỹ thuật mạo danh IP của một máy nào đó được gọi là “spoofing” theo thuật ngữ chuyên môn. “Spoofing” có nhiều dạng và nhiều mục đích nhưng ở đây chúng ta chỉ đề cập đến trường hợp “ai đó” từ Internet mạo danh địa chỉ của máy chủ chúng ta với mục đích “lừa” firewall mà lẻn vào. Thủ thuật này có độ thành công rất cao khi “thử nghiệm” trên các máy chủ và ngay cả các firewall nếu không điều chỉnh cẩn thận. Thử xét:
$IPT -A INPUT -i $IF -s $IP -d $IP -m limit --limit 1/s -j LOG --log-prefix "SPOOFING: "
$IPT -A INPUT -i $IF -s $IP -d $IP -j DROP
Các gói tin đi từ bên ngoài vào xuyên qua $IF và từ $IP không thể đến $IP được. Vả lại, làm sao có thể có gói tin được chính IP của máy chủ chúng ta tạo ra lại đi vào từ Internet? Nên nhớ, các gói tin được tạo ra ngay trên chính máy chủ cho chính máy chủ đều đi xuyên qua địa chỉ loopback (127.0.0.1) xuyên qua loopback interface (lo), cho nên, các gói tin đi từ bên ngoài mà mang IP của chính máy chủ chúng ta thì chắc chắn thuộc dạng “spoofing”. Tất nhiên để có thể lẻn vào bằng phương thức “spoofing” này, kẻ muốn xâm nhập cần nhiều dữ kiện và điều kiện hơn là chỉ đơn thuần “spoofing” vì SPI là hàng rào cản đầu tiên (xem INVALID state ở trên).
8.2 Vấn đề thuộc giao thức TCP:
8.2.1 Loại trừ các truy cập mang tính thiếu hợp lệ
Thử mở rộng một vài TCP flags như đã bàn đến trong phần 7 ở trên –9
a. $IPT -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -s $NET -j DROP
Một gói tin mang tcp flag SYN và FIN cùng một lượt không thể là một gói tin bình thường và hợp lệ. SYN-FIN chỉ thường thấy ở các thao tác rà cổng (port scan) hoặc được dùng với ý định không trong sáng. Gói tin ở dạng này nên loại trừ trước khi đi sâu vào hệ thống. Nếu cần phải log, bạn chỉ cần áp đặt một dòng luật tương tự với target là LOG ở trên.
b. $IPT -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -s $NET -j DROP
Một gói tin mang tcp flag FIN và RST cùng một lượt cũng có thể được xem bất hợp lệ. FIN flag trong một gói tin hợp lệ dùng để thông báo đầu bên kia dòng tin được chấm dứt để xuất truy cập được kết thúc đúng quy cách. Trong khi đó, RST flag dùng để “xé” ngang một xuất truy cập bất chợt. Trường hợp FIN và RST cùng trong một gói tin là điều bất thường và không nên tiếp nhận.
Trường hợp a, b và các trường hợp tương tự đều có thể tạo những tác động không tốt đến dịch vụ trên máy chủ. Chúng khiến cho hệ thống trên máy chủ phải làm việc nhiều hơn một cách không cần thiết và một số trường hợp các gói tin được “nắn ép” cẩn thận có thể dung hại nặng nề đến hệ thống. Tương tự như đã phân tích ở phần 8.1, hai dòng này nên đặt trên dòng 15 (hoặc trên các dòng lệnh bắt đầu cho phép tiếp nhận gói tin) để mang lại tính cụ thể và hiệu năng khi đưa ra các luật cụ thể.
8.2.2 Cản và log cụ thể cho TCP:
Trên dòng chúng ta cho phép các gói tin TCP đi vào phải mang SYN flag và ở tình trạng NEW. Tất nhiên, các gói tin không thoả mãn quy định trên sẽ bị log và cản ở dòng luật 37, 38. Nếu chúng ta không cần phải log chi tiết chuyện gì xảy và thì đoạn firewall script ở trên vừa đủ để hoạt động. Tuy nhiên, nếu chúng ta cần log và cản các gói tin vi phạm một cách cụ thể thì sao?
$IPT -A INPUT -p tcp ! --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -m limit --limit 1/s -j LOG --log-prefix "INVALID_SERVICE_REQUEST: "
$IPT -A INPUT -p tcp ! --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j DROP
Hai dòng trên là câu trả lời. Các gói tin TCP không mang SYN flag mà ở tình trạng NEW thì bị log và bị cản một cách cụ thể. Hai dòng này có thể được đưa vào phía trên dòng 32 (còn nhớ đến tính quan trọng với thứ tự của các luật?). Tất nhiên, tính cụ thể và hiệu năng sẽ được hình thành nếu áp đặt chúng ở đúng vị trí.
8.2.3 Loại trừ các truy cập hợp lệ nhưng nguy hại
Có lẽ bạn sẽ hỏi, tại sao các truy cập đã hợp lệ mà lại có thể nguy hại. Cho đến lúc này, chúng ta chỉ áp đặt các luật để cản những gói tin bất hợp lệ. Tuy nhiên, không nhất thiết các gói tin hợp lệ trên bình diện giao thức cũng hợp lệ trên bình diện tinh thần. Trường hợp điển hình nhất là phương thức xử dụng các gói tin hợp lệ để làm cạn kiệt tài nguyên của máy chủ. Thử hình dung trường hợp 1000 truy cập đến máy chủ trong vòng vài giây (chẳng hạn),
– liệu máy chủ đủ sức đáp ứng hay không?
– trong 1000 truy cập này, có bao nhiêu truy cập với “thiện ý” và bao nhiêu với “ác ý”?
– làm sao phân biệt và xử lý những truy cập “ác ý” trong mớ 1000 truy cập ấy?
Trên thực tế, khó có thể phân biệt một cách chính xác các truy cập thiện ý hoặc ác ý nhưng chúng ta có thể biết được những truy cập thiện ý thường có biên độ nhất định –10
8.2.3.1 Giới hạn truy cập với “connection rate”
“Connection rate” có thể thực hiện bằng chọn lựa -m limit cho bất cứ giao thức nào. Chúng ta chỉ đề cập ở đây cho giao thức TCP và sẽ ứng dụng cho các giao thức khác theo ý muốn. Thử đổi dòng 32 từ:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT
trở thành:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m limit --limit 3/s --limit-burst 5 -m state --state NEW -j ACCEPT
Chuỗi -m limit –limit 3/s –limit-burst 3 dùng CONFIG_IP_NF_MATCH_LIMIT trên netfilter, một “match” trong gói căn bản và đã được tích hợp vào Linux kernel. “limit match” này ảnh hưởng lớn lao đến dòng lệnh trên bình diện giới hạn “connection rate”. Chuỗi này ấn định các gói tin mang SYN flag từ một IP nào đó truy cập đến cổng dịch vụ của máy chủ ở tình trạng NEW. Trong chuỗi -m limit –limit 3/s –limit-burst 3 này, khi ứng dụng trong dòng lệnh, một gói tin sẽ được xử lý theo cơ chế:
–limit-burst ấn định giá trị số lần (cho phép hoặc không cho phép) một gói tin được đi đến bước kế tiếp trong luật (-j ACCEPT hoặc -j DROP hoặc bất cứ “jump to” nào). Mỗi giá trị của –limit-burst là một “giấy phép”, mỗi packet trùng với luật này sẽ dùng hết một “giấy phép”. Khi –limit-burst bằng 0, gói tin trùng với luật đã hết “giấy phép”, thì mọi gói tin mới đi vào dù có trùng với luật quy định hay không đều sẽ không thể “jump” đến target ACCEPT (và do đó sẽ bị DROP bởi policy của firewall hoặc các luật đi theo sau). Vì lý do này, –limit 3/s chính là cơ chế “nạp” giấy phép lại cho –limit-burst. Chuỗi này có ý nghĩa là mỗi 1/3 giây, sẽ tăng –limit-burst lên 1, cho đến khi đạt giá trị tối đa ban đầu (= 3 trong trường hợp này) thì sẽ không tăng nữa.
Cụ thể hơn, tưởng tượng đang có một máy con nào đó truy cập vào máy chủ của chúng ta với tốc độ 50 packet/giây, có nghĩa là cứ 1/50 giây có một packet đi đến máy chủ. Rule trên sẽ xử lí như sau:
-Trong vòng (1/50)*5 = 1/10 giây đầu tiên, 5 giấy phép ban đầu đã được sử dụng hết, gọi thời điểm này là T1 (chẳng hạn). Từ thời điểm T1 trở đi cho đến thời điểm T1+1/3 giây, tất cả packet từ IP này truy cập vào máy chủ sẽ bị DROP.
-Tại thời điểm T1 + 1/3 giây, do qui định của chuỗi –limit 3/s, một giấy phép được nạp vào cho –limit-burst, nhưng gần như ngay tức khắc, giấy phép này được một packet của máy A sử dụng và do đó –limit-burst lại trở về 0 (tiếp tục hết “giấy phép”). Cứ tiếp tục như thế, sau 1/3 giây, sẽ có một packet được chấp nhận và chỉ 1 mà thôi nếu máy A cứ tiếp tục truy cập với tốc độ như trên vào máy chủ.
Nếu máy con ngừng truy cập vào máy chủ thì diễn biến sẽ như sau:
– Cứ sau 1/3 giây, một giấy phép sẽ được nạp vào –limit-burst, và vì bây giờ không còn packet nào được gửi đến do đó –limit-burst sẽ giữ nguyên giá trị. Cứ thể –limit-burst tăng dần cho đến khi chạm quy định ban đầu là 3 thì sẽ ngừng lại, “giấy phép” hoàn toàn ở tình trạng nguyên thuỷ. Trong thời gian –limit-burst tăng lại giá trị ban đầu, nếu máy A lại tiếp tục gửi packet thì những packet này sẽ sử dụng giấy phép trong limit-burst, và lại giảm limit-burst xuống, nếu limit-brust bằng 0 thì tất nhiên firewall sẽ tiếp tục cản các gói tin ở dạng này nếu vẫn tiếp tục vi phạm luật cho đến khi –limit-burst được giải toả (như đã giải thích).
Đây chỉ là một ví dụ minh hoạ ứng dụng -m limit. Bạn cần khảo sát số lượng truy cập đến dịch vụ nào đó trên máy chủ trước khi hình thành giá trị thích hợp cho -m limit. Nên cẩn thận trường hợp một proxy server chỉ có một IP và có thể có hàng ngàn người dùng phía sau proxy; ghi nhận yếu tố này để điều chỉnh limit rate cho hợp lý.
Bài viết tham khảo tại: vniss.wordpress.com
thudinh Network and Security

No comments:

Adsense

Translate