Powered by Blogger.

IPTABLES TUTORIAL ( CONT.)

GIT – iptables là một chương trình chạy ở không gian người dùng, cho phép người quản trị hệ thống có thể cấu hình các bảng của tường lửa trong nhân Linux (được cài đặt trong các mô đun Netfilter khác nhau) và lưu trữ các chuỗi, luật. Các mô đun nhân và chương trình khác nhau được áp dụng cho từng giao thức; iptables cho IPv4, ip6tables cho IPv6, arptables cho ARP, và ebtables cho Ethernet frames.

Case 1 – iptables và máy đơn
Trường hợp điển hình thứ nhất trong việc ứng dụng iptables để bảo vệ.
1. Trường hợp:
Firewall đơn giản cho một máy đơn.
2. Nhu cầu:
Bảo vệ máy đơn không bị rà và truy cập trong khi kết nối vào Internet. Máy đơn này không cung cấp dịch vụ cho những máy bên ngoài truy cập vào.
3. Phương pháp kết nối:
Modem, xDSL, Cable.
Đò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 (xuyên qua modem, xDSL, cable….) và có thể duyệt Internet hoàn chỉnh.
4. Mô hình:
– nếu là modem, ppp0 là external interface.
– nếu là xDSL, có hai trường hợp: ppp0 là external interface (nếu ISP ứng dụng PPPOE) hoặc eth0 là external interface (nếu ISP dùngDHCPD để assign IP cho user).
– nếu là cable, eth0 là external interface, IP address thường được phân bố qua DHCP.
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.
5. $IPT -F
6. $IPT -P INPUT DROP
7. $IPT -P OUTPUT DROP
8. $IPT -P FORWARD DROP
9.
10. $IPT -A OUTPUT -o $IF -s $IP -j ACCEPT
11. $IPT -A INPUT -i $IF -d $IP -m state –state ESTABLISHED,RELATED -j ACCEPT

6. Phân tích:
– Dòng 1: Ấn định giá trị của biến IF bằng chuỗi lệnh ngầm, chuỗi lệnh này xác định network interface nào được gán với default gateway. Khi IF này ứng động và được phân bố một địa chỉ IP, nó cũng chính là default gateway ra vào của các packets trong quá trình truy cập Internet.
– Dòng 2: Ấn định giá trị của biến IP bằng chuỗi lệnh ngầm. Giá trị này được hiện hữu khi interface ở trên ứng động và kết nối vào dịch vụ cung cấp Internet. Đây là một chuỗi lệnh dùng để “tách” lấy giá trị IP hiện có trên IF. Nó tiện dụng vì bạn không cần phải điều chỉnh firewall script này mỗi khi IP address thay đổi.
– Dòng 3: Ấn định giá trị của biến IPT chỉ cho vị trí chứa iptables binary. Dùng cách này có hai điểm tiện là không phải gõ trọn bộ đường dẫn đến nơi chứa iptables và nếu nơi chứa iptables thay đổi vì lý do nào đó thì chỉ cần thay đổi ở biến này.
– Dòng 4: Dòng trống có chủ ý cho dễ nhìn.
– Dòng 5: Lệnh iptables với thông số -F có tác dụng xoá dội các chains còn vương vãi đâu đó (nếu có) khi firewall script này khởi tác. Đây là một lệnh thuộc dạng “house-keeping” (bảo trì) để gìn giữ tính trung thực và chính xác của các “rules” do iptables tạo ra. -F (flush) là một bước nên thực hiện vì mỗi lượt firewall script này được chạy, những rules cần thiết sẽ được ứng dụng và những rules không cần dùng (và còn vương vãi trên memory) sẽ bị loại bỏ.
– Dòng 6-7-8: Ba dòng trông đơn giản này kỳ thật đóng vai trò tối quan trọng. Tác dụng của mục tiêu DROP ở đây với thông số -P dùng để thiết lập chế độ (policy) cản mọi lưu thông trước khi cho phép loại lưu thông cụ thể nào đó được ra hoặc vào. DROP Policy là phương cách ngăn chặn vững nhất bởi vì những gì không cho phép sẽ bị cản. Chỉ có những gì được cho phép một cách cụ thể thì mới được đi qua. Hay nói một cách khác, khi một packet đi vào (hoặc đi ra) mà không có rule nào thích ứng cụ thể cho tính chất của packet này thì nó sẽ bị cản (DROP) theo chế độ chung của firewall.
Diễn dịch luật này thành ngôn ngữ bình thường như sau: theo chế độ mặc định (-P), các chains INPUT, OUTPUT và FORWARD hoàn toàn từ chối (DROP) mọi lưu thông.
– Dòng 9: Dòng trống có chủ ý cho dễ nhìn.
– Dòng 10: Đây là dòng xác định OUTPUT rule cho mọi packet đi ra từ IP và IF (đã xác định ở dòng 1 và 2). Rule này cho phép mọi packet, mọi loại giao thức (protocol) đi từ IP xuyên qua IF được phép đi ra ngoài. Với iptables, nếu bạn không xác định cụ thể loại giao thức (-p) trong một rule thì nó mang giá trị ngầm là mọi giao thức. Đây là một rule rất thư giãn vì nó hoàn toàn không giới hạn cho những packet đi ra, miễn sao nó đi ra từ IP và xuyên qua IF đã định. Đối với người dùng cá nhân, rule này rất thích hợp vì bạn không muốn tự hạn chế đường ra (ngoại trừ bạn có dụng ý bảo mật khác).
Diễn dịch luật này thành ngôn ngữ bình thường như sau: mọi packets từ IP hiện dụng (-s $IP) xuyên qua interface eth0 (-o $IF) đi ra ngoài thì được chấp nhận (-j ACCEPT).
– Dòng 11: Đây là dòng xác định INPUT rule cho mọi packet đi đến IP và IF (đã xác định ở dòng 1 và 2). Rule này chỉ khác OUTPUT rule ở thông số và giá trị thông số -m state –state ESTABLISHED,RELATED. Điểm tối quan trọng cũng nằm ở đây. Nếu rule trên không có thông số và giá trị của thông số -m state thì firewall này hoàn toàn vô dụng bởi vì nó cho phép bất cứ giao thức nào, ở tình trạng nào cũng có thể lưu thông. Với -m state, packets đi vào sẽ được kiểm duyệt tình trạng của packets thoả mãn điều kiện ESTABLISHED hoặc RELATED. Cũng nên đào sâu vài điểm về tình trạng ESTABLISHED và RELATED ở đây:
– Một packet ở tình trạng ESTABLISHED có nghĩa nó thuộc một xuất truy cập (connection) đã hình thành và xuất truy cập này đã có diễn tiến trao đổi các packet từ hai phía “gởi và nhận”. Với các luật ở dòng 10 và 11, chúng ta dễ thấy chỉ có packet từ firewall đi ra mới có thể ở tình trạng NEW để khởi tạo một xuất truy cập. Hay nói một cách khác, firewall của bạn “hỏi” thì đối tượng nào đó từ Internet mới “trả lời”.
Packet ở tình trạng ESTABLISHED có nghĩa là nó đã thông qua giai đoạn “hỏi / trả lời” một cách hợp thức. Điều này cũng có nghĩa, packets từ bên ngoài đi đến $IP xuyên qua $IF sẽ không được tiếp nhận ở tình trạng NEW và INVALID cho nên các packets nào “hỏi” (NEW) hoặc “chen ngang” (INVALID) từ bên ngoài đến firewall sẽ bị chặn (tham khảo thêm tài liệu căn bản về iptables cho 4 states được sử dụng).
– Packet ở tình trạng RELATED không thấy nhiều như packet ở tình trạng ESTABLISHED bởi vì RELATED packet chỉ xuất hiện khi một xuất truy cập mới cần được thiết lập dựa trên tình trạng một xuất truy cập đang có đã được thiết lập một cách hợp pháp.
Loại packet này có thể thấy ở giao thức FTP sau khi phân đoạn kết nối và xác minh người dùng (authentication) trên cổng 21 đã hoàn thành và cần thiết lập cổng dữ liệu 20 để chuyển tải dữ liệu. Ở đây, vì giao thức qua cổng 21 ở dạng ESTABLISHED cho nên cổng 20 được phép thiết lập thêm và phân đoạn này tạo ra packet thuộc dạng RELATED. Packet ở tình trạng RELATED cũng thường thấy ở các ICMP packets ở dạng trả lời (replies).
– -m state ở trên là một trong những tính năng thuộc dạng SPI -1- (stateful packet inspection – kiểm soát đa thể trạng) của iptables. Trước đây, với kernel 2.2.x series và ipchains (tiền thân của iptables), các packets được kiểm soát ở giới hạn loại packet và không thể kiểm soát ở biên độ tình trạng packet.
Tính năng đa thể trạng này không những giúp bạn đơn giản hoá nhóm luật cho firewall của mình mà còn tạo nên một firewall linh động và vững vàng hơn rất nhiều. Nếu không dùng -m state ở đây, ít nhất bạn phải mở một loạt cổng nào đó (dãy 32000 – 64000 chẳng hạn) để các packets từ bên ngoài có thể đi vào để “trả lời” các requests bạn tạo ra. Đây là một phương thức có thể tạo những điểm yếu cho firewall, đó là chưa kể đến tính luộm thuộm khi phải cho phép chuỗi cổng cho mỗi loại giao thức (tcp / udp) và loại icmp ra vào cho thích hợp.
Diễn dịch luật này thành ngôn ngữ bình thường như sau: mọi packets từ bên ngoài Internet đi vào IP hiện dụng (-s $IP) xuyên qua interface eth0 (-i $IF) vào trong máy ở chế độ ESTABLISHED,RELATED thì được chấp nhận (-j ACCEPT).
7. Tổng lượt dạng firewall trên:
Nhìn vào vài dòng luật của firewall trên, chắc chắn có người sẽ thắc mắc và sẽ hỏi chỉ có vậy thôi sao?.
Câu trả lời ngắn: chỉ có vậy nếu chỉ cần như vậy.
Câu trả lời dài: cho một máy đơn và người dùng được quyền gởi bất cứ yêu cầu truy cập trên bất cứ giao thức nào từ bên trong máy ra ngoài cũng như cản bất cứ yêu cầu truy cập trên mọi giao thức từ bên ngoài vào thì vài dòng luật như vậy là đủ. Như bạn biết, trong khi máy chạy trên Linux sẽ có một số dịch vụ đang lắng nghe (LISTEN). Những dịch vụ này chỉ phục vụ cho riêng bạn và bạn không muốn bất cứ ai từ Internet truy cập vào các dịch vụ này.
Luật ở dòng 11 ấn định: các packet đi vào (INPUT) chỉ có thể ở dạng ESTABLISHED và RELATED cho nên một đòi hỏi truy cập mới (new request) từ Internet vào không thể được hình thành. Khi một packet như vậy đi vào firewall, firewall sẽ kiểm tra xem có luật INPUT nào thích hợp cho phép nó đi vào, nếu không firewall sẽ cản nó theo quy định của quy chế mặc định (-P) là DROP. Ở đây bạn có một luật INPUT duy nhất và luật này quy định rất cụ thể tình trạng packet được cho phép vào. Khi packet từ bên ngoài Internet vào, firewall sẽ kiểm tra packet này:
– nếu nó hoàn toàn mới và không hề hiện diện trong bản tình trạng (conntrack table) của netfilter -2- thì packet này bị cản.
– nếu nó đã hiện diện trong state table của netfilter thì nó được tiếp tục đi vào.
8. Mở rộng:
8.1. Vấn đề logging:
Với các luật firewall trên, khi xét kỹ, bạn sẽ thấy thiếu một yếu tố rất quan trọng đó là thông tin logging. Nếu bạn muốn biết có bao nhiêu trường hợp các packets “vi phạm” (bên ngoài các luật cho phép của firewall trên), bạn cần dùng target LOG. Vậy đưa vào các luật để thâu thập các thông tin vi phạm ở đâu? Bạn chỉ cần thêm vài dòng tiếp theo sau dòng 11 ở trên như sau:


12. $IPT -A INPUT -i $IF -d $IP -m limit –limit 1/s -j LOG –log-level 5 –log-prefix “BAD_INPUT: ”
13. $IPT -A INPUT -i $IF -d $IP -j DROP
14. $IPT -A OUTPUT -i $IF -d $IP -m limit –limit 1/s -j LOG –log-level 5 –log-prefix “BAD_OUTPUT: ”
15. $IPT -A OUTPUT -o $IF -d $IP -j DROP
16. $IPT -A FORWARD -i $IF -d $IP -m limit –limit 1/s -j LOG –log-level 5 –log-prefix “BAD_FORWARD: ”
17. $IPT -A FORWARD -i $IF -d $IP -j DROP

– Các luật trên đôi khi còn được gọi là “clean-up rules”, nói theo thuật ngữ chuyên môn của firewall. Lý do chúng được gọi là “clean-up rules” vì chúng đóng vai trò “dọn dẹp” cho các luật đứng trước chúng. Các luật ở dòng 12, 13, 14, 15 ,16 và 17 có chức năng tương tự nhau, chỉ khác ở một điểm là mỗi cặp 12-13, 14-15, 16-17 có tác dụng cho các chains (INPUT, OUTPUT và FORWARD) riêng biệt.
– Diễn dịch luật ở dòng 12 thành ngôn ngữ bình thường như sau: mọi packets đi vào thuộc chain INPUT, xuyên qua interface $IF đến địa chỉ $IP sẽ được log với prefix là “BAD_INPUT” ở chế độ –log-level 5 và ở giới hạn là 1 giây.
– Kế tiếp, ở dòng 13: vào thuộc chain INPUT, xuyên qua interface $IF đến địa chỉ $IP sẽ bị cản (sau khi bị LOG ở trên).
– Dòng 14, 15, 16 và 17 tương tự như trên cho chain OUTPUT và FORWARD.
Vậy điểm cần nhấn mạnh ở đây là vị trí của các luật trong một nhóm luật. Nếu các luật ở dòng 12-17 nằm trên các luật ở dòng 10-11 thì chắc chắn firewall của bạn trở nên vô dụng vì không có bất cứ packets nào có thể đi vào và đi ra vì, hễ một packet nào đi vào và đi ra đều “trùng” với luật đã ấn định (và đã diễn dịch ở trên). Tuy nhiên, khi các luật ở dòng 12-17 nằm dưới các luật dòng 10-11 thì chúng trở thành ích lợi. Một packet đi vào theo trình tự các luật đặt sẵn trong firewall trên, chúng ta sẽ thấy:
– nếu packet đó đi vào để “trả lời” cho một đòi hỏi từ firewall khởi tạo trước thì nó được phép đi vào (áp đặt bởi luật dòng 11).
– nếu packet đó đi vào mà không thoả mãn luật ở dòng 11, nó tiếp tục “bị” xét duyệt bởi các luật đi theo sau. Ở đây, dòng 12 và 13 chắc chắn sẽ “tóm” được packet vi phạm và sẽ được xử lý theo ấn định cho các packet đi vào (thuộc chain INPUT).
– nếu không có các luật đưa ra ở dòng 12, 13, 14, 15, 16 và 17 thì các packet không thoả mãn được luật đã ấn định của firewall cũng sẽ bị cản bằng chế độ đưa ra ở dòng 6, 7, 8 nhưng cản một cách im lặng. Điểm khác biệt ở đây là luật cụ thể ở dòng 12, 13, 14, 15, 16 và 17 sẽ tạo ra log trong /var/log/messages (theo mặc định) cho những packet vi phạm và sẽ cản chúng một cách cụ thể.
8.2. Cản các lưu thông cụ thể
Đối với các lưu thông đi vào INPUT chain, luật ở dòng 11 đã khá vững vì không có gói tin nào từ bên ngoài có thể đi vào nếu như bạn không gởi “request” ra trước. Cho nên, chúng ta chỉ mở rộng ở OUTPUT chain ở đây.
8.2.1 Cản trọn bộ trước, cho phép cụ thể sau
Câu hỏi được đặt ra là các loại lưu thông cụ thể nào cần được cản? Vấn đề này phụ thuộc vào mức cẩn thận (hoặc paraniod)hoặc nhu cầu của từng người dùng. Với một cá nhân muốn truy cập bất cứ nơi đâu, bằng bất cứ giao thức nào thì dòng 10 thuộc phần 5 ở trên hoàn toàn đáp ứng nhu cầu này. Tuy nhiên, với một cá nhân chỉ cần duyệt web và chat bằng Yahoo Instance Messenger chẳng hạn thì giới hạn này có thể thu hẹp lại rất nhiều. Trong trường hợp này, dòng 10 thuộc phần 5 ở trên có thể được thay thế bởi một dòng như sau:


$IPT -A OUTPUT -o $IF -s $IP -p tcp -d any/0 -m multiport –dport 80,443,5050 -j ACCEPT

Dòng trên có thể được diễn dịch nôm na: các lưu thông đi đến bất cứ địa chỉ nào (-d any/0) bằng giao thức tcp (-p tcp đến cổng 80 (cổng 443 và cổng 5050) (–dport 80,443,5050) -3- thì được chấp nhận. Dòng trên không đề cập đến vấn đề “state” của các gói tin (-m state) như ở dòng 11 thuộc phần 5, điều này có nghĩa các lưu thông này có thể đi ra ngoài ở bất cứ state nào tùy thích. Tuy nhiên, nếu bạn paranoid hơn nữa thì chêm vào một đoạn -m state thì càng vững hơn, ví dụ:


$IPT -A OUTPUT -o $IF -s $IP -p tcp -d any/0 -m multiport –dport 80,443,5050 -m state state NEW,ESTABLISHED -j ACCEPT

Dòng trên tương tự như ví dụ trước nhưng chỉ định thêm là các gói tin ở tình trạng NEW và ESTABLISHED thì mới được đi ra ngoài; những gói tin ở dạng RELATED và INVALID sẽ bị cản. Lý do, giao thức http và giao thức dành cho YIM không cần đến tình trạng RELATED và các gói tin ở tình trạng INVALID thì càng nên không cho phép lưu thông. Tất nhiên nếu bạn muốn dùng POP3 và SMTP thì phải thêm giá trị 25 và 110 cho chuỗi –dport ở trên.

Nếu đã thực sự “paranoid” như vậy thì tại sao không xác lập thêm một luật cho giao thức UDP? Nếu bạn không có nhu cầu gì đặc biệt thì có lẽ cổng 53 cho DNS là cổng cần thiết nhất:


$IPT -A OUTPUT -o $IF -s $IP -p udp -d <DNS_của_ISP> –dport 53 -m state state NEW,ESTABLISHED -j ACCEPT

8.2.2 Cho phép trọn bộ trước, cản các cổng cụ thể sau
Trường hợp người dùng muốn tự do truy cập bất cứ nơi đâu, bằng bất cứ giao thức nào nhưng không muốn máy của mình “tự động” truy cập đến các cổng “nguy hại” (ví dụ như máy vô tình bị nhiễm trojan và bị biến thành zombie -4- để tham gia trong các cuộc tấn công từ chối dịch vụ chẳng hạn). Trong trường hợp này, cách giản tiện nhất là thêm hai dòng phía trên dòng 10 thuộc phần 5:


$IPT -A OUTPUT -o $IF -s $IP -p tcp -d any/0 -m multiport –dport 54321,12345 -j DROP
$IPT -A OUTPUT -o $IF -s $IP -p udp -d any/0 -m multiport –dport 54321,12345 -j DROP

Hai dòng trên chỉ định các gói tin đi ra ngoài và đến các cổng trong chuỗi -5- ở trên sẽ bị cản (các cổng nêu ra ở đây chỉ là một ví dụ, không cụ thể áp đặt tính nguy hại của các cổng trên trên thực tế). Lý do chúng ta phải thiết lập hai dòng luật tách biệt vì mỗi dòng dành riêng cho mỗi giao thức và lý do hai dòng trên phải được đặt trước dòng thứ 10 vì những gói tin đi ra phải được kiểm tra trước khi có thể đi ra. Như đã đề cập ở phần 8.1, vị trí các luật là một yếu tố tối quan trọng, đây là yếu tố quyết định các luật của firewall hữu dụng hay vô dụng.
9. Thử nghiệm:
9.1 Thử nghiệm 1:
Giả sử bạn có một dịch vụ đang chạy trên máy (telnet chẳng hạn, hoặc bất cứ dịch vụ nào hiện có trên máy). Sau khi đã ứng động firewall trên, bạn thử nhờ một người bạn nào khác tìm cách truy cập vào dịch vụ telnet này. Tất nhiên bạn phải cung cấp địa chỉ IP cho người bạn ấy.
– người bạn ấy sẽ thử: telnet <địa_chỉ_IP_của_bạn> 23 –> việc này sẽ tạo SYN packet từ bên ngoài vào cổng 23 đã được cản (filtered port) vì firewall trên không hề cho phép bất cứ truy cập nào khởi tạo từ bên ngoài.
– bạn xem thử syslog: tail -f /var/log/message | grep ‘<địa_chỉ_IP_của_người_bạn>’
– bạn xem /proc/net/ip_conntrack: cat /proc/net/ip_conntrack | grep ‘<địa_chỉ_IP_của_người_bạn>’
– bạn theo dõi tcpdump: tcpdump tcp port 23
9.2 Thử nghiệm 2:
Giả sử bạn đã ứng dụng các luật “paranoid” ở phần 8.2.1, chỉ cho phép từ máy truy cập đến cổng 80, 443 và 5050 cho tcp và cổng 53 cho udp. Sau khi ứng động firewall trên, bạn thử:
– truy cập đến một website không dùng cổng 80 tiêu chuẩn mà dùng cổng khác như 8000, 8080 chẳng hạn, ví dụ: http://www.gocit.vn:8000.
– bạn xem thử syslog: tail -f /var/log/message | grep ‘<địa_chỉ_IP_của_website_bạn_truy_cập> ‘
– bạn xem /proc/net/ip_conntrack: cat /proc/net/ip_conntrack | grep ‘<địa_chỉ_IP_của_website_bạn_truy_cập> ‘
– bạn theo dõi tcpdump: tcpdump tcp port <cổng_website_dùng>
Qua hai thử nghiệm trên, chắc chắn bạn sẽ tìm thấy rất nhiều thông tin mới lạ và đây chính là cánh cửa mở rộng cho những điều đằng sau một nhúm firewall script đơn giản như trên.
10. Kết luận:
iptables thật sự không phức tạp. Điều thật sự phức tạp là quá trình phân tích và xác định chức năng của một firewall cho một nhu cầu cụ thể nào đó. Trong quá trinh phân tích và xác định này, bạn sẽ phải đi sâu vào vấn đề khảo sát và thu thập những thông tin cần thiết để hoàn thành một nhóm luật bảo vệ máy của mình. Đây cũng chính là điểm lý thú và bổ ích trong suốt quá trình thiết lập bởi vì chắc chắn bạn sẽ không chỉ dừng lại ở phạm vi một firewall và firewall đó làm được gì. Bài viết này tôi chủ ý đào sâu vào tính năng “stateful” của iptables và bỏ qua những chi tiết thuộc kỹ năng tạo shell script, run level script… Tùy bạn chọn lựa cách điều chỉnh script theo ý mình và chỉnh init script (run level) tùy môi trường.
11. Bị chú:
-1- SPI: Stateful Packet Inspection hay dịch nôm na sang tiếng Việt là “kiểm soát đa thể trạng”, một khái niệm được đưa ra vào những năm đầu của thập niên 90 và được ứng dụng rộng rãi cho các firewall “hiện đại”. Tính “stateful” được khai triển dựa trên tính chất của giao thức TCP. Riêng với iptables, tính “stateful” này không những ứng dụng cho TCP mà còn cho UDP (được biết như một giao thức có tính stateless) và icmp. Dựa trên tính chất của từng loại giao thức, iptables / netfilter lưu trữ tình trạng diễn tiến của các packets trong bảng theo dõi (state table).

-2- netfilter thuộc kernel side, iptables thuộc user side. Xem thêm các thông tin này trên website http://www.iptables.org
-4- zombie: một bán thuật ngữ bảo mật ngầm chỉnh định cho các máy bị nhân nhượng và có thể được sai khiến từ một hoặc nhiều máy từ xa để thực hiện các ý định cụ thể nào đó.
-3,5- iptables cho phép 15 cổng trong chuỗi comma delimeter (,) cho giá trị –dport (destination port) và –sport (source port) nếu dùng match -m multiport. Dùng cách này hiệu năng hơn cách dùng từng dòng luật cho mỗi cổng cần cản hoặc cần cho phép.
Liệt kê nhóm luật “paranoid” cho phần 8.2.1:


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. ISP_DNS=”xxx.xxx.xxx.xxx”
5. $IPT -F
6. $IPT -P INPUT DROP
7. $IPT -P OUTPUT DROP
8. $IPT -P FORWARD DROP
9. $IPT -A OUTPUT -o $IF -s $IP -p tcp -d any/0 -m multiport –dport 80,443,5050 -m state state NEW,ESTABLISHED -j ACCEPT
10. $IPT -A OUTPUT -o $IF -s $IP -p udp -d $ISP_DNS –dport 53 -m state state NEW,ESTABLISHED -j ACCEPT
11. $IPT -A INPUT -i $IF -d $IP -m state –state ESTABLISHED,RELATED -j ACCEPT
12. $IPT -A INPUT -i $IF -d $IP -m limit –limit 1/s -j LOG –log-level 5 –log-prefix “BAD_INPUT: ”
13. $IPT -A INPUT -i $IF -d $IP -j DROP
14. $IPT -A OUTPUT -i $IF -d $IP -m limit –limit 1/s -j LOG –log-level 5 –log-prefix “BAD_OUTPUT: ”
15. $IPT -A OUTPUT -o $IF -d $IP -j DROP
16. $IPT -A FORWARD -i $IF -d $IP -m limit –limit 1/s -j LOG –log-level 5 –log-prefix “BAD_FORWARD: ”
17. $IPT -A FORWARD -i $IF -d $IP -j DROP

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 -i $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).
– 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.
– 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.
– 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.
– 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.
– 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).
– 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.
– 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).
– 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.
– 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.
– 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.
– 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.
– 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.
– 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-.
– 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ụ, 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 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ý.
8.2.3.2 Giới hạn truy cập với “connection limit”
“Connection limit” cần huy động đến CONFIG_IP_NF_MATCH_CONNLIMIT có từ patch-o-matic trên website chính của iptables (http://www.iptables.org). Module này cần được tải và biên dịch -11- trước khi có thể hoạt động. Ứng dụng tính năng này trên dòng 32 như sau:


$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 state –state NEW -m connlimit ! –connlimit-above 2 -j ACCEPT

-m connlimit ! –connlimit-above 2 quyết định tối hậu đến số phận các gói tin đi vào ngoài các áp đặt đi trước (như gói tin TCP phải mang flag SYN và phải ở tình trạng NEW). Tính linh động nằm ở giá trị đảo (!) phía trước –connlimit-above 2. Dòng lệnh này áp đặt thêm một tầng kiểm soát: các gói tin truy cập này đến từ một IP mà không nhiều hơn 2 xuất truy cập thì tiếp nhận. 3, 4 hoặc hơn xuất truy cập không thể xảy ra từ cùng một máy con (có cùng IP) đến máy chủ. Tính chất này khác hẳn tính chất “connection rate” đã trình bày trong phần 8.2.3.1, “connection limit” dựa trên tính đồng thời (concurrent) của giao thức TCP mà điều tác -12-
8.2.4 Vấn đề độ dài của SYN packet:
Bạn có thật sự paranoid không? Nếu có thì tiếp tục theo dõi phần mở rộng này. Theo RFC 793, SYN packet không mang theo “payload” (dữ liệu) và nếu các hệ thống ứng dụng đúng theo RFC 793 thì SYN packet chỉ có chiều dài tối đa là ở khoảng 40 đến 60 bytes nếu bao gồm các tcp options. Dựa trên quy định này (hầu hết các ứng dụng trên mọi hệ điều hành đều tuân thủ theo quy định của RFC 793), chúng ta có thể hình thành một luật khác cho dòng 32 ở trên:


$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 state –state NEW -m length –length 40:60 -j ACCEPT

Nếu cần, bạn vẫn có thể đưa vào một trong hai chọn lựa “connection rate” hoặc “connection limit” cho dòng lệnh trên để thắt chặt. Điều cần nói ở đây là giá trị -m length –length 40:60 ấn định chiều dài của gói tin SYN của giao thức TCP được firewall chúng ta tiếp nhận. Như đã đề cập ở trên, theo đúng quy định, gói SYN không mang dữ liệu cho nên kích thước của chúng không thể (và không nên) lớn hơn 40:60.
Luật trên áp đặt một quy định rất khắc khe để loại trừ các gói SYN lại mang dữ liệu (và đặc biệt mang dữ liệu với kích thước lớn). Theo tôi thấy, những gói tin này rất hiếm thấy ngoại trừ trường hợp cố tình tạo ra hoặc thỉnh thoảng có dăm ba gói “lạc loài” ở đâu vào từ một hệ điều hành nào đó không ứng dụng đúng quy cách. Xử dụng luật này hay không là tùy mức khắc khe của bạn.
Cách tốt nhất trước khi dùng, bạn nên thử capture các gói SYN cho suốt một ngày (hoặc nhiều) và mang về phân tích xem có bao nhiêu gói SYN thuộc dạng không cho phép, có bao nhiêu gói tin được xếp loại vào nhóm có chiều dài 40:60 bytes và từ đó mới đi đến quyết định cuối cùng.
8.3 Vấn đề thuộc giao thức UDP:
Giao thức UDP mang tính chất rất khác với TCP cho nên cơ chế điều hoạt và quản lý có những điểm khác biệt. Bởi UDP hoạt động trên căn bản lặp (interation) -13- nên đối với các gói tin thuộc giao thức này có hai điểm cần chú ý:
8.3.1 Vấn đề thuộc số lượng truy cập UDP
Bởi UDP là giao thức thuộc dạng “stateless” nên dịch vụ UDP trên máy chủ chỉ có thể nhận và “cố gắng” thoả mãn yêu cầu. Dịch vụ UDP trên máy chủ:
– không có cách nào kiểm tra xem nguồn truy cập có thật sự hiện hữu hay không; máy chủ cũng không thể phân biệt gói tin UDP đang đi vào là gói đang trả lời ngược lại (thuộc một xuất truy cập hiện có) hay một gói UDP hoàn toàn mới.
– chỉ đơn giản “trả lời” và không cần theo dõi xem gói tin trả lời có đi đến đích hay không.
Dựa trên tính chất này, kẻ tấn công có thể tạo hàng loạt gói tin (1000 yêu cầu trong một giây chẳng hạn) đến một dịch vụ UDP. Dịch vụ này sẽ cần mẫn đặt các yêu cầu vào hàng chờ đợi (queue) và tuần tự xử lý. Tuy nhiên, “queue” của dịch vụ có giới hạn trên căn bản tài nguyên, liệu dịch vụ UDP này chứa được bao nhiêu yêu cầu trên “queue” trước khi máy chủ bị cạn kiệt? Hơn nữa, vì tính “stateless” này mà thông tin chuyển tải xuyên qua UDP nhanh hơn TCP rất nhiều, điều này lại càng tiện lợi cho việc “dội” một dịch vụ UDP trên máy. Trong trường hợp này, -m limit của iptables trở nên hết sức tiện dụng. Thử xem hai dòng 23, 24 trở thành:


$IPT -A INPUT -i $IF -p udp -s $NET –sport $port -d $IP –dport $port -m state –state NEW,ESTABLISHED -m limit –limit 2/s –limit-burst 2 -j ACCEPT
$IPT -A OUTPUT -o $IF -p udp -s $IP –sport $port -d $NET –dport $port -m state –state ESTABLISHED -m limit –limit 2/s –limit-burst 2 -j ACCEPT

chắc chắn sẽ giúp cho dịch vụ DNS này có đủ thời gian và tài nguyên phục vụ các đòi hỏi về name một cách bình thường. Nên biết rằng, hầu hết các DNS server có thể lưu một bản “cache” cho những IP / Name đã được biên giải cho nên rất hiếm khi một DNS server nào đó đòi hỏi dịch vụ DNS trên máy chủ của chúng ta phải tiếp nhận hơn 2 yêu cầu trong một giây và liên tục 2 lần. Thật ra, giới hạn này vẫn còn rất “dễ chịu” cho một dịch vụ DNS. Tuy nhiên, với các dịch vụ khác cũng dùng giao thức UDP và phục vụ những dòng thông tin ở vận tốc cao (như streaming media chẳng hạn) thì giá trị -m limit trên cần được điều chỉnh cho thích hợp với nhu cầu này.

8.3.2 vấn đề thuộc thực tính của xuất truy cập UDP
Kiểm tra thực tính truy cập cho UDP? Chắc hẳn bạn sẽ hỏi câu này vì ở trên tôi đề cập đến khía cạnh dịch vụ UDP trên máy chủ không có cách nào kiểm tra xem nguồn truy cập có thật sự hiện hữu hay không (nguồn địa chỉ IP). Vậy, giải pháp là sao đây? Phần lớn các cuộc tấn công nghiêm trọng có thể làm tê liệt một dịch vụ bằng giao thức UDP được tạo ra từ các IP giả mạo và các IP thuộc nhóm được IANA phân bố dùng làm IP cho nội mạng -14-. Nếu các địa chỉ dùng để tấn công là các địa chỉ thuộc nhóm public IP thì bạn chỉ có thể giao phó cho -m limit và -m state ở trên. Nếu -m limit được ấn định gắt gao hơn nữa sẽ cản bớt số lượng gói UDP “flood” dịch vụ.
Riêng với các yêu cầu truy cập từ các nhóm IP nội mạng (xem chú thích 14) thì việc lượt bỏ chúng khá đơn giản. Thật ra, việc lọc bỏ này không riêng gì cho giao thức UDP mà còn có thể ứng dụng cho mọi giao thức. Đoạn lệnh sau dùng để thắt chặt vấn đề này:


NON_NET=”10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 224.0.0.0/4 240.0.0.0/5 169.254.0.0/16 192.0.2.0/24″
for entry in $NON_NET; do
$IPT -A INPUT -i $IF -s $entry -m limit –limit 1/s -j LOG –log-level 5 –log-prefix “BAD_NET: ”
$IPT -A INPUT -i $IF -s $entry -j DROP
done

Biến $NON_NET trên có thể đưa vào nhóm biến được ấn định ở phần trên của firewall script và đoạn lặp “for / done” có thể nằm trên dòng 15 (trước luật đầu tiên ấn định ACCEPT). Dòng luật trong đoạn lặp không ấn định cụ thể giao thức (-p) và cũng không ấn định tình trạng (-m state) nên mọi giao thức và mọi tình trạng đều có tác dụng. Lệnh này trông rất đơn giản nhưng hàm chứa tính kiểm soát rất rộng -15-. Nếu bạn thích, thử tính xem có bao nhiêu địa chỉ cả thảy trong nhóm NON_NET này để hình dung.
    Blogger Comment
    Facebook Comment