OpenVPN “TLS Error: TLS key negotiation failed”: поширені причини та виправлення

Було корисно?

Коли OpenVPN викидає “TLS Error: TLS key negotiation failed to occur within 60 seconds”, це не художній каламбур.
Це каже вам: «Я спробував встановити захищений зв’язок, і або ніхто не відповів, або ми не змогли узгодити спосіб спілкування».

У промисловому середовищі ця помилка краде час. Вона з’являється під час зміни мережі, ротації сертифікатів, «швидкого» підправлення фаєрвола або того роду дивакуватостей ISP, які неможливо ескалувати до когось, кому це цікаво.
Хороша новина: зазвичай її можна знайти за кілька хвилин, якщо припинити гадати й почати доводити.

Що насправді означає ця помилка (і чого вона не означає)

TLS-узгодження OpenVPN — це фаза, в якій клієнт і сервер аутентифікують один одного, узгоджують криптопараметри і створюють матеріал ключів для тунелю.
Якщо ви бачите:
“TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)”
зазвичай це означає одну з таких загальних проблем:

  • Ніякі пакети не досягли сервера (неправильна IP/порт, UDP заблоковано, падіння фаєрволом, неправильний маршрут через NAT).
  • Пакети досягли сервера, але відповіді не дійшли до клієнта (асиметричний маршрут, проблеми зі станом NAT, фільтрація вихідного трафіку).
  • Пакети текли, але TLS не зміг завершитись (невідповідність сертифікатів/CA, зсув часу, невідповідність cipher/версій, невідповідність tls-auth/tls-crypt).
  • Пакети текли, але фрагментація/втрати зруйнували рукостискання (проблеми MTU/MSS, path MTU black holes, висока втрата на UDP).
  • Ви потрапляєте не на той екземпляр OpenVPN (порт використовується іншим сервісом, неправильний протокол, неправильна конфігурація сервера).

Чого це зазвичай не означає: «OpenVPN зламався». OpenVPN — це нудне ПЗ. Якби це була людина, воно мало б бирку з іменем і строгі погляди на відступи.

Ще нюанс: повідомлення клієнта часто загальне. Ви отримаєте більше правди зі серверного логу, оскільки сервер може розрізнити «я тебе не бачив» від «я бачив і відхилив».

Швидкий план діагностики

Перше: доведіть базову доступність (IP, порт, протокол)

  1. Підтвердіть, що ви використовуєте правильний протокол (UDP vs TCP). UDP-клієнт, що звертається до TCP-слухача, виглядатиме як чорна діра.
  2. З клієнта: чи досяжний порт? Використайте швидкі опитування (навіть для UDP) і захоплення пакетів.
  3. З сервера: чи бачите ви вхідні пакети? Якщо сервер нічого не бачить, припиніть перекручуватися з шифрами та сертифікатами.

Друге: зіставте логи клієнта і сервера

  1. На сервері шукайте спроби підключення у той самий час, коли клієнт намагається.
  2. Якщо сервер бачить клієнта, але відхиляє його, серверний лог зазвичай вкаже причину (TLS auth failed, неправильний сертифікат, невідомий cipher).

Третє: виключіть «тихі вбивці» (час, tls-auth/tls-crypt, MTU)

  1. Зсув часу: сертифікати можуть бути «ще не дійсними» або «спливли», і ви витратите годину, звинувачуючи фаєрволи.
  2. tls-auth/tls-crypt mismatch: одна сторона очікує додаткову HMAC/обгортку шифрування, інша — ні. Результат: сервер відкидає пакети ще до початку TLS.
  3. MTU/фрагментація: особливо при UDP у обмежених мережах; рукостискання може провалюватись при втратах або чорних дірах фрагментів.

Четверте: тільки потім вивчайте політику крипто

  1. data-ciphers / невідповідність cipher, обмеження за версією TLS, зміни політики OpenSSL або FIPS-обмеження.
  2. Дрейф конфігурацій клієнта і сервера (класична пастка «раніше працювало»).

Суха істина: якщо у вас немає серверних логів і видимості пакетів, ви не діагностуєте — ви займаєтеся крипто-магією.

Цікаві факти та історичний контекст

  • OpenVPN з’явився до модної теми «zero trust»: він став популярним на початку 2000-х як гнучкий TLS-базований VPN, коли розгортання IPsec часто було болісним.
  • Дизайн «UDP-перш за все» — усвідомлений: OpenVPN зазвичай використовує UDP, щоб уникнути проблем TCP-over-TCP і зменшити затримки при втратах.
  • tls-auth був прагматичним фільтром DoS: додавання HMAC до пакетів дозволяє серверу дешево відкидати неавторизований шум перед дорогою TLS-обробкою.
  • tls-crypt підняв планку: він не тільки аутентифікує, а й шифрує канал управління TLS, приховуючи метадані і зменшуючи фингерпринтинг.
  • Переговори cipher еволюціонували: старі конфіги використовували одиночний cipher; новіші версії віддають перевагу data-ciphers для переговору з переліку.
  • Версії TLS стали питанням політики: коли TLS 1.0/1.1 були застарілими, VPN мусили йти в ногу — інакше падали у способи, що виглядають як «мережеві проблеми».
  • Проблеми MTU існують довше за VPN: path MTU discovery був джерелом «працює у мене» з давніх часів, а інкапсуляція VPN полегшує їх виникнення.
  • NAT змінив усе: VPN виросли в світі, що все більше наповнюється NAT (пізніше CGNAT), що ускладнює відстеження стану UDP і доступність для вхідних підключень.

Області відмов: де гине TLS-узгодження

1) Ви взагалі не досягаєте OpenVPN-сервера

Це найпоширеніша категорія і одночасно найчастіше ігнорована.
Клієнт каже «TLS negotiation failed», але реальна помилка — «пакети ніде не потрапили».
Думайте: неправильна IP-адреса, неправильний порт, неправильний протокол, DNS вказує на стару адресу, падіння фаєрволом, групи безпеки в хмарі, фільтрація від ISP або застарілий маршрут.

2) Ви потрапляєте кудись, але не туди, куди думаєте

Спільні IP і повторне використання портів можуть бути веселими, поки не перестануть бути.
Якщо порт 1194 тепер належить іншому сервісу, OpenVPN радо відправлятиме пакети у порожнечу.
Або ви потрапляєте на load balancer, що неправильно форвардить UDP.

3) Сервер отримує пакети, але відкидає їх до початку TLS

Якщо на сервері увімкнено tls-auth або tls-crypt, пакети каналу управління, які не відповідають очікуваному ключу, відкидаються рано.
Це «тихо» за дизайном: це міра проти сканування. Добре для безпеки, погано для вашого артеріального тиску.

4) TLS починається, але перевірка сертифікатів провалюється

Поширені причини: неправильний CA, прострочений клієнтський сертифікат, невідповідність EKU, невідповідність імені сервера, відкликаний сертифікат (якщо ви застосовуєте CRL) або зсув часу.
У сучасному OpenVPN логи часто бувають явними — якщо ви дивитесь на правильний бік (сервер vs клієнт).

5) Невідповідність криптопереговорів

Класика: невідповідність наборів шифрів, невідповідність версій TLS, обмеження політики OpenSSL або занадто старий клієнт, що не підтримує бажаний «діалект» сервера.
Це може проявлятися як помилка рукостискання або як тайм-аут, залежно від того, як саме відбувається відмова і що логуються.

6) MTU, фрагментація і втрата UDP ламають рукостискання

Повідомлення TLS можуть бути більшими, ніж ви очікуєте, особливо з ланцюжками сертифікатів.
На UDP ці повідомлення можуть фрагментуватися. Якщо фрагменти втрачаються — або PMTUD заблоковано — пакети рукостискання зникають і OpenVPN чекає тайм-аут.
Це жорстоко, бо «деякі мережі працюють», а «деякі — ні», що спокушає звинувачувати сертифікати.

7) Виснаження стану та обмеження швидкості

Якщо фаєрвол/NAT має агресивні UDP-таймаути або обмежує «невідомий UDP», ваші початкові пакети можуть відкидатися.
На сервері таблиці conntrack можуть заповнитися; у мережі клієнта NAT-мапінги можуть активно змінюватись.
Під навантаженням це виглядає як випадкові тайм-аути TLS — найгірший тип інциденту: той, що непостійний.

Перефразована ідея від Werner Vogels (Amazon): Все ламається, весь час; ваше завдання — проектувати і експлуатувати системи, які справляються з цією реальністю.

Практичні завдання: команди, що означає вивід, і що робити далі

Нижче — польові перевірені завдання. Виконуйте їх у порядку, поки відмова не стане очевидною.
Кожне завдання містить: виконувану команду, приклад виводу, що це означає, і рішення, яке ви приймаєте.
Так, це повторюється. У цьому й суть: повторення перемагає імпровізацію під час інциденту.

Завдання 1: Підтвердіть, що клієнт націлений на правильне місце (DNS/IP/порт)

cr0x@server:~$ getent ahosts vpn.example.com
203.0.113.10   STREAM vpn.example.com
203.0.113.10   DGRAM  vpn.example.com
203.0.113.10   RAW    vpn.example.com

Значення: DNS розв’язує в 203.0.113.10. Якщо ви очікували іншу IP (новий VIP, новий хмарний LB), ви щойно знайшли дрейф конфігурації.

Рішення: Якщо IP неправильний — виправте DNS або профіль клієнта. Якщо IP правильний — продовжуйте.

Завдання 2: Перевірте, що процес OpenVPN слухає очікуваний протокол/порт

cr0x@server:~$ sudo ss -lpun | grep -E ':(1194|443)\b'
UNCONN 0      0      0.0.0.0:1194      0.0.0.0:*    users:(("openvpn",pid=1423,fd=6))

Значення: Сервер слухає UDP 1194 на всіх інтерфейсах.
Якщо ви бачите tcp замість цього, або воно прив’язане лише до 127.0.0.1, клієнт не зможе підключитись.

Рішення: Якщо не слухає там, де ви думаєте — виправте systemd unit/конфіг і перезапустіть OpenVPN. Інакше — продовжуйте.

Завдання 3: Перевірте серверні логи на наявність спроб клієнта

cr0x@server:~$ sudo journalctl -u openvpn-server@server -S -10min --no-pager
Dec 27 12:10:41 vpn01 openvpn[1423]: UDPv4 link local (bound): [AF_INET]0.0.0.0:1194
Dec 27 12:11:02 vpn01 openvpn[1423]: TLS: Initial packet from [AF_INET]198.51.100.25:54521, sid=2e9c1d7a 3c8d7a4b
Dec 27 12:11:32 vpn01 openvpn[1423]: TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
Dec 27 12:11:32 vpn01 openvpn[1423]: TLS Error: TLS handshake failed

Значення: Сервер бачив початковий пакет з IP клієнта. Отже це не «UDP зовсім заблоковано».
Тепер питання: чи відповідав сервер, і чи отримав клієнт відповідь?

Рішення: Перейдіть до захоплення пакетів і перевірки фільтрів. Якщо ви не бачите рядків «Initial packet» взагалі, зосередьтесь на доступності/фаєрволі перед будь-якими іншими діями.

Завдання 4: Захоплення пакетів на сервері, щоб підтвердити двосторонній трафік

cr0x@server:~$ sudo tcpdump -ni eth0 udp port 1194 and host 198.51.100.25
12:11:02.101234 IP 198.51.100.25.54521 > 203.0.113.10.1194: UDP, length 256
12:11:02.101890 IP 203.0.113.10.1194 > 198.51.100.25.54521: UDP, length 304
12:11:05.103100 IP 198.51.100.25.54521 > 203.0.113.10.1194: UDP, length 256
12:11:05.103640 IP 203.0.113.10.1194 > 198.51.100.25.54521: UDP, length 304

Значення: Ви бачите запит і відповідь. Це свідчить, що сервер відповідає і маршрутизація коректна (принаймні з перспективи сервера).
Якщо ви бачите лише вхідні пакети і немає вихідних відповідей, підозрюйте локальні правила фаєрволу, rp_filter або політичну маршрутизацію.

Рішення: Якщо відповіді існують, підозрюйте фільтрацію на стороні клієнта, MTU/втрати або невідповідність TLS-параметрів. Якщо відповідей немає — виправляйте egress та фаєрвол на сервері.

Завдання 5: Підтвердьте, що хостовий фаєрвол не відкидає OpenVPN

cr0x@server:~$ sudo iptables -S | sed -n '1,120p'
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p udp --dport 1194 -j ACCEPT

Значення: UDP/1194 дозволено входити, стан збережено, за замовчуванням DROP.
Якщо ви не бачите явного дозволу, ваші пакети вмирають на порозі.

Рішення: Додайте правило allow для правильного порту/протоколу на відповідному інтерфейсі. Якщо ви використовуєте nftables/ufw/firewalld, перевірте на відповідному рівні.

Завдання 6: Перевірте reverse path filtering (rp_filter) при асиметричній маршрутизації

cr0x@server:~$ sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.eth0.rp_filter
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1

Значення: Строгий rp_filter може відкидати пакети, якщо ядро вважає, що джерело недосяжне через цей інтерфейс — часто при multi-homing, політичній маршрутизації або вторинних NIC у хмарі.

Рішення: Якщо у вас є асиметричні маршрути за дизайном, встановіть rp_filter у loose-режим (2) для відповідних інтерфейсів і проведіть огляд безпеки.

Завдання 7: Перевірте, що сервер маршрутизує відповіді тим же шляхом

cr0x@server:~$ ip route get 198.51.100.25
198.51.100.25 via 203.0.113.1 dev eth0 src 203.0.113.10 uid 0
    cache

Значення: Ядро відповідатиме через eth0 з джерелом 203.0.113.10. Якщо ви бачите інший інтерфейс або іншу IP-адресу джерела, NAT і відстеження стану можуть зламатися.

Рішення: Виправте маршрути/політику маршрутизації, щоб відповіді йшли правильно. Якщо використовуєте плаваючу IP, переконайтесь, що адреса джерела дійсна на цьому інтерфейсі.

Завдання 8: Виявлення невідповідності tls-auth / tls-crypt у конфігурації

cr0x@server:~$ sudo grep -R --line-number -E '^(tls-auth|tls-crypt|tls-crypt-v2)\b' /etc/openvpn/server/*.conf
/etc/openvpn/server/server.conf:19:tls-crypt /etc/openvpn/server/ta.key

Значення: Сервер вимагає tls-crypt з конкретним ключем. Якщо клієнт використовує tls-auth, або інший ключ, пакети будуть відкинуті рано.

Рішення: Зробіть так, щоб клієнт і сервер точно збігалися: однаковий директив (tls-crypt vs tls-auth), той самий ключ, правильний напрямок, якщо використовується tls-auth.

Завдання 9: Переконайтесь, що профіль клієнта містить правильні tls-crypt або tls-auth матеріали

cr0x@server:~$ grep -nE '^(remote|proto|port|tls-auth|tls-crypt|key-direction)\b' client.ovpn
4:proto udp
5:remote vpn.example.com 1194
12:tls-crypt ta.key

Значення: Клієнт вказує UDP до vpn.example.com:1194 і очікує tls-crypt з ta.key.
Якщо сервер використовує tls-crypt-v2, а клієнт має звичайний tls-crypt ключ — будете мати проблеми.

Рішення: Вирівняйте профіль клієнта з налаштуваннями сервера; при потребі згенеруйте бандли наново. Не копіюйте ключі вручну під тиском.

Завдання 10: Перевірте дати дії сертифікатів і синхронізацію часу (клієнт і сервер)

cr0x@server:~$ date -u
Sat Dec 27 12:12:10 UTC 2025
cr0x@server:~$ openssl x509 -in /etc/openvpn/pki/issued/client01.crt -noout -dates
notBefore=Dec 27 00:00:00 2025 GMT
notAfter=Dec 27 00:00:00 2026 GMT

Значення: Якщо системний час позаду notBefore, сертифікат «з майбутнього». Якщо час попереду notAfter, він прострочений.
Обидва випадки можуть проявлятись як TLS-помилка, іноді як тайм-аути, залежно від детальності логування.

Рішення: Виправте NTP/chrony/systemd-timesyncd, потім спробуйте знову. Якщо сертифікат прострочений — випустіть новий і відкличте старий.

Завдання 11: Переконайтесь, що клієнт використовує правильний CA-ланцюжок

cr0x@server:~$ openssl verify -CAfile /etc/openvpn/pki/ca.crt /etc/openvpn/pki/issued/client01.crt
/etc/openvpn/pki/issued/client01.crt: OK

Значення: Якщо це провалюється з «unable to get local issuer certificate», ви використовуєте неправильний CA або бракує проміжного.

Рішення: Виправте CA-бандл, розповсюджений клієнтам. Якщо ви ротували CA, очікуйте запізнілих клієнтів; обробляйте це через перекриття довіри, а не надію.

Завдання 12: Проінспектуйте узгоджені налаштування cipher OpenVPN (дрейф сервера)

cr0x@server:~$ sudo grep -E '^(cipher|data-ciphers|data-ciphers-fallback|tls-version-min|tls-cipher)\b' /etc/openvpn/server/server.conf
data-ciphers AES-256-GCM:AES-128-GCM
data-ciphers-fallback AES-256-CBC
tls-version-min 1.2

Значення: Сервер буде узгоджувати лише ці data-ciphers; також вимагає TLS 1.2+. Якщо у вас є застарілі клієнти, що підтримують лише BF-CBC або TLS 1.0/1.1, вони проваляться.

Рішення: Бажано оновити клієнти. Якщо тимчасово потрібно підтримувати старих — розширюйте crypto лише під контролем змін з кінцевою датою.

Завдання 13: Перевірте невідповідність груп безпеки хмари / фаєрволу хоста за допомогою лічильників

cr0x@server:~$ sudo iptables -vnL INPUT | sed -n '1,120p'
Chain INPUT (policy DROP 102 packets, 6120 bytes)
 pkts bytes target     prot opt in  out source          destination
  980 58800 ACCEPT     all  --  lo  *   0.0.0.0/0       0.0.0.0/0
  120  9600 ACCEPT     all  --  *   *   0.0.0.0/0       0.0.0.0/0  ctstate RELATED,ESTABLISHED
   10   760 ACCEPT     udp  --  *   *   0.0.0.0/0       0.0.0.0/0  udp dpt:1194

Значення: Лічильники інкрементуються на правилі UDP/1194 коли клієнти намагаються підключитись. Якщо лічильники залишаються нульовими, тоді tcpdump також нічого не показує — пакети фільтруються вище (security group, NACL, ISP).

Рішення: Якщо лічильники інкрементуються, але рукостискання провалюється — це не зовнішнє фільтрування; переходьте до TLS/MTU. Якщо лічильники не інкрементуються — виправляйте upstream ACL.

Завдання 14: Перевірте тиск на conntrack (виснаження стану може давати «випадкові» падіння UDP)

cr0x@server:~$ sudo conntrack -S
cpu=0 found=12034 invalid=2 ignore=0 insert=9012 insert_failed=0 drop=0 early_drop=0 error=0 search_restart=0

Значення: Якщо ви бачите зростаючі drop або early_drop, відстеження стану під тиском.
На завантажених VPN-концентраторах це може спрацювати через сканування, некоректних клієнтів або просто замалі таблиці conntrack.

Рішення: Збільшіть ліміти conntrack, зменшіть експозицію і розгляньте використання tls-auth/tls-crypt, щоб зменшити сміття. Але лікуйте причину, а не тільки симптом.

Завдання 15: Швидка перевірка UDP-з’єднання з мережі клієнта

cr0x@server:~$ nc -uv -w2 203.0.113.10 1194
Connection to 203.0.113.10 1194 port [udp/*] succeeded!

Значення: Це лише доводить, що ви можете відправляти UDP-пакети, а не що OpenVPN відповідає. Але корисно: якщо це відразу падає (DNS, маршрут), ви вже мертві на ранньому етапі.

Рішення: Якщо це «не вдається» — зупиніться і виправляйте базову доступність. Якщо вдається — продовжуйте зіставленням tcpdump/логів на сервері.

Завдання 16: Перевірте проблеми MTU, зменшивши і повторивши спробу

cr0x@server:~$ sudo grep -nE '^(tun-mtu|mssfix|fragment)\b' /etc/openvpn/server/server.conf
cr0x@server:~$ sudo sh -c 'printf "\n# TEMP MTU clamp for handshake debugging\nmssfix 1360\ntun-mtu 1500\n" >> /etc/openvpn/server/server.conf'
cr0x@server:~$ sudo systemctl restart openvpn-server@server

Значення: mssfix зменшує TCP MSS для тунельних TCP-потоків і може опосередковано стабілізувати шляхи, що мають проблеми з фрагментацією.
Деяким середовищам також допомагає регулювання tun-mtu або fragment (але фрагментація — крайній засіб).

Рішення: Якщо MTU-clamp вирішує тайм-аути рукостискання в конкретних мережах, ви знайшли проблему path MTU. Тоді зробіть акуратніше виправлення (правильний розмір MTU, уникати чорних дір ICMP, за потреби використовувати TCP 443 як крайній варіант).

Жарт №1: UDP — як офісні плітки: швидко, поширено і іноді відсутні важливі деталі саме тоді, коли вони потрібні.

Типові помилки: симптом → корінна причина → виправлення

1) Симптом: Клієнт чекає тайм-аут; серверні логи нічого не показують

Корінна причина: Пакети ніколи не потрапляють на сервер: неправильна IP/порт, UDP заблоковано, відсутня група безпеки/NACL, ISP блокує UDP, DNS вказує на старий хост.

Виправлення: Підтвердіть DNS, підтвердіть слухача за допомогою ss, відкрийте фаєрвол і upstream ACL, перевірте серверний tcpdump що пакети приходять.

2) Симптом: Сервер бачить «Initial packet», потім тайм-аут

Корінна причина: Шлях додому зламаний, фільтрація на боці клієнта або MTU/втрати заважають завершити рукостискання.

Виправлення: Серверний tcpdump щоб підтвердити відповіді, перевірте маршрути (ip route get), rp_filter, тестуйте з альтернативних мереж і застосуйте MTU-clamp, якщо потрібно.

3) Симптом: Працює в одній мережі, не працює в готелі/4G/корпоративному Wi‑Fi

Корінна причина: UDP блокується або обмежується; CGNAT з агресивними UDP-таймаутами; MTU black holes; captive portals.

Виправлення: Надайте профіль TCP 443 як сумісний запас (не як основний), або використовуйте UDP 443; clamp MTU; забезпечте keepalive/ping для збереження NAT-мапінгу.

4) Симптом: “TLS Error: tls-crypt unwrapping failed” або тихий тайм-аут після ввімкнення tls-crypt

Корінна причина: Несумісний tls-crypt ключ або змішування директив tls-auth/tls-crypt.

Виправлення: Перевипустіть клієнтський профіль; переконайтеся, що сервер і клієнт використовують той самий tls-crypt ключ і метод. Не копіюйте ключі вручну між репозиторіями і ноутбуками.

5) Симптом: Рукостискання TLS провалюється одразу після ротації сертифікатів

Корінна причина: Неправильний CA розповсюджено, відсутні проміжні, прострочені клієнтські сертифікати або клієнти «прив’язані» до старого CA.

Виправлення: Робіть перекриття довіри під час ротації CA, розповсюджуйте нові профілі централізовано, контролюйте терміни дії і перевіряйте через openssl verify.

6) Симптом: Оновлення сервера; старі клієнти починають тайм-аутити

Корінна причина: Мінімум TLS підвищено, змінено список шифрів, застарілі алгоритми видалені політикою OpenSSL.

Виправлення: Оновіть клієнти. Якщо потрібно тимчасово підтримати спадщину — явно вкажіть сумісні data-ciphers та опції TLS з терміном дії.

7) Симптом: “AUTH_FAILED” не показується; лише TLS negotiation failed

Корінна причина: Аутентифікація відбувається після TLS. Ви навіть не досягаєте цього етапу — це транспорт/TLS, а не username/password.

Виправлення: Перестаньте займатися ротацією паролів. Спочатку перевірте доступність мережі, tls-auth/tls-crypt, перевірку сертифікатів і логи.

8) Симптом: Випадкові відмови під навантаженням, особливо під час сканувань

Корінна причина: Виснаження conntrack, піки CPU від роботи рукостискань або обмеження швидкості upstream.

Виправлення: Використовуйте tls-auth/tls-crypt, звужуйте експозицію фаєрволом, масштабуйтесь, моніторьте conntrack і CPU; не чекайте, доки ноутбук директора стане канаркою.

Три міні-історії з корпоративного життя (анонімізовано, правдоподібно і болісно)

Міні-історія 1: Інцидент через хибне припущення

Середня компанія використовувала OpenVPN для інженерів і on-call співробітників. Вони використовували UDP/1194 і мали усталений клієнтський профіль.
Одного тижня віддалений доступ «випадково» почав падати у частини користувачів — переважно тих, хто подорожував.

Перше припущення було класичним: «мають бути сертифікати». Добросердечний адміністратор рано ротував серверний сертифікат, перевипустив деякі клієнтські сертифікати і розіслав нові профілі кільком людям.
Нічого не змінилося. Паніка зростала. Люди почали пробувати з особистих хот-спотів і отримували різні результати, що тільки підживлювало міф про «ненадійність крипто».

Справжній винуватець був нудним: компанія мігрувала публічний інгрес до нового провайдера і оновила DNS, але частина клієнтських профілів була прив’язана до IP-адреси замість хостнейму.
Ці клієнти все ще націлювалися на стару IP, яка тепер належала іншому орендарю. Пакети не потрапляли на OpenVPN зовсім.

Виправлення не було перевипуском ключів. Це був cleanup: вимагати хостнейми в профілях, уникати захардкожених IP, якщо ви не володієте IP назавжди, і централізовано керувати профілями, щоб дрейф не міг жити безкарно.
Пункт постмортему, що мав значення: додати pre-flight скрипт, який підтверджує, що розв’язаний IP відповідає очікуваному ASN/провайдеру перед запуском тунелю.

Міні-історія 2: Оптимізація, що зіграла злий жарт

Інша організація захотіла «зменшити накладні витрати» і вирішила різко звузити криптографічну політику.
Вони прибрали CBC-fallback, вимагали TLS 1.3 (або думали, що вимагають), і скоротили дозволений список шифрів до мінімуму.
Безпека аплодувала. Графіки продуктивності стали трохи приємніші. Усі пішли додому з відчуттям виконаного обов’язку.

В понеділок вранці: керівництво могло підключитись, дехто з інженерів — теж, але велика кількість керованих ноутбуків не могла.
На клієнті помилка була така сама стара тайм-аут-повідомлення. Допомога була ще старша: «переінсталюйте VPN-клієнт».
Це не допомагало, бо справа не була в пошкоджених інсталяціях; це була невідповідність можливостей.

Керований парк ноутбуків мав старішу версію OpenVPN, упаковану в корпоративний образ з повільним циклом оновлення.
Ці клієнти не підтримували звужену переговорну політику шифрів, яку сервер тепер вимагав.
Оскільки відмова відбувалась на ранньому етапі TLS-узгодження, це виглядало як «мережеві проблеми», хоча пакети текли.

Відкат виправив проблему, але справжнє рішення — процес: встановити матрицю сумісності, запускати крипто-зміни на канаркових групах і мати вимірюваний план депрекації.
Сувора крипто — добре; сюрпризна крипто — як зробити «покращення безпеки», що стає інцидентом продуктивності.

Міні-історія 3: Нудна, але правильна практика, що врятувала ніч

Команда фінансових послуг експлуатувала OpenVPN із процедурою змін, яка здавалася надто нудною, поки не стала рятівною.
Вони мали: зафіксовані конфіги серверів у VCS, стандартизоване логування, односторінковий runbook і заплановані ротації сертифікатів з перекриттям.
Ніхто за це не вихвалявся, бо це не захопливо.

Однієї ночі провайдер мережі мав відмову, що спричинила переривчасті втрати пакетів на шляху, яким користувались віддалені співробітники в регіоні.
Користувачі повідомили про тайм-аути TLS. On-call інженер відкрив runbook і почав зі серверних доказів: tcpdump + кореляція логів.
Вони відразу побачили: вхідні пакети приходять, відповіді йдуть, але повторні передачі і пропуски вказували на втрати поза їхнім краєм.

Команда вже мала два профілі: UDP як основний і TCP 443 як запас, і документували, коли використовувати запас.
Підтримка тимчасово переключила постраждалих користувачів на TCP 443, поки провайдер не виправив маршрутизацію.
Робота тривала. Ніхто не чіпав сертифікати. Ніхто не «оптимізував» списки шифрів о 2-й ночі.

Нудна річ, що їх врятувала: дисциплінована спостережливість і наявність документованого, протестованого запасу.
Не героїзм. Не гадання. Просто опції, які практикували.

Контрольні списки / покроковий план

Покроково: від «TLS negotiation failed» до корінної причини

  1. Визначте кортеж: публічна IP/hostname сервера, протокол (udp/tcp), порт.
    Підтвердіть, що клієнт насправді використовує те, що ви думаєте (а не те, що ви вважаєте).
  2. Перевірте слухача сервера: ss -lpun або ss -lptn.
    Якщо він не слухає — більше нічого не має значення.
  3. Шукайте спроби клієнта в логах сервера: якщо немає слідів — це upstream (DNS, маршрутизація, фаєрвол, група безпеки).
  4. Запустіть tcpdump на сервері: підтвердіть вхідні та вихідні пакети для IP клієнта, що не вдається.
  5. Перевірте фаєрвол і маршрути: правила iptables/nftables, rp_filter, ip route get.
  6. Перевірте вирівнювання tls-auth/tls-crypt: сервер і клієнт мають збігатися в директивах і ключах.
  7. Перевірте час і ланцюжок сертифікатів: системний годинник, дати сертифікатів, верифікація CA.
  8. Підтвердіть налаштування криптопереговорів: data-ciphers, fallback, tls-version-min.
  9. Перевірте гіпотезу MTU: застосуйте консервативний mssfix, спробуйте знову, порівняйте успіх по мережах.
  10. Якщо все ще застрягли: тимчасово підвищіть вивід відлагодження (сервер і клієнт), захопіть пакети з обох боків і порівняйте, що виходить і що приходить.

Операційний чекліст: як запобігти цьому класу інцидентів

  • Стандартизуйте клієнтські профілі (генеровані, не ручні) і встановлюйте їхнє термінове завершення при ротації ключів.
  • Моніторте закінчення терміну сертифікатів для сервера і інфраструктури видачі клієнтських сертифікатів, а не лише публічного TLS-сертифіката.
  • Майте запасний профіль (зазвичай TCP 443) і тестуйте його щоквартально. Це не елегантно; це практично.
  • Логуйте в одному місці (агрегація journalctl або syslog) і зберігайте достатню ретенцію для порівняння з вікнами змін.
  • Відстежуйте дрейф конфігурації за допомогою версійного контролю і контрольних сум розгортання.
  • Робіть крипто-зміни з канарками: спочатку невелика група, потім флот.
  • Базуйте MTU для поширених клієнтських мереж; встановіть розумні значення за замовчуванням і уникайте залежності від фрагментації.
  • Зміцніть вхідні підключення за допомогою tls-auth/tls-crypt, щоб зменшити сміттєвий трафік і навантаження на CPU/conntrack.

Жарт №2: Єдина річ, яку узгоджують швидше за TLS-рукостискання — це час на нараду, доки ви не запросите п’ять часових поясів.

Питання та відповіді

1) Чому клієнт каже «check your network connectivity», коли насправді проблема з сертифікатом?

Тому що клієнт часто чекає успішного рукостискання і виводить загальне повідомлення при тайм-ауті.
Серверний лог зазвичай більш конкретний. Завжди зіставляйте обидві сторони перед тим, як торкатися PKI.

2) UDP чи TCP: що обрати, щоб уникнути помилок TLS-узгодження?

За замовчуванням використовуйте UDP заради продуктивності і стійкості при втратах. Тримайте TCP 443 як запас для ворожих мереж, що блокують UDP.
Не переводьте все на TCP лише тому, що воно «здається надійним»; TCP-over-TCP може підсилювати затримки і повтори.

3) Чи може неправильний системний годинник справді спричинити «TLS key negotiation failed»?

Так. Якщо час клієнта або сервера поза діапазоном дійсності сертифіката, TLS провалюється.
Виправте синхронізацію часу спочатку, потім повторіть тест. Це одне з найдешевших рішень.

4) У чому практична різниця між tls-auth і tls-crypt?

Обидва додають попередньо спільний ключ для каналу управління. tls-auth аутентифікує пакети HMAC; tls-crypt аутентифікує і шифрує канал управління.
Невідповідності призводять до відкидання пакетів ще до завершення TLS, часто виглядаючи як тайм-аут.

5) Я бачу «Initial packet from …» на сервері. Чи гарантує це, що клієнт отримає відповіді?

Ні. Це доводить лише односторонню доставку. Вам все ще потрібно підтвердити, що відповіді сервера доходять до клієнта.
Використайте tcpdump на сервері (а ідеально — і на стороні клієнта) для перевірки кругового шляху.

6) Чи можуть проблеми MTU справді ламати саме рукостискання?

Абсолютно. Повідомлення TLS можуть бути великими і фрагментуватися на UDP.
Якщо фрагменти втрачаються (поширено на деяких шляхах), рукостискання тайм-аутиться. MTU-clamping і уникнення чорних дір ICMP допомагають.

7) Після оновлення OpenVPN/OpenSSL клієнти почали падати. Що змінилось?

Часто: мінімальна версія TLS за замовчуванням підвищилась, заборонені застарілі шифри, посилились перевірки сертифікатів або змінилась поведінка переговорів для data-ciphers.
Трактуйте оновлення як подію сумісності; тестуйте старих клієнтів проти нових серверів перед розгортанням.

8) Як швидко визначити, чи проблема upstream фаєрвол/група безпеки чи конфіг сервера?

Якщо серверні логи не показують спроб клієнта і tcpdump на сервері нічого не бачить — це upstream.
Якщо tcpdump показує вхідні пакети і сервер відповідає, це не upstream-фільтрація; це шлях назад, фільтрація на боці клієнта або TLS/MTU-узгодження.

9) Чи варто збільшувати TLS timeout понад 60 секунд?

Лише як тимчасовий діагностичний інструмент. Збільшення тайм-ауту ховає симптоми і затягує інцидент.
Виправляйте підлягаючу проблему: доступність, втрата/MTU, несумісність tls-crypt або крипто-настройки.

10) Чи може “TLS key negotiation failed” спричинятися авторизацією користувача/паролем?

Зазвичай ні. Username/password відбувається після встановлення TLS-каналу.
Якщо TLS не завершується, сервер навіть не може запросити облікові дані.

Висновок: наступні кроки, щоб запобігти наступному інциденту

«TLS key negotiation failed» — це повідомлення з широкою площею потенційних причин. Ставтеся до нього як до проблеми маршрутизації, поки не доведено протилежне, потім — як до проблеми конфігурації TLS, і лише після цього починайте звинувачувати PKI.
Більшість витрачених годин походить від пропуску цього порядку.

Практичні наступні кроки:

  1. Запишіть ваш відомо добрий кортеж (hostname/IP, протокол, порт) і автоматично перевіряйте його під час деплойментів.
  2. Стандартизуйте профілі, щоб tls-crypt/tls-auth і списки шифрів не могли дрейфувати між користувачами.
  3. Інструментуйте край: збережені серверні логи, можливість tcpdump, лічильники фаєрвола, моніторинг conntrack.
  4. Тримайте протестований запас (звичайно TCP 443) і документуйте, коли його використовувати.
  5. Плануйте крипто- та CA-зміни як реальні міграції: поетапні розгортання, періоди перекриття і явні EOL для застарілих клієнтів.

Зробіть це, і наступного разу ця помилка буде діагностована за десять хвилин замість двох годин суперечок між «це фаєрвол» і «це сертифікати».

← Попередня
Майбутні GPU для ноутбуків: підйом «тонкого монстра»
Наступна →
Безкінечна ера 14 нм у Intel: коли затримки процесу перетворилися на мильну оперу

Залишити коментар