Mục lục

Không có mục lục

Cách thiết lập tường lửa Iptables để bảo vệ lưu lượng giữa các máy chủ của bạn

Ngày đăng: 4 tháng 10 năm 2023

Giới thiệu

Triển khai các thành phần riêng biệt trong thiết lập ứng dụng của bạn trên các node khác nhau là cách phổ biến để giảm tải và bắt đầu mở rộng quy mô theo chiều ngang. Một ví dụ điển hình là định cấu hình cơ sở dữ liệu trên một máy chủ riêng biệt với ứng dụng của bạn. Mặc dù có một số lợi thế với thiết lập này, nhưng việc kết nối qua mạng lại kéo theo một loạt mối lo ngại mới về bảo mật.

Trong hướng dẫn này, chúng tôi sẽ trình bày cách thiết lập tường lửa trên mỗi máy chủ của bạn trong thiết lập phân tán. Chúng tôi sẽ định cấu hình chính sách của mình để cho phép lưu lượng truy cập dự định giữa các thành phần của chúng tôi trong khi từ chối lưu lượng truy cập khác.

Để trình bày trong hướng dẫn này, chúng tôi sẽ sử dụng hai máy chủ Ubuntu 22.04. Một cái sẽ có một ứng dụng web được cung cấp bởi Nginx và cái còn lại sẽ lưu trữ cơ sở dữ liệu MySQL cho ứng dụng. Mặc dù chúng tôi sẽ sử dụng thiết lập này làm ví dụ nhưng bạn sẽ có thể ngoại suy các kỹ thuật liên quan để phù hợp với yêu cầu máy chủ của riêng bạn.

Điều kiện tiên quyết

Để bắt đầu, bạn sẽ phải có hai máy chủ Ubuntu 22.04 mới. Thêm tài khoản người dùng thông thường với các đặc quyền sudo trên mỗi tài khoản. Để thực hiện việc này, hãy làm theo hướng dẫn thiết lập máy chủ ban đầu Ubuntu 22.04 của chúng tôi.

Quá trình thiết lập ứng dụng mà chúng tôi sẽ bảo mật dựa trên hướng dẫn Cách thiết lập cơ sở dữ liệu từ xa để tối ưu hóa hiệu suất trang web với MySQL trên Ubuntu 20.04. Nếu bạn muốn làm theo ví dụ đó, hãy thiết lập ứng dụng và máy chủ cơ sở dữ liệu của bạn như được chỉ ra trong hướng dẫn đó. Nếu không, bạn có thể sử dụng bài viết này như một tài liệu tham khảo chung.

Bước 1 - Thiết lập tường lửa

Bạn sẽ bắt đầu bằng cách triển khai cấu hình tường lửa cơ bản cho từng máy chủ của mình. Chính sách mà chúng tôi sẽ triển khai áp dụng cách tiếp cận ưu tiên bảo mật. Chúng tôi sẽ khóa hầu hết mọi thứ ngoài lưu lượng SSH và sau đó chọc thủng tường lửa cho ứng dụng cụ thể của chúng tôi.

Hướng dẫn này tuân theo cú pháp iptables. iptables được cài đặt tự động trên Ubuntu 22.04 bằng chương trình phụ trợ nftables, do đó bạn không cần phải cài đặt bất kỳ gói bổ sung nào.

Sử dụng nano hoặc trình soạn thảo văn bản yêu thích của bạn, mở tệp /etc/iptables/rules.v4:

  1. sudo nano /etc/iptables/rules.v4

Dán cấu hình từ hướng dẫn mẫu tường lửa:

/etc/iptables/rules.v4
*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]

# Acceptable UDP traffic

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT

# Acceptable ICMP traffic

# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable

# Commit the changes
COMMIT

*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

Lưu và đóng tập tin. Nếu bạn đang sử dụng nano, hãy nhấn Ctrl+X để thoát, sau đó khi được nhắc, Y rồi Enter.

Nếu bạn đang triển khai điều này trong môi trường trực tiếp (live environment), đừng tải lại các quy tắc tường lửa của mình. Việc tải bộ quy tắc được nêu ở đây sẽ ngay lập tức ngắt kết nối giữa ứng dụng và máy chủ cơ sở dữ liệu của bạn. Bạn sẽ cần điều chỉnh các quy tắc để phản ánh nhu cầu hoạt động của chúng tôi trước khi tải lại.

Bước 2 - Khám phá các cổng đang được dịch vụ của bạn sử dụng

Để cho phép liên lạc giữa các thành phần, bạn cần biết các cổng mạng đang được sử dụng. Bạn có thể tìm thấy các cổng mạng chính xác bằng cách kiểm tra các tệp cấu hình của mình, nhưng một phương pháp không xác định ứng dụng để tìm các cổng chính xác là chỉ kiểm tra xem dịch vụ nào đang lắng nghe kết nối trên mỗi máy của chúng tôi.

Bạn có thể sử dụng công cụ netstat để tìm hiểu điều này. Vì ứng dụng của bạn chỉ giao tiếp qua IPv4 nên chúng tôi sẽ thêm đối số -4, nhưng bạn có thể xóa đối số đó nếu bạn cũng đang sử dụng IPv6. Các đối số khác mà bạn cần để tìm các dịch vụ đang chạy của mình là -p, -l, -u, -n-t mà bạn có thể cung cấp dưới dạng -plunt.

Những lập luận này có thể được chia nhỏ như sau:

  • p: Hiển thị PID và tên chương trình chứa từng socket.
  • l: Chỉ hiển thị ổ cắm nghe.
  • u: Hiển thị lưu lượng UDP.
  • n: Hiển thị đầu ra dạng số thay vì tên dịch vụ.
  • t: Hiển thị lưu lượng TCP.
  1. sudo netstat -4plunt

Trên máy chủ web của bạn, kết quả đầu ra của bạn có thể trông như thế này:

Output
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1058/sshd tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx

Cột được đánh dấu đầu tiên hiển thị địa chỉ IP và cổng mà dịch vụ được đánh dấu ở cuối dòng đang nghe. Địa chỉ 0.0.0.0 đặc biệt có nghĩa là dịch vụ được đề cập đang lắng nghe tất cả các địa chỉ khả dụng.

Trên máy chủ cơ sở dữ liệu của bạn, kết quả đầu ra của bạn có thể trông như thế này:

  1. sudo netstat -4plunt
Output
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1097/sshd tcp 0 0 192.0.2.30:3306 0.0.0.0:* LISTEN 3112/mysqld

Bạn có thể đọc các cột này giống hệt nhau. Trong ví dụ này, địa chỉ 192.0.2.30 đại diện cho địa chỉ IP riêng của máy chủ cơ sở dữ liệu. Trong phần hướng dẫn tiên quyết, bạn đã giới hạn MySQL ở giao diện riêng tư vì lý do bảo mật.

Hãy lưu ý các giá trị bạn tìm thấy trong bước này. Đây là các chi tiết mạng mà bạn sẽ cần để điều chỉnh cấu hình tường lửa của mình.

Trên máy chủ web của bạn, bạn cần đảm bảo rằng các cổng sau có thể truy cập được:

  • Cổng 80 trên tất cả các địa chỉ
  • Cổng 22 trên tất cả các địa chỉ (đã được tính trong quy tắc tường lửa)

Máy chủ cơ sở dữ liệu của bạn sẽ phải đảm bảo rằng các cổng sau có thể truy cập được:

  • Cổng 3306 trên địa chỉ 192.0.2.30 (hoặc giao diện được liên kết với nó)
  • Cổng 22 trên tất cả các địa chỉ (đã được tính trong quy tắc tường lửa)

Bước 3 - Điều chỉnh quy tắc tường lửa của máy chủ web

Bây giờ bạn đã có thông tin cổng mình cần, bạn sẽ điều chỉnh bộ quy tắc tường lửa của máy chủ web. Mở tệp quy tắc trong trình chỉnh sửa của bạn với các đặc quyền sudo:

  1. sudo nano /etc/iptables/rules.v4

Trên máy chủ web, bạn cần thêm cổng 80 vào danh sách lưu lượng truy cập được chấp nhận. Vì máy chủ đang lắng nghe tất cả các địa chỉ khả dụng — các máy chủ web thường có thể truy cập được từ mọi nơi — nên bạn sẽ không hạn chế quy tắc theo giao diện hoặc địa chỉ đích.

Khách truy cập web của bạn sẽ sử dụng giao thức TCP để kết nối. Framework của bạn đã có một chuỗi tùy chỉnh có tên TCP dành cho các ngoại lệ ứng dụng TCP. Bạn có thể thêm cổng 80 vào chuỗi đó, ngay bên dưới ngoại lệ cho cổng SSH của bạn:

/etc/iptables/rules.v4
*filter
. . .

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 80 -j ACCEPT

. . .

Máy chủ web của bạn sẽ bắt đầu kết nối với máy chủ cơ sở dữ liệu của bạn. Lưu lượng truy cập đi của bạn không bị hạn chế trong tường lửa và lưu lượng truy cập đến liên quan đến các kết nối đã thiết lập đều được cho phép, vì vậy chúng tôi không phải mở bất kỳ cổng bổ sung nào trên máy chủ này để cho phép kết nối này.

Lưu và đóng tập tin khi bạn hoàn tất. Máy chủ web của bạn hiện có chính sách tường lửa cho phép tất cả lưu lượng truy cập hợp pháp trong khi chặn mọi thứ khác.

Kiểm tra tệp quy tắc của bạn để tìm lỗi cú pháp:

  1. sudo iptables-restore -t < /etc/iptables/rules.v4

Nếu không có lỗi cú pháp nào hiển thị, hãy tải lại tường lửa để triển khai bộ quy tắc mới:

  1. sudo service iptables-persistent reload

Bước 4 - Điều chỉnh quy tắc tường lửa máy chủ cơ sở dữ liệu

Trên máy chủ cơ sở dữ liệu của bạn, bạn cần cho phép truy cập vào cổng 3306 trên địa chỉ IP riêng của máy chủ. Trong trường hợp này, địa chỉ đó là 192.0.2.30. Bạn có thể giới hạn quyền truy cập dành riêng cho địa chỉ này hoặc bạn có thể giới hạn quyền truy cập bằng cách khớp với giao diện được chỉ định địa chỉ đó.

Để tìm giao diện mạng được liên kết với địa chỉ đó, hãy chạy ip -4 addr show scope global:

  1. ip -4 addr show scope global
Output
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 203.0.113.5/24 brd 104.236.113.255 scope global eth0 valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 192.0.2.30/24 brd 192.0.2.255 scope global eth1 valid_lft forever preferred_lft forever

Các khu vực được đánh dấu cho thấy giao diện eth1 được liên kết với địa chỉ đó.

Tiếp theo, bạn sẽ điều chỉnh các quy tắc tường lửa trên máy chủ cơ sở dữ liệu. Mở tệp quy tắc với đặc quyền sudo trên máy chủ cơ sở dữ liệu của bạn:

  1. sudo nano /etc/iptables/rules.v4

Một lần nữa, bạn sẽ thêm một quy tắc vào chuỗi TCP của chúng tôi để tạo thành một ngoại lệ cho kết nối giữa máy chủ web và cơ sở dữ liệu của bạn.

Để hạn chế quyền truy cập dựa trên địa chỉ thực tế được đề cập, bạn sẽ thêm quy tắc như sau:

/etc/iptables/rules.v4
*filter
. . .

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -d 192.0.2.30 -j ACCEPT

. . .

Nếu bạn muốn cho phép ngoại lệ dựa trên giao diện chứa địa chỉ đó, thay vào đó bạn có thể thêm quy tắc tương tự như quy tắc này:

/etc/iptables/rules.v4
*filter
. . .

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -i eth1 -j ACCEPT

. . .

Lưu và đóng tập tin khi bạn hoàn tất.

Kiểm tra lỗi cú pháp bằng lệnh này:

  1. sudo iptables-restore -t < /etc/iptables/rules.v4

Khi bạn đã sẵn sàng, hãy tải lại các quy tắc tường lửa:

  1. sudo service iptables-persistent reload

Cả hai máy chủ của bạn giờ đây sẽ được bảo vệ mà không hạn chế luồng dữ liệu cần thiết giữa chúng.

Kết luận

Việc triển khai tường lửa thích hợp phải luôn là một phần trong kế hoạch triển khai của bạn khi thiết lập ứng dụng. Mặc dù chúng tôi đã trình bày cấu hình này bằng hai máy chủ chạy Nginx và MySQL, nhưng các kỹ thuật được trình bày ở trên vẫn có thể áp dụng được bất kể lựa chọn công nghệ cụ thể của bạn là gì.

Để tìm hiểu thêm về tường lửa và iptables cụ thể, hãy xem các hướng dẫn sau:

  • Cách chọn chính sách tường lửa hiệu quả để bảo mật máy chủ của bạn
  • Đi sâu vào kiến trúc Iptables và Netfilter
  • Cách kiểm tra cấu hình tường lửa của bạn với Nmap và Tcpdump
Chia sẻ

0 câu trả lời