Từ iptables
tới nftables
nftables là một dự án phát triển sau với mục đích thay thế {ip,ip6,arp,eb}tables. Nó cung cấp một khuôn khổ phân loại gói tin mới dựa trên network-specific Virtual Machine và một command line tool mới. Nó có sẵn trên Linux Kernel kể từ phiên bản 3.13. Hầu hết các system admin đã quen với việc dùng iptables, bài này sẽ đưa ra các so sánh giữa iptables và nftables.
Lược sử iptables và nftables
Lược sử iptables và nftables
Cả iptables
và nftables
đều là những sản phẩm của dự án The Netfilter Project.
Netfilter được thành lập bởi Paul "Rusty" Russell, là một lập trình viên người Úc. Rusty đã kêu gọi nhằm thiết kế và cải thiện lại ipchains và ipfwadm trên những phiên bản Linux 2.0.x.
Các hoạt động đóng góp vào các ứng dụng sơ khởi trên Linux vẫn xảy ra, nhưng ít người có thể duy trì nó một cách lâu dài. Rusty là người kiên trì nhất và đã giữ vững các đóng góp của mình trong top đầu contributions. Điều này làm Marc Boucher chú ý và hai người đã thành lập dự án này. Hai người đã đóng góp nhiều công sức và viết ra một số modules như iptable_{filter,nat,mangle}
. Sau đó, những contributions tốt được James Morris đóng góp, thứ hạng ngay dưới Rusty. Morris là core team member thứ 3 của project. Cả ba người đã làm việc và phát hành Netfilter là một phần của Linux Kernel 2.4. Có nhiều thay đổi trong thời gian này, nhiều cộng đồng đã thành lập và giải tán. Nhiều người đã đóng góp vào project, Harald Welte là một người trẻ đã xử lý những hỗn độn trong NAT code.
Vào tháng 11 năm 2001, development workshop đầu tiên của netfilter được tổ chức. Kể từ đó, nhiều lần workshop được tổ chức hơn và có thêm các core member với những đóng góp rất tích cực. Tại lần thứ 2, họ đã quyết định rằng sẽ bầu một người làm chủ tịch, người đó sẽ đưa ra quyết định cuối cùng cho mọi chuyện. Những thành viên không còn đóng góp trong thời gian dài sẽ là thành viên danh dự.
Pablo Neira Ayuso trở thành co-maintainer từ 2011, và tại workshop 2013, anh chính thức được bầu làm người đứng đầu trong nhóm core team.
Note
Mặc dù nftables có những cải tiến trong việc quản lý dòng lệnh bằng command line interface, song đối với những hệ thống lớn, việc system admin gõ từng lệnh để cấu hình rule là không nhiều. Các rule chủ yếu sẽ được viết theo mẫu trên các file sau đó import cấu hình vào. Vậy nên bài viết sẽ nhấn mạnh các yếu tố sử dụng file config.
Info
Các câu lệnh và hình chụp được thực hiện trên lab, OS Rocky Linux 9.4
Chuyển config từ iptables sang nftables
Do cùng thuộc một project, với vai trò đi sau, nftables đương nhiên phải hỗ trợ chuyển đổi từ iptables sang nó. Rule cũ từ iptables có thể dễ dàng chuyển đổi sang nftables rule1 bằng câu lệnh iptables-translate
. Ví dụ:
iptables-translate -A OUTPUT -s 10.10.10.24/32 -d 10.10.15.11/32,10.10.25.11/32 -p tcp -m tcp --dport 3306 -m state --state NEW,ESTABLISHED -j ACCEPT -m comment --comment "Allow call database"
nft 'add rule ip filter OUTPUT ip saddr 10.10.10.24 ip daddr 10.10.15.11 tcp dport 3306 ct state new,established counter accept comment "Allow call database"'
'add rule ip filter OUTPUT ip saddr 10.10.10.24 ip daddr 10.10.25.11 tcp dport 3306 ct state new,established counter accept comment "Allow call database"'
Ngoài ra còn một số câu lệnh khác được hỗ trợ, sẽ không đề cập thêm ở đây do tác giả thấy không cần thiết.
Warning
Sau khi kiểm thử, nhận thấy rằng các rule được translate có thể không hoạt động giống cách mà chúng hoạt động ở iptables. Kiểm tra lại các rule trước khi active chúng vì nó sẽ drop connection. Hãy cẩn thận nếu không bạn sẽ rơi vào tình trạng tự cắn lưỡi do drop ssh connection.
Phương pháp cấu hình
Bằng kinh nghiệm cá nhân, như đã đề cập ở trên, tôi thấy phần lớn sẽ tập trung rule trong một hoặc một số file, mỗi khi cần thêm/xóa rule, system admin thêm/xóa rule trong các file này. Sau đó restart iptables hoặc dùng chuỗi các dòng lệnh nhằm xóa tất cả rule hiện hữu, thêm toàn bộ rule mới, commit cấu hình hiện tại.
Sau khi tham khảo một số phương pháp cấu hình iptables2 và so sánh với phương pháp cấu hình của bản thân, nhận thấy các phương pháp cấu hình không hỗ trợ nhiều file rule. Hoặc các rule sẽ được viết hết vào 1 file, hoặc sẽ dùng script để load nhiều file rule. Như vậy, ưu điểm của nftables đã rõ ràng hơn khi nó có hỗ trợ nhiều file config thông qua config include
.
Bắt đầu cấu hình với nftables
Sau khi cài đặt (hoặc start service đối với các server có sẵn), ta có thông tin của file nftables.service
Kiểm tra nội dung file, ta thấy khi start hoặc reload, nftables sẽ flush ruleset
và load toàn bộ rule từ file /etc/sysconfig/nftables.conf
.
Sau khi theo dõi file config của file /etc/sysconfig/nftables.conf
, nhận thấy nó sẽ include tới các file trong /etc/nftables
. Cụ thể là main.nft
. Trong main.nft
, ta lại thấy nó include các file khác trong thư mục.
Best Practice
Như vậy, best practice có khả năng là:
- Uncomment dòng include trong file
/etc/sysconfig/nftables.conf
để nó yêu cầu rule set từ/etc/nftables/main.nft
- Backup và tạo mới file
/etc/nftables/main.nft
, trong file này include tới các file config rule chi tiết. - Tạo thư mục
/etc/nftables/conf.d/
và chứa tất cả các file rule chi tiết. Khai báo từng file trong/etc/nftables/main.nft
.
Tiến hành thử nghiệm
Ta sẽ tiến hành cấu hình với những rule cơ bản
- Chỉ mở kết nối SSH từ một source IP tới server
- Cho phép ping tới server
- Established connections được cho phép ở cả hai chain INPUT và OUTPUT
- Allow traffic loopback và forward
- DROP các connection khác trên chain INPUT và OUTPUT.
Theo như best practice đã đề cập ở phần trên. ta cấu hình như sau
# Uncomment the include statement here to load the default config sample
# in /etc/nftables for nftables service.
include "/etc/nftables/main.nft"
# To customize, either edit the samples in /etc/nftables, append further
# commands to the end of this file or overwrite it after first service
# start by calling: 'nft list ruleset >/etc/sysconfig/nftables.conf'.
- Rule allow ssh from in comming. Because all established accepted, so we don't need create same rule for chain OUTPUT. If you do not have established rule, you must be create one more rule for OUTPUT chain.
Để các rule hoạt động, ta restart nftable bằng câu lệnh systemctl restart nftables
. Kiểm tra lại danh sách rule, nft list ruleset
, kết quả như sau
table ip connection {
chain INPUT {
type filter hook input priority filter; policy drop;
ip saddr 10.30.90.40 ip daddr 10.20.90.30 tcp dport 22 ct state established,new counter packets 993 bytes 77572 accept comment "Allow ssh connection from my server"
iifname "lo" counter packets 0 bytes 0 accept
icmp type echo-request counter packets 0 bytes 0 accept
icmp type echo-reply counter packets 0 bytes 0 accept
ct state established counter packets 0 bytes 0 accept
counter packets 108 bytes 6894 drop
}
chain FORWARD {
type filter hook forward priority filter; policy accept;
counter packets 0 bytes 0 accept
}
chain OUTPUT {
type filter hook output priority filter; policy drop;
oifname "lo" counter packets 0 bytes 0 accept
ct state established counter packets 745 bytes 163284 accept
counter packets 360 bytes 58317 drop
}
}
Kiểm tra lại thấy ssh đã vào được server, nhưng các connection tới nginx, httpd đã không còn hoạt động.
Inside the blind box
Lược dịch từ bài viết của Andrej Stender3 và thêm vào các chi tiết của tôi
Netfilter
Netfilter là một framework trong linux kernel. Nó cung cấp các hooks cho phép các packages trong mạng đi qua và xử lý chúng khi các packages này đi qua kernel. Các thành phần khác của kernel có thể đăng ký hàm call back với các hooks này, cho phép chúng kiểm tra các gói tin và tiến hành drop, accept gói tin trong kernel.
flowchart LR
A(net_device) --> B[Prerouting];
B --> C{ Routing };
C --> D[Input];
C --> E[Forward];
D --> F(Local Process);
F --> G(Routing);
G --> H[Output];
H --> I[Postrouting];
I --> Z(net_device);
E --> I;
Một gói tin nhận được từ network device đầu tiên đi qua Prerouting hook. Định tuyến quyết định chuyện gì sẽ xảy ra và kernel xác định gói tin này có được đưa vào một local process (chuyển tới một port đang listen trên server) hay forward nó tới Postrouting (trường hợp hệ thống hoạt động như router).
Trong trường hợp đầu tiên, gói tin chuyển tới Input hook và đi vào local process. Local process xử lý các tác vụ của chương trình và tạo ra một gói tin (server trả lời message của client) và gửi chúng tới Output hook, đi tới Postrouting hook, cuối cùng gửi ra ngoài thông qua một network device.
Trong trường hợp thứ hai, gói tin chuyển qua Forward hook và đi tới Postrouting hook, cuối cùng gửi ra ngoài thông qua một network device.
Netfilter hook
là một tập các hook functions
được sắp xếp theo thứ tự ưu tiên. Đối với mỗi gói tin mạng đi qua hook , các hook functions sẽ được gọi lần lượt theo thứ tự mà chúng có trong mảng hook (thứ tự được xác định bởi độ ưu tiên).
Mỗi hook function
được yêu cầu trả về một giá trị cho Netfilter
, Có một vài giá trị trả về nhưng chỉ có hai giá trị liên quan là NF_ACCEPT và NF_DROP. NF_ACCEPT nói với Netfilter rằng nó "cho phép" gói tin đó, tới trạm của hook function
tiếp theo (nếu tồn tại). Nếu tất cả các hook function
đều trả về NF_ACCEPT, gói tin sẽ đi tiếp quá trình của nó trong kernel network stack. Ngược lại, gói tin sẽ bị "dropped" và nó sẽ không còn di chuyển tới hook function
tiếp theo.
Iptables
Iptables tổ chức các rules của nó vào các tables và chains. Các tables đơn giản được hiểu là các group để gom các chains
có điểm chung lại với nhau. Các rules thật sự nằm trong các chain. Iptables đăng ký các chains này với Netfilter hook như là các hook function. Nghĩa là khi các gói tin đi qua một hook (Prerouting, Input) thì sẽ đi qua các hook function được đăng ký với chúng, và do đó, đi qua các rule được quy định.
Iptables, có một tập hợp các tables đã đã được tạo trước, mỗi tables có một số chains đã được định sẵn. Các chains được đặt tên giống như tên của các hook của Netfilter.
table | contains chains |
---|---|
filter | INPUT , FORWARD ,OUTPUT |
nat | PREROUTING ,INPUT , OUTPUT ,POSTROUTING |
mangle | PREROUTING ,INPUT , FORWARD ,OUTPUT ,POSTROUTING |
raw | PREROUTING ,OUTPUT |
Các tables và các chain mặc định này có thể dễ dàng thấy được khi ta cấu hình các rule, và sau đó sử dụng câu lệnh iptables-save để lưu các rule đó vào file. Hình dưới cho thấy, mặc dù trên hệ thống của mình không setup các rule ở các tables mangle, raw thì khi save các rule, iptables vẫn nhận diện các rule mặc định để lưu vào file.
Do các chains trong iptables được đặt tên giống với các hook name trong Netfilter, ta dễ dàng biết được các chain đó sẽ được đưa vào hook nào trong Netfilter flow. Hình dưới mô tả flow gói tin sẽ đi qua tập chác chain của iptables đã đăng ký với Netfilter hook. Có thể thấy rõ chains nào của iptables sẽ được gọi trước, cái nào được gọi sau (thông qua chỉ số ưu tiên màu đỏ, nhỏ hơn thì được gọi trước).
Như vậy, iptables có các chain tương tác với tất cả các hook trong Netfilter. Và do iptables có pre-defined tables và chains, các rule mặc định sẽ luôn được gọi ở các hook function bất kể việc chúng ta có định nghĩa chúng hay không. Hai điểm này là điểm khác biệt lớn và là ý tưởng để tạo nên nftables
sau này.
nftables
Nhìn chung, cách mà nftables
tổ chức các rules, chains và tables giống như iptables. Các tables tiếp tục chứa các chains và các chains mang rules. Tuy nhiên, như đã đề cập ở phần trên, người dùng phải định nghĩa toàn bộ các tables và chains một cách rõ ràng. Người dùng đặt tên cho các tables và chains khi tạo chúng.
NFtables chia các chains thành hai loại:
- Base-chains sẽ được đăng ký với Netfilter như là một hook function đã đề cập ở trên và người dùng cần chỉ định hook đó khi tạo chains. Người dùng không bị bắt buộc tạo chains name giống với name của Netfilter hook mà chúng được đăng ký. Điều này vừa thuận lợi nhưng cũng đồng thời gây ra một số nhầm lần
- Regular chains không được đăng ký với bất kỳ hook nào.
Không giống như iptables phải chia ra nhiều userspace tool để hỗ trợ các thành phần khác nhau (ipv4, ipv6), nftables sử dụng một concept mới gọi là Address Families. Khi người dùng tạo table, sẽ cần phải chỉ định nó được tạo trong Address Families nào. Các Address Families được map với các hook theo danh sách bên dưới.
ip
: maps to IPv4 protocol hooks /NFPROTO_IPV4
(default)ip6
: maps to IPv6 protocol hooks /NFPROTO_IPV6
inet
: maps to both IPv4 and IPv6 protocol hooksarp
: maps to ARP protocol hooks /NFPROTO_ARP
bridge
: maps to bridging hooks /NFPROTO_BRIDGE
netdev
: maps to ingress hook /NFPROTO_NETDEV
Ví dụ sau nghĩa là, bạn tạo một table mới tên foo
, trong Address Families ip, sau đó tạo một base-chains tên là bar
trong table foo
, đăng ký nó với Netfilter hook input
, chỉ định số ưu tiên là 0
Ruleset best practice
Do đã quen thuộc với cách đặt tên các table và chain ở iptables giống với các hook ở Netfilter, mặc dù nftable không bắt buộc, ta cũng nên đặt tên table và chain như vậy để dễ quản lý và vận hành trong quá trình chuyển tiếp.
add table inet filter
# Base chain
add chain inet filter INPUT { type filter hook input priority 0; policy drop; }
add chain inet filter FORWARD { type filter hook forward priority 0; policy accept; }
add chain inet filter OUTPUT { type filter hook output priority 0; policy drop; }
# Regular chain
add rule inet filter INPUT iifname "lo" counter accept comment "Allow connection on loopback interface"
add rule inet filter INPUT icmp type echo-request counter accept comment "Allow ping to server"
add rule inet filter INPUT icmp type echo-reply counter accept comment "Allow reply ping package"
add rule inet filter INPUT ip saddr 10.30.90.40 ip daddr 10.30.90.40 counter accept
add rule inet filter INPUT ct state established counter accept comment "Allow reply package on input chain"
add rule inet filter INPUT ip saddr 10.30.80.40 ip daddr 10.30.90.40 tcp dport 22 ct state new,established counter accept comment "Allow ssh from my admin server"
add rule inet filter INPUT counter drop comment "Drop other input connection"
add rule inet filter OUTPUT oifname "lo" counter accept comment "Allow connection on loopback interface"
add rule inet filter OUTPUT ct state established counter accept comment "Allow reply package"
add rule inet filter OUTPUT counter drop comment "Drop other output connection"
Bên trên diễn dải danh sách rule được sử dụng với cùng yêu cầu thể hiện tại phần thực nghiệm
-
nftables wiki. Moving from iptables to nftables. 2021. URL: https://wiki.nftables.org/wiki-nftables/index.php/Moving_from_iptables_to_nftables (visited on 2024-10-03). ↩
-
SERVER FAULT. Insert multiple iptables rules in critical situations. 2019. URL: https://serverfault.com/questions/980343/insert-multiple-iptables-rules-in-critical-situations (visited on 2024-10-03). ↩
-
Andrej Stender. Nftables - packet flow and netfilter hooks in detail. 2022. URL: https://thermalcircle.de/doku.php?id=blog:linux:nftables_packet_flow_netfilter_hooks_detail (visited on 2024-10-14). ↩