Firewall với firewalld: zone, service và port
Thực hiện trên server của bạn, rồi kiểm tra từng tiêu chí.
Vì sao cần học
Mỗi port mở ra ngoài là một cửa cho kẻ tấn công. Firewall trên host là lớp bảo vệ cuối cùng khi firewall mạng hoặc security group bị cấu hình sai. Firewall cũng là nguyên nhân hàng đầu của lỗi "chạy trên server thì được, từ máy khác thì không"; bài Break/Fix firewall sẽ cho bạn gặp lỗi này.
Mục tiêu
- Hiểu zone, interface và nguồn (source) trong firewalld.
- Mở theo service thay vì port khi có thể; đóng những gì không dùng.
- Phân biệt runtime và permanent, và biết cách đồng bộ hai lớp.
- Đọc cấu hình đang có hiệu lực bằng
--list-all.
Điều kiện tiên quyết
- Bài Lệnh mạng và cấu hình bền vững bằng nmcli.
- Console dự phòng của VM. Rule firewall sai có thể chặn chính phiên SSH của bạn.
Mental model
Zone là một bộ rule. Mỗi interface (hoặc dải địa chỉ nguồn) thuộc một zone; gói tin vào interface nào thì áp rule của zone đó. Zone mặc định thường là public.
Service là tên đặt cho một nhóm port, ví dụ ssh là 22/tcp, http là 80/tcp. Mở theo service dễ đọc hơn và không phải nhớ số port.
Runtime và permanent là hai lớp riêng:
| Lệnh | Runtime (đang chạy) | Permanent (sau reload/reboot) |
|---|---|---|
firewall-cmd --add-service=http | Có | Không |
firewall-cmd --permanent --add-service=http | Không | Có |
firewall-cmd --reload | Nạp lại từ permanent, mất thay đổi chỉ có ở runtime | |
firewall-cmd --runtime-to-permanent | Lưu runtime hiện tại thành permanent |
Cách làm an toàn: thử ở runtime, kiểm tra, rồi --runtime-to-permanent. Nếu lỡ khóa mình, reboot sẽ đưa về cấu hình permanent cũ.
Thực hành (Guided Lab)
1. Bật firewalld mà không tự khóa mình
sudo dnf install -y firewalld
sudo firewall-offline-cmd --list-services
Giải thích lệnh và tham số
firewall-offline-cmd đọc/sửa cấu hình permanent khi firewalld chưa chạy. --list-services liệt kê service được phép trong zone được chọn (mặc định là zone mặc định). Nếu thiếu SSH, sudo firewall-offline-cmd --add-service=ssh thêm service SSH vào cấu hình đó trước khi bật firewall.
ssh phải có trong danh sách. Nếu không có, thêm trước khi bật: sudo firewall-offline-cmd --add-service=ssh.
sudo systemctl enable --now firewalld
sudo firewall-cmd --state
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all
Giải thích lệnh và tham số
firewall-cmd làm việc với firewalld đang chạy: --state hỏi trạng thái (running), --get-default-zone lấy tên zone mặc định, --get-active-zones xem zone gắn với interface/source đang hoạt động, --list-all xem toàn bộ rule của zone. Các truy vấn mặc định đọc runtime; thêm --permanent để đọc cấu hình đã lưu.
2. Mở và đóng service
sudo firewall-cmd --add-service=http
sudo firewall-cmd --remove-service=cockpit
sudo firewall-cmd --list-services
sudo firewall-cmd --permanent --list-services
Giải thích lệnh và tham số
--add-service=http cho phép service HTTP đã định nghĩa (thường TCP/80), --remove-service=cockpit bỏ service cockpit khỏi zone, --list-services xem kết quả. Các lệnh không có --permanent chỉ sửa runtime. --runtime-to-permanent ở nhóm lệnh tiếp theo lưu toàn bộ runtime thành permanent, không chỉ rule vừa thêm; xem lại runtime trước khi lưu.
Hai danh sách khác nhau: thay đổi mới chỉ ở runtime. Lưu lại:
sudo firewall-cmd --runtime-to-permanent
sudo firewall-cmd --permanent --list-services
Giải thích lệnh và tham số
--runtime-to-permanent lưu rule runtime hiện tại thành cấu hình permanent. --permanent --list-services xem danh sách service trong cấu hình đã lưu.
3. Mở một port không có service sẵn
sudo firewall-cmd --permanent --add-port=8443/tcp
sudo firewall-cmd --query-port=8443/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --query-port=8443/tcp
Giải thích lệnh và tham số
--add-port=8443/tcp cho phép cổng 8443 giao thức TCP; --query-port hỏi rule có cho phép không (yes/no). --permanent chỉ sửa cấu hình đã lưu. --reload nạp permanent vào runtime, làm mất các thay đổi chỉ có ở runtime. Mở firewall chưa tạo dịch vụ lắng nghe ở cổng đó.
Trước --reload, port chỉ có trong permanent nên truy vấn runtime trả no. Sau --reload, cả hai lớp đều có.
4. Giới hạn theo nguồn bằng rich rule (tham khảo, không chấm)
Chỉ cho mạng 10.99.0.0/24 vào port 5432:
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.99.0.0/24" port port="5432" protocol="tcp" accept'
sudo firewall-cmd --list-rich-rules
sudo firewall-cmd --reload
Giải thích lệnh và tham số
--add-rich-rule='...' thêm rule nhiều điều kiện: family="ipv4" chọn IPv4, source address="10.99.0.0/24" giới hạn dải nguồn, port="5432" protocol="tcp" chọn port/giao thức, accept cho phép. Nháy đơn giữ cả rule thành một đối số. --list-rich-rules xem rule runtime; --reload bỏ rule runtime này vì chưa lưu permanent.
Lệnh --reload bỏ rule này vì nó chỉ có ở runtime.
Tự kiểm tra (Verification)
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --list-all
Giải thích lệnh và tham số
firewall-cmd --list-all xem zone cùng rule runtime; thêm --permanent để xem cấu hình đã lưu, có hiệu lực sau reload/reboot.
Từ máy của bạn, curl http://<ip-của-vm>:8443 nhận Connection refused (không có dịch vụ) thay vì treo tới timeout. Treo nghĩa là gói tin bị firewall bỏ. Chọn server và bấm Kiểm tra kết quả.
Lỗi thường gặp
- Chỉ chạy lệnh không có
--permanent: mọi thứ mất sau--reloadhoặc reboot. - Chỉ chạy
--permanentmà quên--reload: rule chưa có hiệu lực. - Mở port ở zone không gắn với interface đang dùng. Kiểm tra
--get-active-zones. systemctl stop firewalldđể "thử cho nhanh" rồi quên bật lại.
Ghi chú production
- Mở theo nguyên tắc ít nhất: chỉ các service cần, giới hạn nguồn cho port quản trị và database.
- Trên cloud có thêm security group/firewall mạng; cần mở ở cả hai lớp. Module 09 sẽ học security group.
- Quản lý firewall bằng code (Ansible, Module 07) thay vì gõ tay trên từng máy.
Ghi chú Ubuntu
Ubuntu dùng ufw mặc định. Để làm bài này, sudo ufw disable, rồi sudo apt install firewalld. Không chạy hai firewall cùng lúc.
Dọn dẹp
Giữ firewalld chạy cho các bài sau. Muốn bỏ thay đổi của bài này:
sudo firewall-cmd --permanent --remove-service=http
sudo firewall-cmd --permanent --remove-port=8443/tcp
sudo firewall-cmd --reload
Giải thích lệnh và tham số
--remove-service=http bỏ service HTTP; --remove-port=8443/tcp bỏ rule cổng TCP/8443. --permanent sửa cấu hình đã lưu; --reload áp dụng cấu hình đó vào runtime.