Вы дадалі дамен у спіс дазволеных, запыт даходзіць да вашага праграмы, супастаўшчык вяртае дазвол, а старонка ўсё роўна ніколі не загружаецца. У гэты момант большасць пачынае перапісваць супастаўшчык і дадаваць параўнанні з шаблонамі. Паводле майго досведу, супастаўшчык звычайна слушны, а збой знаходзіцца на ўзровень глыбей: у адказе DNS, які вы сінтэзавалі, у маршруце, які вы ўсталявалі, або ў сокеце, які вы выкарысталі для перасылкі запыту. Спіс — гэта простая частка; шлях пакета — вось дзе спісы дазволеных ламаюцца.

Супастаўшчык рэдка бывае прычынай

Першае, што трэба аддзяліць, — гэта заблакаванае ад зламанага. Заблакаванае імя павінна паваліцца хутка і бачна, бо браўзер атрымлівае адказ, што такога імя не існуе, і спыняецца. Зламанае імя вісіць, паўтарае спробы праз IPv6, пераключаецца на іншы транспарт і пакідае вас з круцялкам. Калі вы бачыце круцялак, ваш спіс дазволеных, хутчэй за ўсё, адказвае нечым, з чым кліент не можа нічога зрабіць.

Пусты запіс A — класічная памылка. Адказ NOERROR з нулём адказаў выглядае як слушны адказ, таму stub-рэзалвер яго прымае, браўзер спрабуе зноў, спрабуе AAAA, спрабуе іншы рэзалвер і здаецца значна пазней. Код адказу 3, NXDOMAIN, з паўторам секцыі пытання і скапіяваным ідэнтыфікатарам транзакцыі спыняе размову адразу. Выкарыстоўвайце яго для кожнага імя, ад якога вы свядома адмаўляецеся.

IPv6 заслугоўвае таго ж рашэння, а не пазіцыі па змаўчанні. Калі вы адказваеце NXDOMAIN для A і прапускаеце AAAA, кліент можа дасягнуць заблакаванага імя праз IPv6 і фільтр працячэ. Некаторыя рэалізацыі адказваюць на заблакаваныя запыты AAAA адрасам loopback, каб злучэнне павалілася адразу, а не пераключылася на іншы шлях. Выберыце адну палітыку, ужывіце яе да абодвух тыпаў запісаў і запісвайце ў лог абодва.

Маршрут, які захоплівае ўсё, валодае ўсім

Схема толькі з DNS ніколі не дадае addRoute("0.0.0.0", 0), таму ў інтэрфейс TUN трапляюць толькі запыты, а ўсё астатняе працягвае ісці праз базавую сетку. Гэта бяспечная форма, і яна таксама тлумачыць, чаму некаторыя спісы дазволеных працуюць на Wi-Fi і не працуюць у сотавай сетцы.

У момант, калі існуе маршрут па змаўчанні, кожны паток ваш. Пакет TCP, які прыходзіць на інтэрфейс і не перасылаецца і не атрымлівае адказу, сядзіць у чарзе, пакуль у кліента не скончыцца час, і няма памылкі для запісу, бо нічога не памылілася. Я бачыў, як чалавек выдаткаваў паўдня на зламаны спіс дазволеных, які насамрэч быў адсутным перасыльнікам для порта 443. Запісвайце пратакол і прызначэнне кожнага пакета, які вы вырашылі адкінуць.

Сокет рэзалвера павінен пакінуць тунель

Перасылка — гэта месца наступнай пасткі. Рэзалверы аператара часта жывуць на прыватным адрасе, да якога тунель не дастае, таму перасланы запыт ідзе ў нікуды, і праграма паведамляе пра сканчэнне часу чытання. Адпраўляйце ўхваленыя запыты да рэзалвера, пра які вы ведаеце, што ён даступны, і спачатку перадайце гэты сокет у VpnService.protect(). Незасценены сокет вяртае запыт у ваш уласны тунель, дзе ён зноў даходзіць да праграмы і круціцца, пакуль не спрацуе тайм-аўт.

Збой выглядае гэтак жа, як перапынак сеткі, і таму ён так доўга жыве ў справаздачах пра памылкі. Трымайце лічыльнікі адпраўленых запытаў і атрыманых адказаў: калі першы лік расце, а другі застаецца на нулі, вы глядзіце на сокет, а не на спіс.

Памер і кантрольныя сумы знікаюць бязмоўна

Ціхія скіды таксама бываюць з-за памеру. Адказ DNS з вялікім наборам адказаў або рукапоціск TCP са шчодрымі опцыямі могуць перавысіць MTU шляху, які вы ніколі яўна не задавалі; фрагмент знікае вышэй па плыні, і кліент або паўтарае спробу з меншым памерам, або спыняе спробы. Усталяванне MTU інтэрфейса ў 1280 — гэта асцярожны выбар, які вытрымлівае большасць сотавых шляхоў, і быць яўным лепш, чым атрымаць у спадчыну значэнне па змаўчанні, якое ніхто не мераў.

Калі вы будуеце пакеты самі, кантрольная сума — іншы ціхі забойца. Кантрольная сума UDP, вылічаная па псеўдазагалоўку, які выпускае даўжыню UDP або поле пратакола, дае пакет, што выглядае правільным у вас і адкідваецца атрымальнікам без следу. Параўнайце ваш псеўдазагаловак са спецыфікацыяй поле за полем і падчас адладкі выведзіце вылічаную кантрольную суму для аднаго вядомага патоку.

Што VpnService не зробіць за вас

Дзве межы варта ведаць, перш чым будаваць вакол іх. Ніводная звычайная праграма не можа ўсталяваць сістэмны проксі або файл PAC па-за Wi-Fi, і гэтая частка не змянілася. Шлях для асобных праграм змяніўся: да API 29 VpnService.Builder наогул не мог несці проксі, а з API 29 setHttpProxy(ProxyInfo.buildPacProxy(uri)) перадае платформе скрыпт PAC для ацэнкі для сеткі VPN. Ацэньвайце правілы ў вашым уласным кодзе, калі вы арыентуецеся на старэйшыя API або калі мадэль PAC не можа выразіць правіла. UDP таксама не бясплатны: браўзеры адпраўляюць праз SOCKS-проксі толькі TCP, і большасць кліентаў SOCKS5 ніколі не рэалізуюць UDP ASSOCIATE, таму схема на базе проксі скідвае або працякае UDP, пакуль TCP выглядае здаровым.

Гэтая другая мяжа — прычына, чаму пратакол на базе UDP можа працаваць у звычайнай сетцы і зламацца ў момант, калі падключаецца ваш VPN. Калі тунель павінен несці UDP, перасыльнік мусіць рэалізаваць для яго шлях перасылкі, а не толькі шлях TCP з іншым тыпам сокета.

Правярайце ў такім парадку

Праходзьце спіс па парадку і спыніцеся на першым этапе, які праваліўся, бо кожная наступная праверка — гэта шум, пакуль папярэдняя не вытрымае.

  1. Пералічыце ўсталяваныя маршруты і пацвердзіце, ці трапляюць наогул пакеты не-DNS у інтэрфейс TUN.
  2. Запішыце ў лог імя запыту, рашэнне і код адказу для аднаго заблакаванага і аднаго дазволенага імя.
  3. Пацвердзіце, што сокет рэзалвера засценены і што абраны рэзалвер адказвае знутры тунеля.
  4. Пацвердзіце MTU інтэрфейса і кантрольную суму аднаго адказу, пабудаванага ўручную.
  5. Паўтарыце тую ж старонку на Wi-Fi і ў сотавай сетцы, бо рэзалверы аператара і MTU шляху адрозніваюцца.

Калі ўсе пяць вытрымалі, а старонка ўсё яшчэ вісіць, наступны падазроны — сам перасыльнік: параўнайце захоплены запыт з захопленым адказам і пашукайце адсутную колькасць байтаў або напалову закрыты сокет. Даведка VpnService.Builder апісвае кантракты маршрутаў, DNS і MTU, а protect() — гэта асобны выклік VpnService, а не опцыя будаўніка; падключаны інтэрфейс азначае толькі тое, што першы кантракт выкананы.

Падобныя артыкулы