
В среде, указанной ниже, IPv4 мурлычет как кот, но IPv6 исчезает через короткое время – т.е. даже хост не может связаться со своим контейнером через IPv6 через сеть Docker. Я что-то пропустил?
Редактировать №1
Заменил 64:ff9b:: на что-то глобальное, но проблема осталась. Хост теряет подключение по IPv6 (но не по IPv4) к напрямую подключенному контейнеру Docker. Сначала "Нет маршрута к хосту", затем тайм-аут.
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
задачи/маршрутизатор.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
файлы/брандмауэр/правила.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
файлы/брандмауэр/правила.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
решение1
Я предполагаю, что ваши правила брандмауэра IPv6 блокируютNDP (протокол обнаружения соседей)пакетов, что не позволяет вашему хосту правильно определить адрес канального уровня контейнера.
В стеке IPv4 разрешение адресов канального уровня (Ethernet) обрабатываетсяARP (протокол разрешения адресов), который работает, используя адреса уровня связи в качестве назначения пакетов. Когда хост отправляет запросы ARP или незапрошенные объявления ARP, эти пакеты пересылаются напрямую на широковещательный адрес уровня связи (который находится FF:FF:FF:FF:FF:FF
в протоколе Ethernet) и, по этой причине, не подвергаются iptables
фильтрации.
В стеке IPv6 разрешение адресов канального уровня осуществляется протоколом NDP (Neighbor Discovery Protocol). В отличие от ARP, пакеты NDP на самом деле являются пакетами ICMPv6, пересылаемыми на адреса IPv6 и, как следствие, подлежащими ip6tables
фильтрации.
Я считаю, что, исходя из моего опыта и из того, что я видел вСтатья в Вики Arch Linux, модуль 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