Инструменты пользователя

Инструменты сайта


linux:docker_network_conflict

Это старая версия документа!


Конфликт сети Docker с корпоративной/VPN-сетью

Симптомы

  • В браузере или curl не открывается внутренний сервис (Jira, LDAP, change-pass, git и т.п.)
  • Ошибка: Connection refused или Failed to connect на портах 80/443
  • DNS резолвится правильно (getent hosts hostname возвращает ожидаемый IP)
  • Проблема появляется после docker compose up или когда на машине много Docker-сетей
  • VPN подключён, но трафик до нужного IP не идёт через tun0/tun1

Суть проблемы

Docker создаёт bridge-интерфейсы (br-xxxxxxxxxxxx) с собственными подсетями, например:

  • 172.17.0.0/16 — default bridge
  • 172.22.0.0/16 — сеть проекта rpcserver_default
  • 172.18.0.0/16status_app-network

Если подсеть Docker пересекается с корпоративной сетью (часто 172.16.0.0/12 или конкретно 172.22.0.0/16 для IEP), Linux направляет пакеты в Docker-bridge, а не в VPN.

Пример: change-pass.iep.loc172.22.224.153. Сеть rpcserver_default заняла 172.22.0.0/16. Маршрут:

172.22.224.153 dev br-355c08cd95dd src 172.22.0.1

Пакеты уходят в пустой Docker-bridge → Connection refused. Реальный сервер в корпсети недоступен.

Это не проблема DNS и не resolv.conf. Имя резолвится верно; ломается маршрутизация на уровне ядра Linux.

Быстрая диагностика

1. Проверить DNS

HOST=change-pass.iep.loc   # подставьте свой хост
getent hosts "$HOST"

Если IP получен — DNS в порядке (или запись в /etc/hosts).

2. Куда уходит маршрут

ip route get $(getent hosts "$HOST" | awk '{print $1; exit}')

Плохо (конфликт с Docker):

172.22.224.153 dev br-xxxxxxxxxxxx src 172.22.0.1

Хорошо (через VPN/корпсеть):

172.22.224.153 via 10.5.192.1 dev tun0 src 10.5.193.211

3. Проверить порты

IP=$(getent hosts "$HOST" | awk '{print $1; exit}')
nc -vz "$IP" 80
nc -vz "$IP" 443
curl -vk --connect-timeout 5 "https://$HOST/"

При конфликте с Docker — Connection refused до VPN, даже если VPN подключён.

4. Найти конфликтующую Docker-сеть

ip route | grep 172.22          # или другая проблемная подсеть
docker network ls
docker network inspect $(docker network ls -q) | grep -E '"Name"|Subnet|Gateway'

Ищите сеть, у которой Subnet совпадает с диапазоном корпоративных адресов.

Пример из практики:

  • Сеть: rpcserver_default
  • Subnet: 172.22.0.0/16
  • Bridge: br-355c08cd95dd
  • Конфликт с: change-pass.iep.loc (172.22.224.153)

Скрипт проверки

Сохраните как check-docker-network-conflict.sh:

check-docker-network-conflict.sh
#!/usr/bin/env bash
set -u
 
HOST="${1:-change-pass.iep.loc}"
 
echo "=== DNS ==="
getent hosts "$HOST" || { echo "DNS fail"; exit 1; }
IP=$(getent hosts "$HOST" | awk '{print $1; exit}')
echo "IP=$IP"
 
echo
echo "=== Route ==="
ip route get "$IP"
 
echo
echo "=== TCP 80/443 ==="
nc -vz "$IP" 80  2>&1 || true
nc -vz "$IP" 443 2>&1 || true
 
echo
echo "=== Docker routes (172.16/12 overlap) ==="
ip route | grep -E '172\.(1[6-9]|2[0-9]|3[0-1])\.' || echo "(none)"
 
echo
echo "=== Docker networks ==="
docker network inspect $(docker network ls -q) 2>/dev/null \
  | grep -E '"Name"|Subnet|Gateway' || echo "docker not available"
chmod +x check-docker-network-conflict.sh
./check-docker-network-conflict.sh change-pass.iep.loc

Решение

Временное (сразу восстановить доступ)

Остановить проект, который создал конфликтующую сеть:

cd ~/projects/rpc.server    # путь к compose-проекту
docker compose down
# или: docker-compose down

Проверить:

ip route get 172.22.224.153
curl -vk https://change-pass.iep.loc/

Маршрут должен идти через tun0 / tun1, не через br-….

Постоянное (при следующем ''docker compose up'')

В docker-compose.yml проекта задайте другую подсеть, не пересекающуюся с корпоративной:

networks:
  default:
    ipam:
      config:
        - subnet: 192.168.220.0/24

Или для named network:

networks:
  app-network:
    ipam:
      config:
        - subnet: 192.168.221.0/24
Выбирайте диапазоны вне 172.16.0.0/12 (172.16–172.31), если VPN/IEP использует 172.22.x, 172.18.x и т.п. Удобные варианты: 192.168.200.0/24, 192.168.220.0/24.

Глобально для всех новых Docker-сетей

/etc/docker/daemon.json:

{
  "default-address-pools": [
    { "base": "192.168.200.0/16", "size": 24 }
  ]
}
sudo systemctl restart docker
После смены пулов пересоздайте существующие compose-проекты (docker compose down && docker compose up -d). Старые сети с 172.22.0.0/16 останутся, пока их не удалите.

Таблица: что проверять

Симптом Вероятная причина Что смотреть
DNS не резолвит resolv.conf, VPN DNS, /etc/hosts getent hosts
DNS OK, route через br-… Конфликт Docker subnet ip route get, docker network inspect
Route через tun0, но timeout VPN без маршрута в сеть ip route, админы VPN
Route OK, Connection refused Сервис не слушает порт nc -vz IP 443 на стороне сервера
TLS verify error Корпоративный CA curl -k vs установка CA в систему

Профилактика

  1. Не использовать 172.16.0.0/12 для Docker, если работаете с IEP/RTLabs VPN
  2. Перед docker compose up нового проекта: docker network inspect … | grep Subnet
  3. При смене машины / VPN — один раз прогнать ip route get <корп-хост>
  4. Документировать subnet каждого локального compose в README проекта

Связанные команды

# все маршруты Docker-bridge
ip route | grep '^172\.'
 
# какой bridge за какой сетью
docker network ls
docker network inspect rpcserver_default
 
# удалить «висячую» сеть (если compose уже down)
docker network rm rpcserver_default

История кейса

Дата: 2026-08-13

Хост: change-pass.iep.loc172.22.224.153

Причина: Docker-сеть rpcserver_default с 172.22.0.0/16 перехватывала маршрут.

Решение: docker compose down в rpc.server + смена subnet в compose на 192.168.220.0/24.

Результат: ip route getvia 10.5.192.1 dev tun0, curl → HTTP 200.

linux/docker_network_conflict.1786607269.txt.gz · Последние изменения: 2026/08/13 07:47 — werwolf