Điểm:0

Iptables và docker - vô hiệu hóa quyền truy cập từ xa vào vùng chứa trong khi vẫn giữ lại giao tiếp giữa máy chủ và vùng chứa qua proxy

lá cờ us

gần đây, tôi đã bắt đầu di chuyển một máy chủ web có một số ứng dụng sang máy chủ mới và đóng gói mọi ứng dụng app trong vùng chứa docker. Thiết lập hiện tại của tôi bao gồm nginx cho máy chủ cơ sở dữ liệu và proxy ngược chạy trên chính máy chủ và tất cả các ứng dụng web chạy trong bộ chứa docker của riêng chúng.

Tôi hiện đang cố gắng bảo mật máy chủ web bằng iptables, giống như cách tôi đã làm nhiều năm trước. Tôi cần thỏa mãn các điều kiện sau:

  1. tường lửa thông thường cho các dịch vụ không phải docker vẫn hoạt động (các chính sách mặc định sẽ bị loại bỏ cho cả đầu vào và đầu ra, chỉ có thể truy cập các cổng được đặt tên rõ ràng)
  2. các vùng chứa (với một ngoại lệ - xem bên dưới) không được truy cập từ thế giới
  3. vùng chứa phải có thể truy cập máy chủ bằng cách sử dụng "docker.host.internal" để truy cập máy chủ cơ sở dữ liệu
  4. vùng chứa phải có thể truy cập các dịch vụ của vùng chứa khác bằng tên miền công khai (được ủy quyền) của họ
  5. một container phải có 22 cổng có thể truy cập trực tiếp từ thế giới (git)

Cho đến nay, tôi chỉ có thể đáp ứng ba yêu cầu đầu tiên. Thiết lập iptables đơn giản của tôi, mà tôi đã áp dụng từ môi trường không docker trước đó, trông giống như thế này:

# chính sách mặc định bị loại bỏ

-P ĐẦU VÀO THẢ
-P VỀ PHÍA TRƯỚC DROP
-P ĐẦU RA THẢ

# cho phép duyệt internet, NTP, DNS
-A ĐẦU RA -p tcp -m tcp --dport 80 -j CHẤP NHẬN
-A ĐẦU RA -p tcp -m tcp --dport 443 -j CHẤP NHẬN
-A INPUT -p tcp -m tcp --sport 80 -m state --state LIÊN QUAN, THÀNH LẬP -j CHẤP NHẬN
-A INPUT -p tcp -m tcp --sport 443 -m state --state LIÊN QUAN, THÀNH LẬP -j CHẤP NHẬN
-A INPUT -p udp -m udp --sport 53 -j CHẤP NHẬN
-A INPUT -p tcp -m tcp --sport 53 -j CHẤP NHẬN
-A ĐẦU RA -p udp -m udp --dport 53 -j CHẤP NHẬN
-A ĐẦU RA -p tcp -m tcp --dport 53 -j CHẤP NHẬN
-A INPUT -p udp -m udp --dport 123 -j CHẤP NHẬN
-A ĐẦU RA -p udp -m udp --sport 123 -j CHẤP NHẬN

# cho phép dịch vụ - máy chủ web, máy chủ SSH trên cổng 16 (tôi biết nó không chuẩn, nhưng tôi đã quen với điều đó) và SSH trên cổng 22 để truy cập git
-A INPUT -p tcp -m tcp --dport 22 -j CHẤP NHẬN
-A INPUT -p tcp -m tcp --dport 16 -j CHẤP NHẬN
-A INPUT -p tcp -m tcp --dport 80 -j CHẤP NHẬN
-A INPUT -p tcp -m tcp --dport 443 -j CHẤP NHẬN
-A OUTPUT -p tcp -m tcp --sport 22 -m state --state LIÊN QUAN, THÀNH LẬP -j CHẤP NHẬN
-A OUTPUT -p tcp -m tcp --sport 16 -m state --state LIÊN QUAN, THÀNH LẬP -j CHẤP NHẬN
-A OUTPUT -p tcp -m tcp --sport 80 -m state --state LIÊN QUAN, THÀNH LẬP -j CHẤP NHẬN
-A OUTPUT -p tcp -m tcp --sport 443 -m state --state LIÊN QUAN, THÀNH LẬP -j CHẤP NHẬN

# cho phép tất cả giao tiếp cục bộ
-A INPUT -i lo -j CHẤP NHẬN
-A ĐẦU RA -o lo -j CHẤP NHẬN

# cho phép ping
-A VỀ PHÍA TRƯỚC -p icmp -j CHẤP NHẬN
-A INPUT -p icmp -j CHẤP NHẬN
-A ĐẦU RA -p icmp -j CHẤP NHẬN

Tôi không khẳng định đây là cách tốt nhất để làm mọi việc, nhưng nó phải khá an toàn và đã hoạt động với tôi trong nhiều năm.

Bây giờ đến những thứ tôi không hiểu rõ. Nếu tôi áp dụng điều này cho cấu hình docker mới của mình, nó sẽ ngắt quyền truy cập vào máy chủ bằng bí danh "docker.host.internal". Để cho phép điều đó, tôi đã sử dụng:

iptables -A INPUT -i br-+ -j CHẤP NHẬN
iptables -A OUTPUT -o br-+ -j CHẤP NHẬN

Tôi đã từng thấy -tôi docker0 đang được sử dụng, nhưng nó không hiệu quả với tôi, bởi vì mỗi bộ chứa docker đều có bộ chứa riêng anh-* giao diện trên thiết lập của tôi mà nó sử dụng để truy cập Máy chủ. Điều này đã làm việc, càng xa càng tốt.

Bây giờ tôi nhận thấy rằng tất cả các cổng docker đã xuất bản (tôi sử dụng 80XX cho các dịch vụ web và hơn các tên miền chính xác của proxy cho các cổng đó thông qua proxy nginx) đều có thể nhìn thấy trên thế giới. Tôi chắc chắn không muốn điều đó, vì vậy sau khi tìm kiếm, tôi đã thêm điều này:

iptables -I DOCKER-USER -i venet0 -j DROP

(venet0 là tên của giao diện mạng của tôi, thay vì eth0)

Điều này hoạt động tốt, nhưng đã phá vỡ điều kiện 4 và 5 - các vùng chứa không còn có thể truy cập lẫn nhau trên địa chỉ miền công cộng của chúng và tôi không thể kết nối với máy chủ git qua cổng 22 (mà tôi mong đợi).

Bằng cách giao tiếp trên địa chỉ phạm vi công cộng, ý tôi là như sau:

Tôi có một máy chủ CI máy bay không người lái đang chạy trong một vùng chứa, để lộ cổng 8001 đến chủ nhà. Tôi hơn là có một proxy nginx chuyển địa chỉ https://ci.example.com đến cảng này. Điều này cũng đúng với bộ chứa Gitea của tôi, để lộ cổng 8002 và có sẵn trên https://git.example.com.

Drone cần xác thực qua OAuth với máy chủ Gitea. Để làm điều đó, nó phải có khả năng truy cập nó thông qua https://git.example.com:443 địa chỉ, không phải docker nội bộ http://gitea_container_name:8002. Tôi có một số trường hợp sử dụng khác mà điều này cần có thể thực hiện được, nhưng trường hợp này giải thích điều đó tốt nhất.

Bây giờ tôi đã dành nhiều giờ để cố gắng làm cho nó hoạt động, nhưng không thành công - nếu tôi quản lý để nó hoạt động, các điều kiện khác sẽ bị hỏng và ngược lại. Một số thứ tôi đã thử (hầu hết đến từ nhiều câu hỏi khác ở đây):

# đã cố kích hoạt cổng cụ thể cho bộ chứa gitea, không có tác dụng
iptables -I DOCKER-USER -i venet0 -p tcp --sport 8002 -j CHẤP NHẬN

# đã thử đề xuất này, không có tác dụng
iptables -I DOCKER-USER -i venet0 -p tcp -m conntrack --ctorigdstport 443 --ctdir ORIGINAL -j CHẤP NHẬN

# không có hiệu lực, nhưng tôi nghi ngờ điều này sẽ không hoạt động vì tôi không nghĩ 443 là nguyên nhân của chuỗi này
iptables -I DOCKER-USER -i venet0 -p tcp --dport 443 -j CHẤP NHẬN

# không có hiệu lực
iptables -A INPUT -i docker0 -j CHẤP NHẬN

Thiết lập như thế này có được không? Ai đó thành thạo hơn trong thế giới docker và tường lửa có thể chỉ cho tôi đi đúng hướng không?

thiết lập của tôi:

  • Debian 11
  • iptables v1.8.7 (nf_tables)
  • Docker 20.10.5

Cảm ơn rất nhiều trước!

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.