Cấu hình firewall sử dụng ipset

Iptables là công cụ để quản lý, cấu hình các quy tắc firewall trong Linux kernel. iptables chỉ là một phần trong netfilter framework, chịu trách nhiệm giao tiếp giữa người dùng và netfilter để đẩy các rule của người dùng vào cho Netfiler xử lý.

ipset là một phần mở rộng của iptables cho phép bạn tạo các quy tắc tường lửa match với một tập các địa chỉ. Khác với iptables chain được lưu trữ và xử lý tuyến tính, ipset được lữu trữ dưới dạng cấu trúc dữ liệu, hỗ trợ tìm kiếm hiệu quả hơn.

Bên cạnh những tình huống mà bạn có thể nghĩ ngay tới để áp dụng ipset hiệu quả, chẳng hạn như chặn một số lượng lớn các host riêng lẻ mà không làm ảnh hưởng tới hiệu năng hệ thống hay gây nghẽn mạng, ipset cũng mở ra những cách thức tiếp cận mới khi thiết kế firewal và có thể giúp đơn giản hóa nhiều kịch bản cấu hình.

Trong bài viết này, chúng ta sẽ thảo luận nhanh về cách cài đặt ipset, một số nguyên tắc và khái niệm cốt lõi về cách thức hoạt động của iptables. Sau đó sẽ tập trung vào cách sử dụng, cú pháp và các ví dụ về kết hợp ipset hoạt động cùng iptables.

Cài đặt

ipset chỉ là một package trên hầu hết các distribution, do đó việc cài đặt khá đơn giản, chúng ta sẽ không mất nhiều thời gian ở bước này. Nếu distro của bạn không có sẵn package, hãy thực hiện theo các hướng dẫn cài đặt ở trang chủ http://ipset.netfilter.org/
Để cài đặt ipset trên Ubuntu, thực hiện lệnh:

apt-get install ipset  

Để cài đặt ipset trên CentOS, thực hiện lệnh:

yum install ipset  

Tổng quan iptables

Một cách ngắn gọn, một iptables firewall là tập hợp các chain, được phân ra 4 bảng chính (raw, mangle, nat, filter), mỗi chain bao gồm một hoặc nhiều các rule. Với mỗi một gói tin, ở từng giai đoạn xử lý, kernel sẽ tham chiếu tới các chain phù hợp để xác định sẽ làm gì với gói tin. Các chain sẽ được tham chiếu theo thứ tự, dựa vào “hướng” của gói tin ( remote-to-local, remote-to-remote hoặc local-to-remote ) . Bảng dưới đây mô tả các chain sẽ được tham chiếu tùy theo hướng cụ thể của gói tin.
Alt text Khi tham chiếu một chain, gói tin sẽ được so sánh với từng rule theo thứ tự trong chain đó cho đến khi tìm được rule phù hợp. Khi tìm được rule phù hợp, gói tin sẽ được xử lý theo target của rule đó. Trong trường hợp không có rule phù hợp, default target hoặc một chính sách nào đó mặc định sẽ được chọn để xử lý gói tin.
Một chain là tập các rule được sắp xếp theo thứ tự, một rule đơn giản là sự kết hợp giữa match/target, tương tự như chúng ta sử dụng câu điều kiện nếu … thì …
Một ví dụ đơn giản về match là "TCP destination port 80", một target có thể là “drop the packet”. Target có thể điều hướng packet đến một chain do user tự định nghĩa.
Một câu lệnh định nghĩa các rule của iptables có 3 phần cơ bản để chỉ rõ table/chain, match và target.
Alt text Bên cạnh các tính năng được tích hợp sẵn, iptables còn cung cấp khả năng mở rộng như một API cho "match extensions" (module để phân loại gói tin ) và "target extensions" (module để xác định sẽ làm gì với gói tin).

ipset

ipset là một match extension của iptables. Để sử dụng nó, bạn sẽ tạo các set bằng lệnh ipset, sau đó sử dụng nó để chỉ định match specifition của một rule trong iptables. Một set đơn giản là một danh sách các địa chỉ được lưu trữ tối ưu cho việc tra cứu với tốc độ nhanh.
Giả sử nếu bạn muốn chặn traffic từ 2 địa chỉ IP là 1.1.1.1 và 2.2.2.2 thì ta sẽ thực hiện 2 lệnh sau với iptables.

iptables -A INPUT -s 1.1.1.1 -j DROP  
iptables -A INPUT -s 2.2.2.2 -j DROP  

Điều kiện match ở đây -s 1.1.1.1 có nghĩa là các packet có địa chỉ nguồn là 1.1.1.1. Để chặn cả 1.1.1.1 và 2.2.2.2, bạn phải sử dụng 2 rule riêng biệt trong iptables. Bạn hoàn toàn có thể sử dụng ipset để đạt được mục đích tương tự với cách thực hiện như sau:

ipset -N myset iphash  
ipset -A myset 1.1.1.1  
ipset -A myset 2.2.2.2  
iptables -A INPUT -m set --set myset src -j DROP  

Các lệnh ipset trên sẽ tạo một set có tên là myset thuộc type iphash gồm 2 địa chỉ 1.1.1.1 và 2.2.2.2. Sau đó iptables sẽ chỉ định match với set được tạo ra từ ipset (-m set --set myset src) , có nghĩa là “match với tất cả các packet có địa chỉ nguồn là một trong các địa chỉ trong myset. Flag src nghĩa là match với địa chỉ nguồn, bạn có thể sử dụng flag “dst” cho mục đích match với địa chỉ đích hoặc sử dụng flag “src,dst” khi cần match cả địa chỉ nguồn và địa chỉ đích.
Với cách làm sử dụng ipset, bạn chỉ cần tới 1 rule của iptables. Ở ví dụ trên chúng ta chỉ sử dụng 2 địa chỉ IP, nhưng khi cần chặn tới 1000 địa chỉ thì bạn sẽ thấy rõ sự khác biệt. Thay vì sử dụng 1000 rule của iptables, bạn vẫn chỉ cần 1 rule kết hợp cùng ipset để có được tác dụng tương đương.

Set types

Mỗi set khi tạo ra sẽ thuộc 1 type xác định, đây là cách để xác định loại giá trị được lưu trữ trong set (IP address, network, port …) và cũng như xác định phần nào của gói tin sẽ được kiểm tra để match với set. Ngoài kiểm tra địa chỉ IP được minh họa ở trên, ipset cũng có thể kiểm tra port, IP + Port và cả địa chỉ MAC + IP của gói tin. Hai dạng linh động nhất thường được sử dụng trong ipsetiphash (lưu trữ danh sách các địa chỉ IP) và nethash (lưu trữ danh sách mạng (IP/mask)). Về các set type bạn có thể tham khảo thêm tại ipset man page.

Lợi ích của ipset

Bên cạnh hiệu quả về mặt hiệu năng, ipset cũng cho phép đơn giản hóa cấu hình trong nhiều trường hợp.
Nếu bạn muốn tường lửa cho phép tất cả các gói tin được tiếp tục xử lý ở chain continue ngoại trừ những gói tin đến từ địa chỉ 1.1.1.1 hoặc 2.2.2.2 , bạn sẽ cấu hình iptables như thế nào ?

iptables -A INPUT -s ! 1.1.1.1 -g  continue  
iptables -A INPUT -s ! 2.2.2.2 -g  continue  

Cấu hình như trên có hoạt động không ? Tất nhiên là không. Nếu gói tin có địa chỉ nguồn là 1.1.1.1, nó sẽ không match với rule đầu tiên, nhưng gói tin này sẽ match với rule thứ 2 (bởi vì địa chỉ nguồn của nó không phải là 2.2.2.2) nên vẫn được chuyển tới chain “continue”. Đây là một ví dụ đơn giản, nhưng nó cũng minh chứng lợi ích của việc đạt được yêu cầu trong một rule duy nhất. Thực tế các rule của iptables là độc lập với nhau nhưng việc kết hợp, sắp xếp và tối ưu các rule để đạt được những yêu cầu cho trước không phải lúc nào cũng đơn giản, đặc biệt là việc kết hợp các rule bình thường và các rule có điều kiện đảo ngược. ipset sẽ làm cho mọi thứ dễ dàng hơn trong những trường hợp như thế.

ipset -N myset iphash  
ipset -A myset 1.1.1.1  
ipset -A myset 2.2.2.2  
iptables -A INPUT -m set ! --set myset src -g continue  

Nếu gói tin đi đến có địa chỉ nguồn là 1.1.1.1 hay 2.2.2.2 cũng không thể match với rule (iptables -A INPUT -m set ! --set myset src -g continue ), do đó sẽ không được xử lý tiếp bởi chain “continue”.

Một lợi ích khác của ipset là bạn có thể thay đổi danh sách địa chỉ của set một cách độc lập với iptables. Đối với iptables, thứ tự các rule là một điểm rất quan trọng, do đó việc sửa đổi các rule hay sắp xếp thứ tự sẽ có ảnh hưởng lớn. Ngược lại, ipset lưu trữ các giá trị trên một mặt phẳng, không đòi hỏi thứ tự nên việc thêm, xóa, sửa đổi không mất nhiều thời gian cân nhắc, suy nghĩ.

Giới hạn truy cập

Nếu một ngày boss của bạn nói rằng có một số nhân viên thường xuyên giải trí trên Internet trong giờ hành chính thay vì làm việc, nhiệm vụ khi đó sẽ là giới hạn truy cập trên PC của các nhân viên này chỉ có thể kết nối tới những trang web họ cần để làm việc nhưng không làm ảnh hưởng đến những người khác.
Để giới hạn 3 PC (10.0.0.5, 10.0.0.6 và 10.0.0.7) chỉ có thể kết nối tới 3 địa chỉ worksite1.com, worksite2.com và worksite3.com, bạn thực hiện như sau :

ipset -N limited_hosts iphash  
ipset -A limited_hosts 10.0.0.5  
ipset -A limited_hosts 10.0.0.6  
ipset -A limited_hosts 10.0.0.7  
ipset -N allowed_sites iphash  
ipset -A allowed_sites worksite1.com  
ipset -A allowed_sites worksite2.com  
ipset -A allowed_sites worksite3.com  
iptables -I FORWARD -m set --set limited_hosts src -m set ! --set allowed_sites dst -j DROP  

Ví dụ này sử dụng match cả hai set trong cùng 1 rule. Nếu packet đến có địa chỉ nguồn match với limited_hosts và địa chỉ đích không match với allowed_sites, gói tin sẽ bị DROP.

Vậy trong tình huống ngược lại, boss muốn chặn truy cập tới một số trang web trên tất cả các host trên mạng LAN, trừ PC của boss và trợ lý. Cách thực hiện sẽ như sau:

ipset -N blocked_sites iphash  
ipset -A blocked_sites badsite1.com  
ipset -A blocked_sites badsite2.com  
ipset -A blocked_sites badsite3.com

ipset -N allowed_hosts iphash  
ipset -A allowed_hosts 10.0.0.5  
ipset -A allowed_hosts 10.0.0.6

iptables -I FORWARD -m set --set ! allowed_hosts src  -m set --set blocked_sites dst -j DROP  

Lưu ý rằng trong nhiều trường hợp, giải pháp này sẽ không hiệu quả đối với nhiều website. Chẳng hạn bạn muốn chặn truy cập vào facebook.com, thực tế là domain này sẽ được phân giải ra rất nhiều IP, mà iptables/ipset chỉ hỗ trợ hostname nếu chúng được phân giải ra một địa chỉ IP duy nhất . Việc phân giải tên miền cũng chỉ xảy ra lúc thực hiện lệnh, sau đó nếu địa chỉ IP thay đổi, iptables cũng không cập nhật sự thay đổi này. Vì những lý do đó, cách tốt nhất để áp dụng chính sách truy cập Web là sử dụng các giải pháp về HTTP Proxy như Squid.

Tự động chặn các truy cập không mong muốn

ipset cũng cung cấp target extension cho iptables có thể tự động thêm hoặc xóa các entry dựa trên iptables rule. Thay vì phải thêm các entry bằng lệnh ipset, bạn có thể cấu hình để iptables thực hiện việc này.
Giả sử có một host đang muốn kết nối vào port 25 nhưng bạn lại không chạy SMTP server trên máy chủ, và bạn muốn chặn luôn các traffic đến từ host này. Cách thực hiện như sau:

ipset -N banned_hosts iphash  
iptables -A INPUT -p tcp --dport 25 -j SET --add-set banned_hosts src  
iptables -A INPUT -m set --set banned_hosts src -j DROP  

Nếu gói tin có destination port là 25, địa chỉ nguồn của nó sẽ được thêm vào banned_hosts, sau đó ta sẽ thêm một rule để chặn các gói tin có địa chỉ nguồn nằm trong banned_hosts.

ipset trong OpenStack

Neutron sử dụng iptables để thiết lập chức năng security group, nhưng ở các phiên bản trước sẽ gặp phải một số vấn đề. Khi một security group có nhiều rule liên quan đến các security group khác, hiệu năng của security group sẽ giảm hay khi một port được update, toàn bộ các chain liên quan đến port này sẽ được xóa đi và tạo lại, điều này cũng gây ra vấn đề hiệu năng cho L2 agent.
Trong Openstack Juno, ipset được sử dụng để tối ưu iptables rule chain. Giả sử bạn có 2 instance A và B có địa chỉ IP là 10.3.25.57, 10.3.25.58 thuộc SECGROUP1. Bạn tạo một intances C mới thuộc SECGROUP2. SECGROUP2 sẽ chỉ cho phép kết nối SSH từ các instance thuộc SECGROUP1.
Ở các phiên bản trước, iptables rule của port thuộc instance C trong L2 agent sẽ như sau :

-A neutron-openvswi-i9f5f8a14-e -m state --state INVALID -j DROP
-A neutron-openvswi-i9f5f8a14-e -m state --state RELATED,ESTABLISHED -j RETURN
-A neutron-openvswi-i9f5f8a14-e -s 10.3.25.3/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
-A neutron-openvswi-i9f5f8a14-e -p tcp -m tcp --dport 22 -s 10.3.25.57/32 -j RETURN
-A neutron-openvswi-i9f5f8a14-e -p tcp -m tcp --dport 22 -s 10.3.25.58/32 -j RETURN

Khi sử dụng “iptables+ipset”, các rule đối với instance C sẽ như sau:

-A neutron-openvswi-i9f5f8a14-e -m state --state INVALID -j DROP
-A neutron-openvswi-i9f5f8a14-e -m state --state RELATED,ESTABLISHED -j RETURN
-A neutron-openvswi-i9f5f8a14-e -s 10.3.25.3/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
-A neutron-openvswi-i9f5f8a14-e -p tcp -m tcp --dport 22 -m set --match-set IPv49ba654b2-a3a4-49f8-8 src -j RETURN
-A neutron-openvswi-i9f5f8a14-e -j neutron-openvswi-sg-fallback

ipset chain sẽ chứa địa chỉ IP của các instance thuộc SECGROUP1

# ipset list IPv49ba654b2-a3a4-49f8-8
Name: IPv49ba654b2-a3a4-49f8-8  
Type: hash:ip  
Revision: 2  
Header: family inet hashsize 1024 maxelem 65536  
Size in memory: 16536  
References: 1  
Members:  
10.3.25.57  
10.3.25.58  

Bằng cách này, thời gian iptables-save/iptables-load sẽ gỉam đi đáng kể khi chỉ cần chỉnh sửa các ipset trong trường hợp có sự thay đổi về Security Group.

ipset không chỉ cung cấp thêm một phương thức cấu hình mới cho iptables, nó còn hỗ trợ đơn giản hóa nhiều kịch bản mà nếu chỉ sử dụng iptables sẽ gặp khó khăn hoặc kém hiệu quả. Bạn cũng có thể kết hợp ipset với một số tính năng khác của iptables, chẳng hạn như packet marking, để thực hiện các chính sách về network. Bất cứ lúc nào bạn muốn thiết lập các rule firewall áp dụng cho một nhóm host hoặc nhiều địa chỉ cùng một lúc, bạn nên cân nhắc tới việc kết hợp cùng ipset.

Tham khảo

www.linuxjournal.com/content/advanced-firewall-configurations-ipset
blueprints.launchpad.net/neutron/+spec/add-ipset-to-security
ipset.netfilter.org/ipset.man