Cách đây hơn 1 tháng có bạn đã gửi câu hỏi trong bài viết Hướng dẫn cài đặt Netdata như sau: “Bạn cho mình hỏi cách khóa truy cập thông qua địa chỉ ip:port cụ thể được không, hiện tại mình dùng ufw để block port 19999 nhưng khi truy cập qua ip của vps dưới dạng x.x.x.x:19999 thì vẫn vào được trang netdata.

Sau đó mình kiểm tra lại thì mới phát hiện ra rằng trên máy chủ Linux, tường lửa UFW sẽ không hoạt động nếu Docker đang được kích hoạt: UFW không chặn được truy cập các port được khai báo bởi Docker

Cụ thể lỗi và cách khắc phục lỗi các bạn xem tiếp bên dưới sẽ rõ.

I. Kích hoạt UFW

Cài đặt UFW bằng lệnh sudo apt install ufw -y, sau đó mở cổng 22 và kích hoạt UFW trên hệ thống

ufw allow ssh
ufw default deny incoming
ufw enable
Code language: JavaScript (javascript)

Kiểm tra tình trạng hoạt động của ufw bằng lệnh ufw status, sẽ thấy trạng thái active (đang hoạt động)

Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere                  
22/tcp (v6)                ALLOW       Anywhere (v6)             Code language: YAML (yaml)

Mình sử dụng 1 máy tính khác để kiểm tra port 8888 của máy chủ (IP: xxx.xxx.xxx.xxx) có đang mở không. Sử dụng lệnh:

nmap -Pn -p 80 xxx.xxx.xxx.xxxCode language: CSS (css)

Kết quả trả về sẽ thấy cổng 8888 đang bị chặn (STATE: filtered)

Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-27 17:17 +07
Nmap scan report for static.xxx.xxx.xxxclients.your-server.de (xxx.xxx.xxx.xxx)
Host is up.

PORT     STATE    SERVICE
8888/tcp filtered sun-answerbook

Nmap done: 1 IP address (1 host up) scanned in 2.06 secondsCode language: YAML (yaml)

II. Kích hoạt Docker

Mình kích hoạt Smokeping trên máy chủ, sử dụng file docker-compose.yml với nội dung như sau

---
version: "2.1"
services:
  smokeping:
    image: lscr.io/linuxserver/smokeping
    container_name: smokeping
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Ho_Chi_Minh
    volumes:
      - ./config:/config
      - ./data:/data
    ports:
      - 8888:80
    restart: unless-stoppedCode language: YAML (yaml)

III. Cổng 8888 giờ đã được mở!

Giờ kiểm tra port 8888 lại từ máy tính khác

nmap -Pn -p 80 xxx.xxx.xxx.xxxCode language: CSS (css)
Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-27 17:21 +07
Nmap scan report for static.xxx.xxx.xxxclients.your-server.de (xxx.xxx.xxx.xxx)
Host is up (0.28s latency).

PORT     STATE SERVICE
8888/tcp open  sun-answerbook

Nmap done: 1 IP address (1 host up) scanned in 0.34 secondsCode language: YAML (yaml)

Ngạc nhiên chưa! Cổng 8888 giờ đã chuyển sang trạng thái open, mặc dù đã thiết lập UFW chặn tất cả cổng trừ cổng 22 của SSH.

Đây là một lỗi bảo mật nguy hiểm vì cứ tưởng hệ thống đã được UFW bảo vệ, nhưng hóa ra lại không.

IV. Nguyên nhân gây lỗi

Nguyên nhân khiến UFW không còn hoạt động là do Docker có quyền chỉnh sửa trực tiếp vào iptables của hệ thống. Khi kích hoạt Smokeping, Docker tự động thêm Rule DNAT vào iptables, giúp truy cập được cổng 8888 từ bên ngoài.

Kiểm tra iptables bằng lệnh sau

iptables -t nat --list | grep 8888Code language: PHP (php)

Sẽ thấy kết quả như dưới đây

DNAT       tcp  --  anywhere             anywhere             tcp dpt:8888 to:172.20.0.2:80Code language: CSS (css)

V. Cách khắc phục

Có hai cách để khắc phục lỗi UFW không hoạt động khi sử dụng Docker.

1. Ngăn Docker chỉnh sửa iptables

Chỉnh sửa file /etc/docker/deamon.json

sudo nano /etc/docker/daemon.jsonCode language: Nginx (nginx)

Thêm vào dòng { "iptables" : false } và lưu lại.

Khởi động lại Docker bằng lệnh

sudo service docker restartCode language: Nginx (nginx)

Kiểm tra lại kết nối từ bên ngoài, giờ đã yên tâm cổng 8888 đã bị khóa.

Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-27 16:27 +07
Nmap scan report for static.xxx.xxx.xxxclients.your-server.de (xxx.xxx.xxx.xxx)
Host is up.

PORT     STATE    SERVICE
8888/tcp filtered http-proxy

Nmap done: 1 IP address (1 host up) scanned in 2.04 secondsCode language: YAML (yaml)

Ưu và nhược điểm của cách này như sau:

  • Ưu điểm: chỉnh sửa nhanh, gọn, lẹ, phù hợp với các máy chủ chỉ chạy 1-2 dịch vụ Docker.
  • Nhược điểm: tính năng quản lý mạng của Docker bị vô hiệu hóa, khiến cho các dịch vụ mạng khởi tạo sau đó sẽ không thể truy cập được mạng Internet.

Nếu muốn dịch vụ Docker truy cập được mạng Internet, phải chỉnh sửa file cấu hình của UFW:

nano /etc/default/ufwCode language: JavaScript (javascript)

Thêm vào dòng sau để mở kết nối mạng cho Docker network:

-A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADECode language: YAML (yaml)

Trong đó 172.17.0.0/16 là Subnet của Docker network. Nếu có nhiều Docker network, phải thêm nhiều dòng tương ứng

2. Sử dụng ufw-docker

Để vừa bảo đảm các rule tường lửa của UFW hoạt động trơn tru, vừa giúp Docker duy trì tính năng quản lý mạng, chúng ta sẽ nhờ đến sự trợ giúp của công cụ ufw-docker.

Chi tiết cách thức hoạt động khá là rắc rối, được ghi trên trang Github. Để dễ hiểu, mình chỉ tải về và sử dụng.

sudo wget -O /usr/local/bin/ufw-docker \
  https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
sudo chmod +x /usr/local/bin/ufw-dockerCode language: Bash (bash)

Nếu bạn đã chỉnh sửa file /etc/docker/deamon.json theo hướng dẫn ở cách 1, cần phải xóa nó đi và khởi động lại Docker

sudo rm /etc/docker/deamon.json
sudo service docker restartCode language: Nginx (nginx)

Cài đặt ufw-docker bằng lệnh sau, nó sẽ thêm một số rule vào file after.rules của ufw

ufw-docker install

Sau đó, kích hoạt lại Smokeping, sẽ thấy port 8888 giờ đã bị chặn truy cập từ bên ngoài.

Để mở truy cập vào tất cả các cổng đang mở của Smokeping, mình dùng lệnh sau

ufw-docker allow smokeping

Hệ thống sẽ hiện ra thông báo các rule được thêm vào ufw như dưới đây

allow smokeping 80/tcp smokeping_default
ufw route allow proto tcp from any to 172.18.0.2 port 80 comment allow smokeping 80/tcp smokeping_defaultCode language: YAML (yaml)

Kiểm tra lại từ máy bên ngoài, port 8888 giờ đã truy cập thành công

Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-28 19:27 +07
Nmap scan report for static.xxx.xxx.xxxclients.your-server.de (xxx.xxx.xxx.xxx)
Host is up (0.35s latency).

PORT     STATE SERVICE
8888/tcp open  sun-answerbook

Nmap done: 1 IP address (1 host up) scanned in 0.38 seconds
Code language: YAML (yaml)

Để xem các lệnh khác của ufw-docker, gõ

ufw-docker helpCode language: Bash (bash)

Kết quả

Usage:
  ufw-docker <list|allow> [docker-instance-id-or-name [port[/tcp|/udp]] [network]]
  ufw-docker delete allow [docker-instance-id-or-name [port[/tcp|/udp]] [network]]

  ufw-docker service allow <swarm-service-id-or-name <port</tcp|/udp>>>
  ufw-docker service delete allow <swarm-service-id-or-name>

  ufw-docker <status|install|check|help>

Examples:
  ufw-docker help

  ufw-docker check           # Check the installation of firewall rules
  ufw-docker install         # Install firewall rules

  ufw-docker status

  ufw-docker list httpd


  ufw-docker allow httpd
  ufw-docker allow httpd 80
  ufw-docker allow httpd 80/tcp
  ufw-docker allow httpd 80/tcp default

  ufw-docker delete allow httpd
  ufw-docker delete allow httpd 80/tcp
          ufw-docker delete allow httpd 80/tcp default

  ufw-docker service allow httpd 80/tcp

  ufw-docker service delete allow httpdCode language: YAML (yaml)

Ví dụ, mình có thể kiểm tra các rule đã được thêm vào bởi ufw-docker bằng lệnh ufw-docker status, kết quả sẽ hiện ra như bên dưới

[ 3] 172.18.0.2 80/tcp          ALLOW FWD   Anywhere                   # allow smokeping 80/tcp smokeping_default
Code language: YAML (yaml)

Vậy là xong. UFW và Docker giờ đã hoạt động êm ái cùng nhau.

Lưu ý: Nếu bạn cần hỗ trợ kỹ thuật, vui lòng gửi câu hỏi trực tiếp ở phần Thảo luận bên dưới, mình sẽ trả lời sớm. Đừng vào hỏi trong fanpage Yêu Chạy Bộ, sẽ không có phản hồi đâu!

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *


3 Comments

  1. Hôm trước mình cũng bị cái này, cài mấy cái redis, mongo bằng docker, tưởng ufw có chặn ai dè hôm sau hacker vào phá mới biết 🙂 thế là tắt gán port cho host luôn, sau đó set ip tĩnh cho container, xong cho mấy app gọi vào ip của container với port default của nó cho chắc ăn.

    1