Iptables đặt quy tắc để bộ chứa docker có thể truy cập dịch vụ trên IP máy chủ


18

Tôi gặp sự cố khi truy cập giao diện riêng (ip) từ bộ chứa docker. Tôi khá chắc chắn rằng nó liên quan đến các quy tắc Iptables của tôi (hoặc có thể định tuyến). Khi tôi thêm --net=hostcờ vào docker run, mọi thứ sẽ hoạt động như mong đợi. Tương tự như vậy khi tôi xác định rằng chính sách INPUT đang theo tự do -P INPUT ACCEPT, mọi thứ cũng hoạt động như tôi mong đợi. Tuy nhiên đây là những lựa chọn không mong muốn và không an toàn mà tôi muốn tránh.

Vì nó không dành riêng cho các dịch vụ của tôi (DNS) Tôi đã loại trừ vấn đề đó, vì việc tìm kiếm kết hợp với docker mang lại một khu vực vấn đề (phổ biến) khác, thêm tiếng ồn vào kết quả tìm kiếm.

Ngoài ra, liên kết các container Docker không phải là một tùy chọn khả thi, bởi vì một số container nhất định cần được chạy với tùy chọn --net = host, ngăn chặn liên kết và tôi muốn tạo một tình huống nhất quán khi có thể.

Tôi có các quy tắc Iptables sau đây. Một sự kết hợp giữa CoreOS, Digital Ocean và Docker tôi giả sử.

-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth1 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT

Giao diện máy chủ (có liên quan) của tôi:

3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.129.112.210/16 brd 10.129.255.255 scope global eth1
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever

Và tôi chạy một container docker:

$ docker run --rm -it --dns=10.129.112.210 debian:jessie # Specifying the DNS is so that the public DNS servers aren't used.

Tại thời điểm này, tôi muốn có thể sử dụng một dịch vụ địa phương, ràng buộc vào ngày 10.129.112.210:53. Vì vậy, sau đây sẽ mang lại một trả lời:

$ ping google.com
^C
$ ping user.skydns.local
^C

Khi tôi chạy lệnh tương tự từ máy chủ của mình:

$ ping photo.skydns.localPING photo.skydns.local (10.129.112.206) 56(84) bytes of data.
64 bytes from 10.129.112.206: icmp_seq=1 ttl=64 time=0.790 ms
^C

Nghị quyết của tôi

$ cat /etc/resolv.conf
nameserver 10.129.112.210
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4

Vấn đề ở đây không phải là truy cập các máy chủ công cộng, mà là các máy chủ nội bộ, sử dụng dịch vụ DNS cục bộ có sẵn trên máy chủ (thông qua một ví dụ docker khác).

Để minh họa cho nó hơn nữa (Kỹ năng thiết kế nghệ thuật ascii của tôi vượt qua iptables fu của tôi, vì vậy điều đó sẽ đủ nói vào thời điểm này):

 ______________________________________________
|  __________________________           Host   |
| |   Docker DNS container   |                 |
|  ``````````````````````|```                  |
|                        |                     |
|     ,----------,---( private n. interface )  |
|     |          |                             |
|     |          |   ( public  n. interface )---
|     |          |                             |
|     |          |   ( loopbck n. interface )  |
|     |          |                             |
|     |          |                             |
|     |        __|_______________________      |
|     |       | Docker service container |     |
|     |        ``````````````````````````      |
|     |                                        |
|     |                                        |
| [ Local host service using DNS. ]            |
|                                              |
|______________________________________________|

  private (host) network interface: eth1 (10.129.0.0/16)
  Docker network interface: docker0 (172.17.0.0/16)

Tôi đã tìm kiếm, đọc và áp dụng các cấu hình Iptables khác nhau, nhưng tôi biết quá ít các quy tắc Iptables "nâng cao" hơn để hiểu những gì đang diễn ra và do đó để có được kết quả mong muốn.

Đầu ra của iptables -t nat -nL:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0

Chain DOCKER (2 references)
target     prot opt source               destination

Đầu ra của cat /proc/sys/net/ipv4/ip_forward:

1

Bạn có thể gửi đầu ra của iptables -t nat -nL? Bạn đã thực hiện bất kỳ phân tích gói tin nào chưa, hãy thực hiện ping từ bộ chứa nguồn và sử dụng tcpdump để chụp các gói trên máy chủ.
Daniel t.

Chắc chắn, cảm ơn vì đã giúp đỡ cho đến nay: pastebin.com/TAaT73nk (Không phù hợp với nhận xét ..) - chỉnh sửa -> Đã cập nhật liên kết đến một pastebin không hết hạn.
Dynom

Có thể tôi không hiểu chính xác vấn đề của bạn, nhưng tôi không thấy bất kỳ quy tắc nào để cho phép truy vấn DNS trên máy chủ. Ngoài ra, ip_forward có được kích hoạt không?
Laurentiu Roescu

Xin chào @LaurentiuRoescu. $ cat /proc/sys/net/ipv4/ip_forward -> 1-A INPUT -i eth1 -j ACCEPTchấp nhận tất cả các kết nối trên giao diện riêng . Bạn đang thiếu những quy tắc nào?
Dynom

2
Tôi nghĩ các gói từ container đến từ giao diện docker0, không phải eth1. thử-A INPUT -i docker0 -j ACCEPT
Laurentiu Roescu

Câu trả lời:


14

Container giao tiếp với máy chủ bằng docker0giao diện. Để cho phép lưu lượng truy cập từ container thêm:

-A INPUT -i docker0 -j ACCEPT

2
Dynom, một bài học bạn có thể muốn rút ra từ đây là việc ghi nhật ký tất cả các từ chối của bạn là hữu ích, ví dụ như iptables -A INPUT -j LOG. Con tem IN=docker0sẽ rất hữu ích trong việc tìm ra những quy tắc cần thiết. Không rời xa công việc của Laurentiu, điều tuyệt vời - +1 từ tôi!
MadHatter hỗ trợ Monica

5
Đối với những người sử dụng UFW, đây là những gì tôi đã làm để cho phép tất cả thông tin liên lạc từ các container Docker đến máy chủ: ufw cho phép đăng nhập vào docker0
Ali Ok

0

Tôi đã gặp tình huống rất giống nhau nhưng việc thêm -A INPUT -i docker0 -j ACCEPTsẽ mở tất cả các truy cập trên giao diện eth0 của máy chủ docker vào các container mà hoàn toàn không phải là những gì tôi dự định.

Và vì tôi nhận thấy rằng container của tôi chỉ có quyền truy cập hạn chế (chỉ nói cổng 22) vào giao diện máy chủ thay vì tắt hoàn toàn khỏi mạng máy chủ, tôi đã xem lại các quy tắc iptables của mình và tìm thấy một quy tắc trong chuỗi IN_public_allow chịu trách nhiệm cho việc này. Quy tắc là -A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT. Vì vậy, tôi đã thêm các quy tắc tương tự để cho phép container của tôi truy cập các cổng máy chủ khác mong muốn, mà tôi nghĩ có thể là một cách chính xác hơn một chút để mở truy cập mạng máy chủ vào container.


-i docker0phải đảm bảo rằng điều này sẽ không ảnh hưởng đến lưu lượng không đến qua mạng docker0. Ngữ pháp của bạn không rõ ràng mặc dù. Có lẽ bạn đã nói rằng truy cập đi từ máy chủ docker thông qua eth0 đã được bật, điều này có thể đúng. Tôi đồng ý rằng các quy tắc được nhắm mục tiêu nhiều hơn chỉ có thể mở nhiều như bạn cần.
mc0e
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.