web-dev-qa-db-ja.com

IPv6接続が突然消える

以下に指定されている環境では、IPv4は猫のように喉を鳴らしますが、IPv6はしばらくすると消えます。つまり、ホストでさえ、Dockerネットワークを介してIPv6経由でコンテナに到達できません。私は何か見落としてますか?

編集#1

64:ff9b ::をグローバルなものに置き換えましたが、問題は解決しません。ホストは、直接接続されたDockerコンテナーへのIPv6(IPv4ではない)接続を失います。最初に「ホストへのルートがありません」、次にタイムアウトします。

playbook.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

タスク/ファイアウォール.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

タスク/router.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

files/Firewall/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

files/Firewall/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

files/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;
    }
}

files/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
1
Al Klimov

私の推測では、IPv6ファイアウォールルールが NDP(Neighbor Discovery Protocol) パケットをブロックしているため、ホストがコンテナのリンク層アドレスを適切に解決できません。

IPv4スタックでは、リンク層(イーサネット)アドレスの解決は ARP(アドレス解決プロトコル) によって処理されます。これは、パケットの宛先としてリンク層アドレスを使用して機能します。ホストがARP要求または一方的なARPアドバタイズメントを発行すると、それらのパケットはブロードキャストリンク層アドレス(イーサネットプロトコルではFF:FF:FF:FF:FF:FF)に直接転送されるため、iptablesの対象にはなりません。フィルタリング。

IPv6スタックでは、リンク層アドレスの解決はNDP(近隣探索プロトコル)によって処理されます。 ARPとは異なり、NDPパケットは実際にはIPv6アドレスに転送されるICMPv6パケットであり、その結果、ip6tablesフィルタリングの対象になります。

私の経験によれば、 Arch Linux Wikiの記事 に見られるように、CONNTRACKモジュールはICMPv6 NDPパケットを追跡し、応答パケットを[〜#としてマークするようには設計されていないと思います。 〜]確立された[〜#〜]または[〜#〜]関連[〜#〜]。私の提案は、そのようなトラフィックを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