Điểm:5

Sử dụng chuyển tiếp iptables, trong khi vẫn giữ đúng IP nguồn

lá cờ ng

Tôi có một máy chủ đang chạy Wireguard (do đó cần hóa trang) và một container chạy trên cổng 2525.

tôi có những điều sau đây iptables quy tắc:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to-destination 172.18.0.1:2525
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Khi kết nối với máy chủ: 2525 trực tiếp, bộ chứa Docker có thể thấy địa chỉ IP thực của tôi (1.2.3.4). Khi kết nối với cổng máy chủ: 25, bộ chứa Docker đang nhìn thấy IP cục bộ được cung cấp bởi mạng docker:

Ngày 07 tháng 4 12:45:46 mx postfix/smtpd[87]: mất kết nối sau khi CONNECT từ ẩn số[172.18.0.1]
Ngày 07 tháng 4 12:45:46 mx postfix/smtpd[87]: ngắt kết nối khỏi lệnh không xác định[172.18.0.1]=0/0

Làm cách nào để đảm bảo bộ chứa Docker nhìn đúng địa chỉ IP công cộng khi kết nối với cổng 25 (và không chỉ khi kết nối với cổng 2525).

Cảm ơn

# iptables -L -n -v -t nat
Chuỗi PREROUTING (chính sách CHẤP NHẬN 0 gói, 0 byte)
 pkts byte đích prot chọn không tham gia đích nguồn
52300 3131K DNAT tcp -- eth0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:25 đến:172.18.0.1:2525
 150K 8524K DOCKER tất cả -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE khớp với loại dst LOCAL

Chuỗi INPUT (chính sách CHẤP NHẬN 0 gói, 0 byte)
 pkts byte đích prot chọn không tham gia đích nguồn

ĐẦU RA chuỗi (chính sách CHẤP NHẬN 0 gói, 0 byte)
 pkts byte đích prot chọn không tham gia đích nguồn
    2 120 DOCKER tất cả -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE khớp kiểu dst LOCAL

Chuỗi POSTROUTING (chính sách CHẤP NHẬN 0 gói, 0 byte)
 pkts byte đích prot chọn không tham gia đích nguồn
 3385 256K MẶT MẠO tất cả -- * !docker0 172.17.0.0/16 0.0.0.0/0
1733K 104M MẶT MẠO tất cả -- * !br-b147ffdbc9f3 172.18.0.0/16 0.0.0.0/0
    0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:53
    0 0 MASQUERADE udp -- * * 172.17.0.2 172.17.0.2 udp dpt:53
    0 0 MASQUERADE tcp -- * * 172.18.0.2 172.18.0.2 tcp dpt:25

Chuỗi DOCKER (2 tài liệu tham khảo)
 pkts byte đích prot chọn không tham gia đích nguồn
   12 1419 TRẢ LẠI tất cả -- docker0 * 0.0.0.0/0 0.0.0.0/0
    0 0 TRẢ LẠI tất cả -- br-b147ffdbc9f3 * 0.0.0.0/0 0.0.0.0/0
   56 3192 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:5354 tới:172.17.0.2:53
    0 0 DNAT udp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:5354 tới:172.17.0.2:53
  107 6020 DNAT tcp -- !br-b147ffdbc9f3 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:2525 tới:172.18.0.2:25
# địa chỉ ip
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 trạng thái qdisc noqueue nhóm UNKNOWN mặc định qlen 1000
    liên kết/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    máy chủ phạm vi inet 127.0.0.1/8 lo
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
    inet6 ::1/128 máy chủ phạm vi
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast trạng thái UP nhóm mặc định qlen 1000
    liên kết/ether 32:d0:56:15:0a:64 brd ff:ff:ff:ff:ff:ff
    tên thay thế enp0s3
    tên thay thế ens3
    inet 159.223.80.86/20 brd 159.223.95.255 phạm vi toàn cầu eth0
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
    inet 10.15.0.19/16 brd 10.15.255.255 phạm vi toàn cầu eth0:1
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
    inet6 2400:6180:0:d0::f57:6001/64 phạm vi toàn cầu
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
    liên kết phạm vi inet6 fe80::30d0:56ff:fe15:a64/64
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast trạng thái UP nhóm mặc định qlen 1000
    liên kết/ether 32:dc:4a:e4:27:be brd ff:ff:ff:ff:ff:ff
    tên thay thế enp0s4
    tên thay thế ens4
    inet 10.130.244.15/16 brd 10.130.255.255 phạm vi toàn cầu eth1
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
    liên kết phạm vi inet6 fe80::30dc:4aff:fee4:27be/64
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 trạng thái qdisc noqueue nhóm UNKNOWN mặc định qlen 1000
    liên kết/không có
    inet 10.200.200.52/24 phạm vi toàn cầu wg0
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
5: wg1: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 trạng thái qdisc noqueue nhóm UNKNOWN mặc định qlen 1000
    liên kết/không có
    inet 10.222.111.1/24 phạm vi toàn cầu wg1
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
6: br-b147ffdbc9f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 trạng thái qdisc noqueue nhóm LÊN mặc định
    liên kết/ether 02:42:46:21:70:c0 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 phạm vi toàn cầu br-b147ffdbc9f3
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
    liên kết phạm vi inet6 fe80::42:46ff:fe21:70c0/64
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
7: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 trạng thái qdisc noqueue UP nhóm mặc định
    liên kết/ether 02:42:66:22:41:91 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 phạm vi toàn cầu docker0
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
    inet6 fe80::42:66ff:fe22:4191/64 liên kết phạm vi
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
9: veth31eff9d@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 trạng thái Nhóm UP mặc định
    liên kết/ether e6:fb:80:5d:c7:a3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    liên kết phạm vi inet6 fe80::e4fb:80ff:fe5d:c7a3/64
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
19: veth01269f5@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-b147ffdbc9f3 trạng thái UP nhóm mặc định
    liên kết/ether 36:f4:e7:43:5f:da brd ff:ff:ff:ff:ff:ff link-netnsid 2
    liên kết phạm vi inet6 fe80::34f4:e7ff:fe43:5fda/64
       hợp lệ_lft mãi mãi ưa thích_lft mãi mãi
setenforce 1 avatar
lá cờ us
có vẻ như bạn có quy tắc định tuyến sau SNAT khi truy cập giao diện docker mà bạn có thể xóa. Bạn có thể vui lòng thêm kết quả của `iptables -L -n -v -t nat` không?
eKKiM avatar
lá cờ lr
Bạn có thể giải thích thêm về cơ sở hạ tầng/thiết lập mạng của mình, bao gồm cả phần bảo vệ dây không? Tôi không rõ (tại thời điểm này) tại sao việc hóa trang lại cần thiết.
lá cờ ng
@ setenforce1 được thêm vào bài đăng đầu tiên
lá cờ ng
@eKKiM Tôi tin rằng cần phải định tuyến đúng cách (nghĩa là nó hoạt động như một cổng/VPN: máy khách -> máy chủ WG -> internet)
eKKiM avatar
lá cờ lr
Máy chủ WG có phải là cổng mặc định trong mạng của bạn không? Bạn có thể thêm đầu ra của `ifconfig -a` hoặc `ip addr` không?
lá cờ ng
Không, đó là một máy chủ đại dương kỹ thuật số. eth0 có IP công khai. Đã thêm `ip addr` vào bài gốc.
eKKiM avatar
lá cờ lr
Tôi không thấy lý do cho tất cả các quy tắc giả trang POSTROUTING đó. Bạn có thể thay thế nó bằng một `iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE` không
lá cờ ng
Tôi đã xóa một cái, tôi hiện có cái này: ``` ip6tables -A INPUT -i eth0 -m tcp -p tcp --dport 25 -j TỪ CHỐI ip6tables -A INPUT -i eth0 -m tcp -p tcp --dport 2525 -j TỪ CHỐI iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE ```
Điểm:2
lá cờ cl
A.B

Chỉ cần để Docker xử lý chuyển hướng, chuyển hướng động và có thể thay đổi khi vùng chứa được thêm, xóa hoặc khởi động lại. Nhưng hãy xem CẬP NHẬT phía dưới.

Chuyển hướng này không nên đến 172.18.0.1 là máy chủ chứ không phải vùng chứa. Khi máy chủ nhận được kết nối như vậy, nó sẽ được xử lý bởi docker-proxy ủy quyền nó cho vùng chứa, làm mất địa chỉ IP nguồn trong quá trình này.

Docker đã DNAT + định tuyến cổng này một cách chính xác (ngoại trừ từ chính máy chủ, trong đó docker-proxy đóng vai trò này) trong quy tắc cuối cùng của bộ quy tắc, tới vùng chứa đang chạy có địa chỉ 172.18.0.2. Ngoại trừ nó được cấu hình để sử dụng cổng 2525 thay vì cổng 25.

  107 6020 DNAT tcp -- !br-b147ffdbc9f3 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:2525 tới:172.18.0.2:25

Điều này phải được khắc phục bằng cài đặt Docker, không phải thủ công iptables các quy tắc không thể thay đổi bất cứ khi nào bố cục vùng chứa thay đổi. Vì cổng 25 được đặc quyền, nếu Docker đang chạy rootless, cần có các cài đặt bổ sung, hãy kiểm tra tài liệu về việc hiển thị các cổng đặc quyền.


CẬP NHẬT (bao thanh toán trong nhận xét của OP): OP hiện không thể sử dụng -p 25:25 bởi vì docker-proxy xung đột với máy chủ SMTP của máy chủ cục bộ và cạnh tranh để nghe trên cổng 25 trên máy chủ. Đó là lý do ban đầu (sai) iptables chuyển hướng đã được thực hiện bởi OP.

Người ta có thể:

  • vô hiệu hóa trên toàn cầu docker-proxy bằng cách chạy dockerd với tài sản userland-proxy đặt thành sai

    hoặc như một tham số --userland-proxy=false hoặc như một tài sản "userland-proxy": sai thêm vào /etc/docker/daemon.json.

    Điều này sau đó sẽ cho phép sử dụng docker chạy ... -p 25:25 ... (như tài liệu) mà không có xung đột: máy chủ sẽ tự truy cập khi truy cập localhost hoặc $HOSTNAME, các hệ thống từ xa sẽ truy cập bộ chứa và không có "Địa chỉ đã được sử dụng" sẽ khiến trình nền SMTP của máy chủ lưu trữ hoặc bộ chứa Docker bị lỗi khi khởi động.

  • hoặc nếu không, hãy thêm chuyển hướng thủ công (với thiết lập dài bên dưới để thực hiện điều đó gần như tự động)

    Bất cứ khi nào vùng chứa được khởi động lại, sẽ có rủi ro là địa chỉ IP (nội bộ) của vùng chứa đó sẽ thay đổi. Vì vậy, điều này phải được tính toán. Vì vậy, với một container có tên mx sử dụng mạng có tên mx và một địa chỉ IP duy nhất liên quan đến việc này có thể được thực hiện như được giải thích bên dưới.

    Tạo một chuỗi tiền định tuyến riêng biệt (để nó có thể được xóa mà không cần phải xóa bất kỳ thứ gì khác) và gọi nó trước:

    iptables -t nat -N mynat
    iptables -t nat -I PREROUTING -j mynat
    

    Địa chỉ IP của vùng chứa có thể được truy xuất theo chương trình (đối với trường hợp đơn giản của vùng chứa có tên mx với một địa chỉ duy nhất):

    containerip=$(docker containerkiểm tra --format '{{.NetworkSettings.IPAddress}}' mx)
    

    (hoặc người ta có thể sử dụng jq: containerip=$(docker container kiểm tra mx | jq '.[].NetworkSettings.IPAddress')

    Việc tìm tên giao diện cầu phức tạp hơn hoặc ít nhất là tôi không thể tìm ra cách cho nó chỉ bằng cách sử dụng docker ... kiểm tra. Vì vậy, hãy tìm địa chỉ IP của nó trên máy chủ và truy vấn máy chủ bằng cách sử dụng địa chỉ IP để chỉ tìm giao diện cầu nơi đặt địa chỉ IP cụ thể này (yêu cầu jq chỉ huy.)

     bridgeip=$(docker kiểm tra mạng --format '{{(index .IPAM.Config 0).Gateway}}' mx)
     bridgeinterface=$(địa chỉ ip -json hiển thị cho "$bridgeip"/32 | jq -r '.[].ifname')
    

    tuôn ra và phục hồi mynat mỗi lần container được (khởi động lại):

    iptables -t nat -F mynat
    iptables -t nat -A mynat ! -i "$bridgeinterface" -p tcp --dport 25 -j DNAT --to-destination "$containerip":25
    

    đó sẽ là cho trường hợp hiện tại:

    iptables -t nat -I mynat ! -i br-b147ffdbc9f3 -p tcp --dport 25 -j DNAT --to-destination 172.18.0.2:25

    Và để đảm bảo các quy tắc tường lửa của Docker không chặn lưu lượng truy cập như vậy, hãy làm điều gì đó tương tự bắt đầu trong bộ lọc/PHÍA TRƯỚC từ DOCKER-NGƯỜI DÙNG chuỗi.

    Ban đầu (nếu từ khi khởi động, bạn cũng có thể phải tạo trước DOCKER-NGƯỜI DÙNG):

    iptables -N myforward
    iptables -I DOCKER-USER 1 -j myforward
    

    Sau đó, sau mỗi lần container được (khởi động lại):

    iptables -F myforward
    iptables -A myforward -p tcp! -i "$bridgeinterface" -d "$containerip" -p tcp --dport 25 -j CHẤP NHẬN
    

    đó sẽ là cho trường hợp hiện tại:

    iptables -A myforward -p tcp ! -i br-b147ffdbc9f3 -d 172.18.0.2 -p tcp --dport 25 -j CHẤP NHẬN
    

Ghi chú:

  • Để đơn giản hóa các quy tắc ở trên và tránh một số tính toán, vùng chứa và mạng cầu nối của nó có thể được bắt đầu bằng các địa chỉ IP cố định.Xem ví dụ SO Q/A này: Gán IP tĩnh cho bộ chứa Docker.

  • Đây cũng là một Q/A UL SE với câu trả lời của tôi về các vấn đề khi tương tác với Docker (nó hướng đến nftables nhưng một số phần về DOCKER-NGƯỜI DÙNG chuỗi hoặc br_netfilter tương tác cầu nối vẫn được quan tâm): docker danh sách trắng nftables

lá cờ ng
Cảm ơn. Điều này đang sử dụng `docker run`: `docker run -d -P --network mx -p 2525:25 -v /srv/mx/:/mx/ --restart always --name mx mx`
lá cờ ng
Tôi đang chạy trên cổng 2525 vì nếu tôi không chạy hậu tố trên máy chủ cục bộ, lệnh `mail` sẽ không hoạt động và email không được gửi. https://Pastebin.com/RR2mDx9T (khi chạy container trên cổng 25)
eKKiM avatar
lá cờ lr
afaik docker userland proxy sẽ ủy quyền kết nối theo nghĩa đen, do đó ip nguồn sẽ bị thay đổi..
A.B avatar
lá cờ cl
A.B
@eKKiM thực sự, đó là những gì tôi trình bày tại `docker-proxy`.
A.B avatar
lá cờ cl
A.B
@Tuinslak vì vậy với bối cảnh này (không thể sử dụng cổng 25), quy tắc Docker đã có sẵn (quy tắc cuối cùng được thấy trong bộ quy tắc được hiển thị trong câu hỏi được đặt bởi `-p 2525:25`) đã xử lý nó. Tại sao bạn lại thêm một quy tắc ghi đè lên nó?
eKKiM avatar
lá cờ lr
@ A.B cụm từ "Chỉ cần để Docker xử lý chuyển hướng" hãy để tôi giả sử để nó được xử lý bởi docker-proxy
A.B avatar
lá cờ cl
A.B
@eKKiM docker-proxy chỉ liên quan đến trường hợp máy chủ: 172.18.0.1. Nó không liên quan khi định tuyến đến vùng chứa 172.18.0.2. Nhưng quy tắc iptables mà OP đã thêm làm cho luồng buộc phải docker-proxy thay vì được định tuyến.
lá cờ ng
Nếu tôi không chạy `iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE`, máy chủ sẽ không chuyển tiếp các gói và tôi không thể sử dụng nó làm VPN/ping bất kỳ máy chủ nào bên ngoài máy chủ - https:// pastebin.com/uY0Rka6Z
lá cờ ng
Có vẻ như `iptables -t nat -I PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to-destination 172.18.0.2:25` hoạt động. Vì vậy, tôi không thể sử dụng docker-proxy (`172.18.0.1`) mà cần sử dụng IP thực của vùng chứa?
A.B avatar
lá cờ cl
A.B
Liên kết của tôi về `docker-proxy` cho biết nó có thể bị vô hiệu hóa trên toàn cầu với `--userland-proxy=false`. Hoặc `"userland-proxy": false` trong [`/etc/docker/daemon.json`](https://docs.docker.com/engine/reference/commandline/dockerd/) . Nếu bạn không cần tiếp cận các vùng chứa của mình (tất cả chúng không chỉ vùng chứa này: nó là toàn cầu) bằng cách sử dụng chính máy chủ lưu trữ, thì bạn có thể chỉ cần sử dụng `-p 25:25`.Đây chỉ là sự cố khi có liên quan đến kẹp tóc NAT, vì vậy khi một vùng chứa cần tiếp cận một vùng chứa khác bằng cách sử dụng địa chỉ IP của máy chủ công khai (địa chỉ của eth0).
A.B avatar
lá cờ cl
A.B
Bạn có thể sử dụng `172.18.0.2:25` mà không gặp vấn đề gì nhưng xin lưu ý rằng địa chỉ này không cố định, địa chỉ này có thể thay đổi khi bạn chạy các vùng chứa khác tùy thuộc vào cấu hình.
A.B avatar
lá cờ cl
A.B
Tôi đã sửa đổi câu trả lời của mình để giải quyết thông tin trong nhận xét và thực hiện một số thao tác tự động hóa.

Đă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.