Linux
IPv6 連接突然消失
在下面指定的環境中,IPv4 像貓一樣發出咕嚕聲,但 IPv6 會在短時間內消失——即即使主機也無法通過 Docker 網路通過 IPv6 訪問其容器。我錯過了什麼?
編輯#1
替換 64:ff9b:: w/ 全域,但問題仍然存在。主機失去了與直接連接的 Docker 容器的 IPv6(但不是 IPv4)連接。首先“沒有到主機的路由”,然後超時。
劇本.yml
--- - hosts: all become: yes become_method: sudo tasks: - import_tasks: tasks/firewall.yml - import_tasks: tasks/router.yml - import_tasks: tasks/docker.yml - name: /usr/local/docker-services file: path: /usr/local/docker-services owner: root group: root mode: '0700' state: directory - name: nginx-site.conf copy: dest: /usr/local/docker-services/nginx-site.conf owner: root group: root mode: '0666' src: files/nginx-site.conf - name: docker-compose.yml copy: dest: /usr/local/docker-services/docker-compose.yml owner: root group: root mode: '0666' content: | version: '2.4' networks: ext-nginx: internal: true enable_ipv6: true driver_opts: com.docker.network.bridge.name: docker1 ipam: config: - subnet: 192.168.234.0/30 gateway: 192.168.234.1 - subnet: 64:ff9b::192.168.234.0/126 gateway: 64:ff9b::192.168.234.1 services: nginx: container_name: nginx image: nginx restart: always logging: options: labels: container labels: container: nginx networks: ext-nginx: ipv4_address: 192.168.234.2 ipv6_address: 64:ff9b::192.168.234.2 priority: 1 volumes: - type: bind source: /usr/local/docker-services/nginx-site.conf target: /etc/nginx/conf.d/default.conf read_only: true register: docker_compose_yml - name: docker-compose.service copy: dest: /etc/systemd/system/docker-compose.service owner: root group: root mode: '0644' src: files/docker-compose.service register: docker_compose_service - name: systemctl daemon-reload when: docker_compose_service.changed systemd: daemon_reload: yes - name: systemctl stop docker-compose.service when: >- docker_compose_service.changed or docker_compose_yml.changed service: name: docker-compose state: stopped - name: systemctl start docker-compose.service service: name: docker-compose state: started enabled: yes
任務/firewall.yml
--- - name: Firewall rules applicator apt: name: iptables-persistent - name: Firewall rules file loop: [4, 6] copy: dest: '/etc/iptables/rules.v{{ item }}' owner: root group: root mode: '0644' src: 'files/firewall/rules.v{{ item }}' register: firewall_file - name: Apply firewall rules when: 'firewall_file.results[0].changed or firewall_file.results[1].changed' service: name: netfilter-persistent state: restarted
任務/路由器.yml
--- - name: net.ipv4.ip_forward sysctl: name: net.ipv4.ip_forward value: '1' - name: net.ipv6.conf.all.forwarding sysctl: name: net.ipv6.conf.all.forwarding value: '1'
任務/docker.yml
--- - name: apt-transport-https apt: name: apt-transport-https - name: Docker apt key apt_key: url: https://download.docker.com/linux/debian/gpg - name: Docker apt repo apt_repository: filename: docker repo: > deb https://download.docker.com/linux/debian {{ ansible_lsb.codename }} stable - name: /etc/docker file: path: /etc/docker owner: root group: root mode: '0755' state: directory - name: /etc/docker/daemon.json copy: dest: /etc/docker/daemon.json owner: root group: root mode: '0644' content: '{"iptables":false}' - name: Docker apt: name: docker-ce - name: Docker compose apt: name: docker-compose
文件/防火牆/rules.v4
*filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -d 127.0.0.0/8 ! -i lo -j DROP -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT -A FORWARD -o docker1 -d 192.168.234.2/32 -p tcp -m tcp --dport 80 -j ACCEPT -A FORWARD -i docker1 -o eth0 -j ACCEPT -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT COMMIT *nat :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] -A PREROUTING -i eth0 -d 78.47.124.58 -p tcp -m tcp --dport 80 -j DNAT --to 192.168.234.2 -A POSTROUTING -o eth0 ! -s 78.47.124.58 -j MASQUERADE COMMIT
文件/防火牆/rules.v6
*filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -d ::1/128 ! -i lo -j DROP -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT -A FORWARD -o docker1 -d 64:ff9b::192.168.234.2 -p tcp -m tcp --dport 80 -j ACCEPT -A FORWARD -i docker1 -o eth0 -j ACCEPT -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT COMMIT *nat :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] -A PREROUTING -i eth0 -d 2a01:4f8:c0c:3bc1::/64 -p tcp -m tcp --dport 80 -j DNAT --to 64:ff9b::192.168.234.2 -A POSTROUTING -o eth0 ! -s 2a01:4f8:c0c:3bc1::/64 -j MASQUERADE COMMIT
文件/nginx-site.conf
server { listen 80; listen [::]:80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } }
文件/docker-compose.service
[Unit] Requires=docker.service [Service] Type=oneshot RemainAfterExit=yes WorkingDirectory=/usr/local/docker-services ExecStart=/usr/bin/docker-compose up -d --force-recreate ExecStop=/usr/bin/docker-compose down [Install] WantedBy=multi-user.target
我的猜測是您的 IPv6 防火牆規則正在阻止NDP(鄰居發現協議)數據包,從而阻止您的主機正確解析容器的鏈路層地址。
在 IPv4 堆棧中,鏈路層(乙太網)地址的解析由ARP(地址解析協議)處理,該協議使用鏈路層地址作為數據包目的地。當主機發出 ARP 請求或未經請求的 ARP 通告時,這些數據包被直接轉發到廣播鏈路層地址(
FF:FF:FF:FF:FF:FF
在乙太網協議中),因此不受iptables
過濾。在 IPv6 堆棧中,鏈路層地址的解析由 NDP(鄰居發現協議)處理。與 ARP 不同,NDP 數據包實際上是轉發到 IPv6 地址的 ICMPv6 數據包,因此會受到
ip6tables
過濾。我相信,根據我的經驗以及Arch Linux Wiki 文章中所見,CONNTRACK 模組並非旨在跟踪 ICMPv6 NDP 數據包並將回複數據包標記為ESTABLISHED或RELATED。我的建議是在
files/firewall/rules.v6
文件中明確允許此類流量:(新規則)
-A INPUT -i docker1 -p ipv6-icmp -m icmp6 --icmpv6-type 133 -m comment --comment router-solicitation -j ACCEPT -A INPUT -i eth0 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -m comment --comment router-advertisement -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 135 -m comment --comment neighbor-solicitation -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 136 -m comment --comment neighbor-advertisement -j ACCEPT
(完整檔案)
*filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -d ::1/128 ! -i lo -j DROP -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT -A INPUT -i docker1 -p ipv6-icmp -m icmp6 --icmpv6-type 133 -m comment --comment router-solicitation -j ACCEPT -A INPUT -i eth0 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -m comment --comment router-advertisement -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 135 -m comment --comment neighbor-solicitation -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 136 -m comment --comment neighbor-advertisement -j ACCEPT -A FORWARD -o docker1 -d 64:ff9b::192.168.234.2 -p tcp -m tcp --dport 80 -j ACCEPT -A FORWARD -i docker1 -o eth0 -j ACCEPT -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT COMMIT *nat :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] -A PREROUTING -i eth0 -d 2a01:4f8:c0c:3bc1::/64 -p tcp -m tcp --dport 80 -j DNAT --to 64:ff9b::192.168.234.2 -A POSTROUTING -o eth0 ! -s 2a01:4f8:c0c:3bc1::/64 -j MASQUERADE COMMIT