Между двумя своими серверами связи нет, а интернет у обоих есть: порядок диагностики
Оба сервера отвечают на пинг снаружи, SSH открывается без задержек, apt update спокойно тянет пакеты — с интернетом всё в порядке на каждом по отдельности. А друг с другом они не разговаривают: приложение на одном не может достучаться до базы или API на другом, хотя IP и порт вроде бы правильные. Обманчивость этой проблемы в том, что рабочий интернет с обеих сторон создаёт ложное чувство, что сеть в целом настроена нормально, и заставляет искать причину не там. На деле между «сервер А видит интернет» и «сервер А видит сервер Б» лежит минимум шесть независимых слоёв, и то, что один из них работает, ничего не говорит об остальных. Разберём порядок проверки — от простого к редкому, без гадания и правки конфигов наугад.
Содержание
- 1. Убедитесь, что оба сервера действительно живы
- 2. Файрвол на каждой стороне отдельно — а не один раз «в целом»
- 3. Сервис на принимающей стороне слушает нужный порт и нужный интерфейс
- 4. Если ожидается приватная сеть, VLAN или VPN — она реально поднята с обеих сторон?
- 5. Маршрутизация в целом: может ли пакет физически дойти
- 6. Облачные security groups и ACL — отдельный уровень, до файрвола ОС
- Общий принцип: не гадать, а идти со стороны отправителя, потом со стороны получателя
1. Убедитесь, что оба сервера действительно живы
Первый шаг — не про сеть между серверами, а про то, живы ли они вообще как хосты и как запущенные сервисы.
Проверяйте доступность сервера Б с третьей точки — со своего ноутбука, с мониторинга, с любого адреса, который не является сервером А. Если проверять доступность Б, находясь на А, вы тестируете ровно ту связь, которая, предположительно, и сломана, — и не узнаете, жив ли Б в принципе, если результат отрицательный.
# с третьей машины, не с одного из двух проверяемых серверов
ping -c 4 <публичный-ip-сервера-А>
ping -c 4 <публичный-ip-сервера-Б>
Если оба отвечают — переходите к следующей проверке: живой хост ещё не значит, что нужный сервис на нём поднят и работает. «Интернет у сервера есть» чаще всего означает лишь то, что исходящий curl или apt update отрабатывают, — это ничего не говорит о состоянии конкретной службы, к которой вы пытаетесь подключиться со второго сервера.
# на самом сервере — жива ли служба, которая должна принимать соединение
sudo systemctl status postgresql
sudo journalctl -u postgresql -n 50 --no-pager
Частый сценарий: ОС отвечает на пинг и SSH работает нормально, а нужный процесс упал после ошибки конфигурации или нехватки памяти и не перезапустился. Внешне сервер выглядит живым, а сервиса, до которого пытается достучаться второй сервер, физически не существует. Эта проверка отсекает случаи, когда причина вообще не в сети.
2. Файрвол на каждой стороне отдельно — а не один раз «в целом»
Файрвол — самая частая причина пропавшей связности между двумя своими серверами, и здесь важна методика: проверять нужно обе стороны по отдельности, а не полагаться на память о том, что «вроде настраивали одинаково». Правила могут блокировать входящие соединения на принимающей стороне, исходящие — на отправляющей, или и то и другое сразу, и это разные причины с разным местом исправления.
# Ubuntu/Debian с UFW
sudo ufw status verbose
# RHEL/CentOS/Rocky/AlmaLinux с firewalld
sudo firewall-cmd --list-all
# сырые правила iptables — если ufw/firewalld не используются
sudo iptables -L -n -v --line-numbers
# nftables
sudo nft list ruleset
Проверяйте не только цепочку INPUT на принимающей стороне, но и OUTPUT на отправляющей — реже встречается, но политика OUTPUT DROP с явными разрешениями только под определённые сервисы иногда блокирует именно то соединение, которое вы пытаетесь поднять, а остальной трафик идёт по уже прописанным правилам и создаёт впечатление, что с исходящим трафиком всё в порядке.
Практическая проверка с отправляющей стороны — просто попробовать подключиться к нужному порту:
# с сервера-отправителя к порту на сервере-получателе
nc -zv 10.10.0.2 5432
# без nc — тот же тест средствами bash
timeout 3 bash -c "</dev/tcp/10.10.0.2/5432" && echo "порт открыт" || echo "нет ответа"
Здесь важен не только факт успеха или неудачи, а характер отказа — он подсказывает, на каком слое искать дальше:
Connection refusedсразу — пакет дошёл до хоста-получателя, но на порту никто не слушает, либо стоит явноеREJECT-правило. Это уже не про маршрутизацию, а про порт 3 или файрвол с REJECT вместо DROP.- Таймаут без ответа — пакет либо отбрасывается файрволом (
DROP, без ответа отправителю), либо вообще не доходит до получателя ни на каком промежуточном участке. Это неотличимо от разрыва маршрутизации на уровне одногоnc, и требует следующих шагов — traceroute и проверки cloud-уровня.
Эта разница между «refused» и «таймаут» экономит массу времени: она сразу отсекает половину гипотез.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать сервер3. Сервис на принимающей стороне слушает нужный порт и нужный интерфейс
Даже если файрвол на обеих сторонах пропускает трафик, а порт правилами не закрыт, соединение не установится, если сама служба слушает только 127.0.0.1 — локальный loopback-интерфейс, недоступный никому, кроме процессов на этом же хосте. Это не файрвол и не маршрутизация, а конфигурация самого сервиса, и путают её с сетевой проблемой чаще всего.
ss -tlnp | grep 5432
Три возможных результата и что они означают:
Вывод ss | Что значит |
|---|---|
LISTEN 0 244 127.0.0.1:5432 | Сервис слушает только локальный интерфейс — снаружи хоста порт не виден никому и никогда, даже если файрвол полностью открыт |
LISTEN 0 244 10.10.0.1:5432 | Сервис слушает конкретный (в данном случае приватный) адрес — доступен только через этот интерфейс |
LISTEN 0 244 0.0.0.0:5432 | Сервис слушает все интерфейсы сразу — доступен и через приватный адрес, и через публичный, если это не остановлено файрволом |
Если второй сервер подключается к приватному IP (10.10.0.1), а служба слушает только 127.0.0.1 — соединение не установится никогда, вне зависимости от состояния файрвола и маршрутизации, и правка bind/listen_addresses в конфиге службы — единственное исправление. Если ожидается доступ именно по приватной сети между своими серверами, а не по публичному адресу, стоит свериться со схемой из статьи про приватную сеть между своими серверами — там разобраны типичные ошибки биндинга применительно именно к внутреннему трафику между двумя вашими хостами.
4. Если ожидается приватная сеть, VLAN или VPN — она реально поднята с обеих сторон?
Если серверы должны видеть друг друга через приватную сеть провайдера, VLAN или VPN-туннель (чаще всего WireGuard), а не через публичные адреса, — стоит проверить не то, что туннель когда-то был настроен, а что он сейчас поднят и работает в обе стороны.
# состояние WireGuard: есть ли peer, был ли недавний handshake
sudo wg show
# интерфейс существует и в состоянии UP
ip link show wg0
# адрес на интерфейсе назначен верно
ip addr show wg0
Строка latest handshake в выводе wg show, которой нет вообще или которая застряла на времени много часов назад, — верный признак, что туннель не поднимается или обрывается сразу после установки. Пустая строка latest handshake: (none) при этом означает, что данные вообще не проходили ни в одну сторону.
Отдельная и коварная ситуация — туннель формально «работает» (handshake свежий), но данные не идут: чаще всего это неверно прописанные AllowedIPs на одной из сторон, из-за чего пакеты в нужную подсеть просто не заворачиваются в интерфейс wg0, хотя криптографическое рукопожатие прошло успешно. Проверьте маршруты на обеих машинах, а не только на одной:
ip route show
ip route get 10.10.0.2
Маршрут может существовать на сервере А (пакеты к Б уходят через wg0) и отсутствовать на сервере Б в обратную сторону — тогда А формально «видит» Б на уровне отправки, но ответы возвращаться не будут, и итог для приложения тот же самый: связи нет. Подробный разбор причин, по которым туннель WireGuard не поднимается или не пропускает трафик при, казалось бы, верном конфиге, — в статье про WireGuard, который не поднимает туннель.
Если приватная сеть — не VPN, а VLAN или внутренний интерфейс от провайдера, проверьте на панели хостинга, что второй сервер вообще подключён к тому же сегменту, а не просто получил похожий по виду приватный адрес из другого, изолированного VLAN — визуально 10.x.x.x ничем не отличается от такого же адреса в соседнем, недоступном сегменте.
5. Маршрутизация в целом: может ли пакет физически дойти
Если файрвол пропускает, сервис слушает нужный адрес, а туннель (если он есть) поднят — следующий шаг - проверить сам маршрут между серверами, причём в обе стороны отдельно, потому что маршрутизация между двумя точками не обязана быть симметричной.
# с сервера А к серверу Б
mtr -n 10.10.0.2
# с сервера Б к серверу А — отдельная проверка,
# путь туда и обратно может отличаться
mtr -n 10.10.0.1
Смотреть здесь нужно на две вещи. Во-первых, доходит ли трасса до цели вообще, или обрывается на каком-то промежуточном узле — это видно по последней строке вывода: если она показывает потери, а не сам целевой хост, пакеты до получателя не доходят системно, а не эпизодически. Как правильно читать колонки mtr и не спутать штатное ограничение ICMP на промежуточном узле с реальной потерей, разобрано в статье про то, как читать колонки mtr; там же объяснено, почему доверять стоит именно последней строке трассы.
Во-вторых — сама топология маршрута. Если ожидается, что трафик между своими серверами идёт по приватному сегменту или туннелю напрямую, а трасса показывает несколько внешних транзитных узлов между ними, — значит, используется не тот адрес (публичный вместо приватного) либо маршрут в таблице реально указывает наружу, а не в приватный интерфейс. Общий подход к тому, как делить маршрут на участки и находить, на каком конкретно из них теряются пакеты, — в статье про локализацию участка потерь пакетов.
Если трасса обрывается на первом же хопе за пределами самого сервера — это обычно уже не вопрос конфигурации ОС, а следующий, более редкий и чаще всего забываемый уровень.
6. Облачные security groups и ACL — отдельный уровень, до файрвола ОС
Это тот уровень, который чаще всего забывают, потому что он физически не виден на самом сервере. Security group или ACL у облачного провайдера фильтрует трафик до того, как пакет вообще попадёт на сетевой интерфейс операционной системы — значит, iptables, ufw, tcpdump на сервере ничего об этой блокировке не знают и не покажут, потому что пакет до интерфейса ОС просто не долетел.
Логика проверки простая: если файрвол ОС на обеих сторонах пропускает трафик (шаг 2), сервис слушает правильный адрес (шаг 3), а трасса всё равно не доходит либо соединение висит по таймауту без единого ответа — самое время открыть в панели управления облачного провайдера правила security group или сетевого ACL для обоих серверов: разрешён ли конкретный порт именно между этими двумя инстансами (или их подсетью), а не только «из интернета» или «изнутри одной security group», если серверы формально числятся в разных группах.
Подтвердить, что проблема именно на этом уровне, помогает tcpdump на принимающей стороне в момент попытки подключения с другого сервера:
sudo tcpdump -ni eth0 host <ip-сервера-отправителя> and port 5432
Если здесь не появляется вообще ничего — ни одного пакета, — при том что файрвол ОС проверен и не блокирует, это сильный сигнал: пакет отсекается ещё до сетевого интерфейса сервера, на уровне security group, ACL или сетевой инфраструктуры провайдера. Конкретный интерфейс этой настройки отличается от провайдера к провайдеру — идти нужно в раздел сетевых правил в панели управления конкретного облака и сверять правила для обоих серверов, а не только для одного.
Общий принцип: не гадать, а идти со стороны отправителя, потом со стороны получателя
Шесть уровней выше можно проверять по порядку, но на практике быстрее работает не последовательный обход всех шести, а проверка одного и того же момента подключения с двух концов одновременно, вместо того чтобы менять настройки наугад и смотреть, помогло ли.
Практическая последовательность:
- На принимающей стороне запустите
tcpdumpс фильтром по IP отправителя и нужному порту — и оставьте его слушать. - На отправляющей стороне запустите попытку подключения (
nc -zv,curl, реальный запрос приложения). - Смотрите на отправляющей стороне: пакет ушёл (виден в
tcpdump -i <интерфейс-отправителя>на исходящем интерфейсе) или не ушёл вообще — если не ушёл, проблема локальна для отправителя (файрвол OUTPUT, отсутствие маршрута, недоступный шлюз). - Если пакет ушёл, но на принимающей стороне в
tcpdumpне появилось ничего — проблема где-то между серверами: маршрутизация, VPN-туннель, security group провайдера. Она не в файрволе ОС получателя — тот пакет попросту не увидел. - Если пакет дошёл до получателя (виден в его
tcpdump), но ответа не последовало — проблема на стороне получателя: файрвол ОС с правилом DROP, либо сервис не слушает нужный адрес.
Этот метод не требует угадывания: он однозначно указывает, по какую сторону границы находится проблема, за одну параллельную проверку с двух терминалов, а не за несколько циклов правки конфигов и повторных попыток подключения.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Пинг между серверами проходит, а подключение к порту приложения — нет. Что это значит?
ICMP (пинг) и TCP-соединение к конкретному порту проверяются файрволом независимо друг от друга: правило может разрешать ICMP и одновременно блокировать конкретный TCP-порт. Рабочий пинг подтверждает только то, что маршрутизация в целом работает и хосты видят друг друга на сетевом уровне — дальше нужно отдельно проверять файрвол и биндинг сервиса именно для нужного порта.
Как отличить, что блокирует именно файрвол, а не маршрутизация?
По характеру отказа при попытке подключения: Connection refused означает, что пакет дошёл до хоста и получил явный отказ (нет слушателя на порту или правило REJECT) — это не про маршрут. Таймаут без единого ответа не отличить одной командой: это может быть и правило DROP, и обрыв маршрута, и security group провайдера — для этого случая нужна проверка tcpdump с двух сторон по методу из предыдущего раздела.
Оба сервера у одного провайдера в одном дата-центре — обязательно ли гонять трафик через VPN?
Не обязательно, если провайдер даёт приватную сеть внутри своей инфраструктуры (второй интерфейс, VLAN) — тогда VPN-туннель просто не нужен для связи между этими двумя серверами. Разница между приватной сетью провайдера и VPN-туннелем и когда что уместнее разобрана в статье про приватную сеть между своими серверами.
Подключаемся по доменному имени, а не по IP — может проблема быть в DNS?
Да, и стоит исключить эту причину в первую очередь: если имя резолвится не в тот адрес (например, случайно в публичный IP вместо приватного, или вообще не резолвится с одного из серверов), внешне это выглядит как «связи нет», хотя на самом деле сеть ни при чём. Проверяется через dig <имя> или getent hosts <имя> на обеих машинах и сравнением с ожидаемым адресом — а для самой диагностики связности лучше сразу тестировать по IP, чтобы не путать сетевую проблему с проблемой резолвинга.
Все шесть уровней проверены, а связи всё равно нет — что дальше?
Реже встречающаяся, но реальная причина — проблема с MTU на пути через туннель: маленькие пакеты (тот же ping) проходят нормально, а более крупные пакеты приложения теряются из-за фрагментации. Это отдельная тема, которая обычно всплывает уже после того, как первые шесть уровней исключены, и заслуживает отдельного разбора, а не догадки в рамках этого чек-листа.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →