Кожне виправлення було справжнім – а нас усе одно викидало з гри

Ми з сином граємо в No Man's Sky удвох, він на Windows, я на Mac, і приблизно через десять хвилин нас викидало з сесії. Поки я ганявся за причиною, знайшлися три цілком справжні несправності: правило файрвола, що діяло лише в одному мережевому профілі; роутер, який сам призначив себе DNS-сервером для всієї квартири; і браузер, що за моєю спиною ходив у власний DNS. Я виправив усі три – і нічого не зрушило, а потім 12 секунд запису трафіку показали чому: два комп’ютери в одній квартирі, на одному комутаторі, не обмінювалися жодним ігровим пакетом.

Ми з сином граємо в No Man’s Sky удвох, із двох комп’ютерів в одній квартирі: він на Windows, я на Mac, і кожну сесію я налаштовую сам. Першого ж разу Windows спитала, чи пускати nms.exe у мережу, а що син сидить під звичайним обліковим записом, вікно захотіло пароль адміністратора. Я ввів свій. Ми пограли хвилин десять, а тоді його сесія зникла з моєї гри й не поверталася, доки ми обидва не перезапустили гру.

Наступної сесії все повторилося, і ще раз після неї. Усе, що я знайшов за ті два вечори, було справжнім, я виправив геть усе – а нас однаково викидало.

Перешкода сиділа на два рівні трансляції адрес вище за мою квартиру, у мого інтернет-провайдера, і жодна моя майстерність по цей бік стіни туди не діставала. Кожне з тих виправлень було справжньою роботою над справжнім дефектом, і саме тому їх так легко було вважати поступом. А поступ буває лише один – коли зрушується симптом.

Типові налаштування думають, що за клавіатурою сидить адміністратор

Насамперед я взявся за той запит пароля, і виявилося, що за ним ховаються два окремі дефекти.

Коли відповідаєш на вікно Windows Firewall «do you want to allow», воно записує два правила, і в обох погані типові значення. Воно прив’язує їх лише до профілю Private, а edge traversal виставляє в DeferToApp. Перше важить тому, що Ethernet-інтерфейс на кілька секунд проходить через Public під час кожного завантаження й кожного повторного розпізнавання мережі, і в цей проміжок вхідний трафік до гри відкидається. Друге – тому, що edge traversal і є тим непрошеним вхідним трафіком, на якому тримається hole punching, пробивання NAT для прямого з’єднання між гравцями.

Коли я прочитав журнал подій самого файрвола, вечір нарешті склався в картинку. О 19:46 застосунок Xbox після оновлення заново зареєстрував пакет гри. О 19:55 служба файрвола створила правила з дією block – у такому стані вона тримає їх, поки вікно чекає на відповідь. За 12 секунд мій пароль адміністратора перемкнув їх на allow. А ще за дві години гра окремо попросила edge traversal, і вікно вискочило вдруге.

[тодішній макс]

А на тому самому комп’ютері вже лежав доказ того, чим це закінчується. Там стояли два постійні правила block для viber.exe під обліковим записом іншого члена родини – лишилися з того дня, коли кілька місяців тому те саме вікно просто закрили. Відтоді Viber мовчки не приймав нічого вхідного, і ніхто в родині не пов’язав одне з другим.

що записує вікно і що мало б записати той самий виконуваний файл, той самий комп’ютер
записане у відповідь на запит
  • діє лише в профілі Private, тож якщо завантаження проходить через Public, вхідний трафік відкидається
  • edge traversal лишається на DeferToApp, тож пробивати NAT не дозволено
  • поки вікно чекає на відповідь, правило явно блокує
  • якщо натиснути Cancel, стає постійним block, і жодного запиту вже не буде
  • наступного разу знову потрібен адміністратор, фізично за клавіатурою
написане свідомо, один раз
  • діє в усіх профілях, тож коротке вікно Public нічого не змінює
  • edge traversal дозволено – саме цього потребують прямі з’єднання
  • записано один раз, наперед, а політику файрвола перед тим експортовано
  • закрите вікно йому не страшне, бо вікна більше немає
  • син запускає гру зі свого звичайного облікового запису, і ніхто нікого ні про що не питає

На заміну – два правила, написані один раз: New-NetFirewallRule -Program <the exe> -Profile Any -EdgeTraversalPolicy Allow, одне для TCP, друге для UDP, а перед тим я експортував політику файрвола, щоб було куди відступати. Прив’язати правило до ідентичності пакета було б охайніше, але так не працює: ігри з Game Pass – це пакетні застосунки з повною довірою (full trust) і без AppContainer SID, тож правило, прив’язане до пакета, не ловить жодного їхнього трафіку. Правильна точка опори – шлях до виконуваного файлу, бо застосунок Xbox не змінює кореневу теку встановлення.

Запит більше не з’являвся. Наступного дня нас знову викинуло.

Підрахунок пакетів розсуджує там, де теорії безсилі

Першим я перевірив фізичний рівень, бо минулого разу, не перевіривши його, втратив майже цілу суботу. Мережевий порт на комп’ютері з Windows працював на гігабіті, нуль помилок і нуль відкинутих пакетів, і за 15 днів з’єднання жодного разу не падало. Мій Mac сидів на Wi-Fi через дві кімнати; зі 150 пінгів між ними не загубився жоден.

[див. також]

Тоді я нарешті записав трафік – це варто було зробити ще першого вечора. pktmon входить до складу Windows, вміє фільтрувати за однією адресою, і йому вистачило 12 секунд, щоб покласти край здогадкам. Я запустив його зі свого Mac через SSH, поки ми з сином стояли пліч-о-пліч в одному збереженні, і тільки тому цей замір хоч чогось вартий.

Два різні запитання, а не одне повторене

Журнал локалізований, тож пошук за текстом повідомлення не знаходить нічого, а читання XML – усе. Якщо розшифрувати, Action 2 – це block, а 3 – allow, і видає все процес, який зробив зміну: svchost.exe – це служба файрвола, що діє сама, а dllhost.exe – людина, яка відповідає на вікно. Два записи dllhost з різницею майже у дві години – це два окремі запитання, а не одне нетерпляче повторене.

Попросити той самий комп’ютер показати всі правила, що блокують вхідний трафік, – це один рядок, а у відповідь вилазять правила, на які ніхто в родині не пам’ятає своєї згоди. Два з них місяцями відрізали вхідний Viber в обліковому записі, з якого ніколи не відкривають термінал.

Обидва дефекти були справжні, і обидва я виправив. До наступного вечора на комп’ютері не лишилося жодного правила, що блокує вхідний трафік, і запит більше не з’являвся. Сесія однаково обірвалася.

Одна квартира, один комутатор і жодного ігрового пакета між ними

Два комп’ютери на одному комутаторі, в одній квартирі, а ми з сином стоїмо на тому самому місці в тій самій грі. За 12 секунд вони сказали один одному лише дві речі: широкомовний запит пошуку пристроїв і Syncthing, що оголошував себе в локальній мережі. Гра не передала нічогісінько.

Цей один підрахунок дав більше, ніж усі теорії, які я наплодив за два вечори. Одним вимірюванням він зняв підозру з файрвола, бездротового з’єднання, комутатора й кабелю, бо жодне з них не може пояснити, чому два вузли взагалі не звертаються один до одного. Хоч що там робила гра, робила вона це десь там, в інтернеті.

А годиною раніше я переконав себе, що комп’ютери таки спілкуються, бо таблиця сусідів у Windows три заміри поспіль тримала запис мого Mac у стані reachable. Але то моя ж SSH-сесія підтримувала цей запис живим. Урок копійчаний, а я все одно засвоюю його знову і знову: коли до комп’ютера підключений ти сам, ти теж частина його трафіку.

Адреса, в яку вірить мій роутер, мені не належить

Роутер називав своєю WAN-адресою 100.66.81.157. Цей діапазон, 100.64.0.0/10, зарезервовано рівно для одного: для провайдерів, яким забракло публічних адрес і які ховають абонентів за другим рівнем трансляції. Інтернет бачив мене зовсім під іншою адресою, а traceroute показав між ними проміжний вузол, який відмовляється себе назвати.

Решту розповідають три перевірки з’єднання. Через локальну мережу – усе гаразд. Назовні на WAN-адресу мого роутера й назад – теж гаразд, отже, мій роутер правильно робить hairpin-трансляцію, тобто розвертає назад у локальну мережу пакети, адресовані його ж зовнішній адресі. Назовні на публічну адресу й назад – нічого. Транслятор провайдера не хоче розвертати мої ж пакети й віддавати їх мені.

У цьому й уся несправність. Підбір гравців бачить двох людей, які приходять з однієї публічної адреси, і дає кожному з нас публічну адресу й порт іншого, бо ззовні ми виглядаємо саме так. І ми обидва стукаємо у двері, які відчиняються лише з того боку, де нема жодного з нас.

Тому сесія йде в обхід, через ретранслятор самої Hello Games, і тільки завдяки цьому ми взагалі можемо грати. Але ця сесія тримається на UDP-записі в таблиці трансляції оператора, і коли транслятор перебудовує свою таблицю, запис зникає разом із сесією, і сама вона вже не повертається. Десять хвилин – стільки прожив один такий запис.

Межа того, що можна полагодити, проходить рядком у тарифі

Свою частину роботи мій роутер зробив. Його UPnP-служба тримала для гри активні правила з підписом Microsoft Multiplayer, які спрямовували UDP-порти 3074 і 47601 на комп’ютер із Windows. Усі до одного були декорацією. Порт, відкритий на власному роутері, виявляється відкритим не на тому роутері, якщо над ним стоїть транслятор оператора, і ніщо з мого боку цього транслятора не змінить того, що він робить.

[майбутній макс]

Я пішов шукати публічну адресу для оптоволоконної лінії. Провайдер продає її просто на своєму сайті, як додаткову послугу. З мого облікового запису її не купиш, і абонент на тому самому тарифі одним рядком пояснив на форумі чому: «у комбо-тарифах виділеної IP немає». Коли телебачення, інтернет і мобільний зв’язок зібрали в одну акційну ціну, цю опцію прибрали, в обліковому записі про це ані слова, а щоб її повернути, треба розірвати договір і підписати новий.

Резервна лінія теж сиділа за трансляцією, у звичайному приватному діапазоні. Той провайдер продає публічну адресу приблизно за євро на місяць, і вона з’явилася за кілька хвилин після оплати. WAN-адреса роутера й адреса, яку бачить інтернет, стали одним і тим самим рядком – оце й увесь технічний зміст виправлення.

Жодна інженерія мене б до цього не довела. Це була галочка на чужій сторінці рахунків.

пакет, що з’єднує нас двох обидва рази та сама форма; різниця лише в тому, чия коробка його розвертає
Пакет від «його комп’ютер із Windows» до «мій Mac», обидві машини за тим самим роутером. до: він іде через мій роутер, далі транслятор оператора, і транслятор оператора його зупиняє, тож до іншої машини нічого не доходить. після: він іде через мій роутер, і мій роутер розвертає його назад, тож він доходить до іншої машини. до адреса, яку видають нам обом, належить операторові мій роутер WAN 100.66.81.157, в інтернеті не маршрутизується транслятор оператора тримає публічну адресу назад його не розвертає нічого не доходить його комп’ютер із Windows мій Mac після адреса, яку видають нам обом, – це вже мій роутер мій роутер сам тримає публічну адресу розвертає його, і він доходить його комп’ютер із Windows мій Mac

Та галочка коштувала мені периметра. За транслятором оператора вхідний трафік з інтернету взагалі не міг дістатися моєї локальної мережі, і я свідомо на це спирався: це єдиний захист, який неможливо налаштувати неправильно, бо ти його ніколи й не налаштовував. Маршрутизована адреса кладе цьому край. Сьогодні жоден порт не переадресовано всередину, але припущення в моїх власних нотатках про безпеку писалися по той бік цієї межі, і перечитати їх тепер – справжня робота, а не формальність.

Нова можливість приходить із налаштуваннями того, хто її приніс

На відміну від оптоволоконного провайдера, другий роздає ще й IPv6. Мій роутер місяцями стояв у режимі Native з увімкненим делегуванням префікса, але делегувати було нічого: жодної глобальної адреси на жодному пристрої, жодного маршруту за замовчуванням, а ping6 відповідав no route to host.

Щойно прийшов префікс, роутер почав оголошувати себе кожному пристрою як DNS-сервер для IPv6. А його власний DNS пересилає запити провайдерові. macOS без суперечок бере перший DNS-сервер, який їй дали, тож кожне внутрішнє ім’я в квартирі почало ходити через провайдера й отримувати публічний запис із зірочкою (wildcard), а Pi-hole, який фільтрує рекламу й телеметрію для всіх пристроїв, просто випав із цього шляху. Жодна тривога не спрацювала. Усе спливло, коли телефон не зміг відкрити Home Assistant.

куди пішло внутрішнє ім’я, щойно з’явився префікс п’ять кроків, і кожен працює саме так, як задумано
  1. ● 01
    пристрій
    бере перший DNS-сервер, який йому дали
  2. ● 02
    роутер
    оголосив себе тієї ж години, коли прийшов префікс
  3. – 03
    Pi-hole
    його так і не спитали
  4. ● 04
    провайдер
    куди роутер натомість пересилає запити
  5. ✕ 05
    wildcard-запис
    кожне внутрішнє ім’я – одна публічна відповідь

Першим ділом я вирішив прив’язати оголошення до власних IPv6-адрес Pi-hole. У тому самому рядку, де радив це зробити, я сам позначив, що префікс нестабільний, – і все одно порадив. Префікс за кілька годин переїхав двічі, тож записані мною адреси вмерли ще до кінця вечора. Ризик, який ти назвав, але під який не підлаштував рішення, – це просто ризик, який ти записав.

[макс]

Поки що IPv6 вимкнений. У заводській прошивці цього роутера немає налаштування, яке б не давало йому оголошувати себе, – це задокументована помилка, а не моя неуважність, а от неофіційна збірка прошивки від спільноти такий перемикач має. Але перепрошивати неофіційною збіркою єдину коробку, через яку ходить уся квартира, заради можливості, якою зараз ніщо не користується, – погана угода. IPv6 узагалі вмикали лише заради розумної лампочки, яка не хотіла під’єднуватися, а USB-адаптер Zigbee ще кілька місяців тому зняв цю проблему.

Публічна адреса і стабільний зв’язок живуть на різних дротах

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

Публічна адреса тепер живе на резервній лінії. А це кручена пара, і комутатор, від якого вона залежить, живиться від скромного акумулятора в сусідньому під’їзді, тож у місті з графіками відключень світла ця лінія гасне першою. Тримається якраз оптоволокно. Виходить, що зв’язок, потрібний мені, щоб не падати, і зв’язок, потрібний мені для досяжної адреси, – це два різні дроти, і кожного окремо замало.

Це задача маршрутизації, і побутова прошивка розв’язує не ту її половину. Вона вміє перемикати: коли одна лінія вмирає, весь трафік іде другою. А тут потрібне правило: ігровий комп’ютер виходить в інтернет через лінію з публічною адресою, решта квартири – через оптоволокно, і кожна лінія робить те, заради чого її обрали. Саме власний шлюз дає змогу таке правило записати.

Роутер і досі питає про імена провайдера, а не Pi-hole, тож усе, що звертається до нього як до запасного варіанта, втрачає фільтрацію. Цю перевірку я зробив такою, що лише сповіщає про зміну стану, а не сигналить постійно, бо міркував так: жоден пристрій не використовує роутер як DNS-сервер. А потім знайшов комп’ютер із Windows, який робив саме це через IPv6. Тобто припущення, на якому я збудував перевірку, було хибним уже тоді, коли я її писав.

Коли ми граємо, я перемикаю всю квартиру на резервну лінію просто на комутаторі в шафі, тож обидва комп’ютери опиняються за публічною адресою. Ми грали дві години, і сесія трималася.