Соединяю локальные сети через VPS-сервер и Keenetic посредством WireGuard VPN

рассвет, москва, деревья, мгу, мосфильмовскаяСегодня случилось страшное. Мой провайдер MosLine, без каких-либо объявлений или предупреждений сменил мне публичный IPv4 адрес на частный. В результате отключились две важные для меня функции: связь нескольких разрозненных локальных сетей и туннелирование IPv6 (использовался 6in4 вариант туннелирования, когда требуется наличие «белого» IPv4 адреса), поскольку MosLine (вкупе с его дочерней Optic-Inet) так и не научился раздавать своим клиентам IPv6. Собственно, отключение вбило очередной гвоздик в гробик провайдера, так как я уже сейчас могу получить минимум вдвое более быстрый канал через мобильную сеть и вдвое дешевле (см. статью о современных средствах добычи мобильного интернета). И единственные две вещи, которые меня останавливают от перехода на более дешевого альтернативного провайдера, так это необходимость перекраивания внутренней локальной инфраструктуры, а также необходимость инвестирования в новое оборудование. Ну и ping на мобильной сети не такой комфортный, как на оптике. И пока я раздумываю над сменой провайдера, необходимо закрыть хотя бы первую функцию, а именно связать разрозненные локальные сети в единое информационное пространство. Благо, у меня есть несколько VPS-серверов, которые можно оперативно использовать для решения этой проблемы.

Итак, в качестве инфраструктуры у меня используются роутеры, или как говорят англоязычные специалисты «рутеры», Keenetic. Может быть, данные роутеры не самые продвинутые в плане настроек, но они не кушают мозг в процессе эксплуатации (один раз настроил и работает годами), а при самой настройке нет необходимости бегать кругами вокруг роутера, курить трубку и бить в бубен исполняя тотемный танец по призыву коллективного разума с вопросом «а почему не работает». На стороне VPS, как водится, у меня крутится разновидность Linux.

Локальные сети еще издревле соединялись между собой через сети общего пользования посредством VPN-технологии. За десятилетия развития VPN появилось несметное некоторое количество вариантов VPN-протоколов и соответствующего программного обеспечения. Традиционно для VPN используются такие варианты VPN-протоколов, как IPSec/L2TP, PPTP или OpenVPN. Но в последнее время все больше набирает популярность такой протокол для организации VPN как WireGuard. Создатели WireGuard позиционируют свое решение как быстрое, современное и безопасное решение для организации виртуальных частный сетей. И судя по тестам, заявления совсем не беспочвенные. WireGuard работает весьма шустро, кушает очень мало ресурсов и поддерживается актуальными системами (как на Linux, так и на Windows, Android и т. п.), что позволяет соединять вместе различные устройства, работающие под разными операционными системами. Но помимо легковесности и безопасности у WireGuard есть еще одно преимущество, его довольно-таки просто установить и настроить.

В сети существует множество инструкций о том, как установить WireGuard в виде любого сетапа, на любое устройство и для любых целей. Не буду их повторять, но порекомендую, исключительно для облегчения и ускорения процесса, воспользоваться WireGuard installer. Скрипт устанавливает WIreGuard на основные Linux дистрибутивы и позволяет осуществлять простую настройку как сервера, так и облегчает добавление новых пиров к серверу. В принципе, для WireGuard существует около двух десятков установщиков, поэтому не обязательно, особенно если есть силы, использовать указанный выше скрипт-инсталлятор. Вполне можно обойтись другим решением или установить все руками с начала и до конца.

Итак, скачав скрипт, дав ему права и, наконец, запустив wireguard-install.sh, а затем ответив на несколько примитивных вопросов или просто понажимав Enter, можно наконец выдохнуть. По умолчанию, скрипт добавляет одного клиента (пира). Для добавления нового или удаления старых клиентов (пиров) необходимо запустить скрипт еще раз. Ну или отредактировать текстовой конфигурационный файл. Он, как правило, располагается в /etc/wireguard и называется аналогично названию WireGuard интерфейса, обыкновенно это wg0.conf. Данный файл можно редактировать текстовым редактором, однако, для того, чтобы изменения вступили в силу, следует перезапустить WireGuard. Остановка и последующий запуск осуществляются через команду wg-quick [down|up] wg0. Где wg0 как раз название интерфейса/имя конфигурационного файла.

Вообще, в рамках WireGuard нет такого понятия как сервер и клиент. Есть понятие пиры. Так подняв «сервер» на VPS и прописав в нем «клиента» я просто создал возможность для соединения этих устройств. Но никто из них не будет являться сервером, в классическом понимании. Разделение в WireGuard на относительный «сервер» и потенциального «клиента» лишь в том, кто сам пытается соединиться (клиент), а кто просто ожидает соединения (сервер).

При создании клиентов через скрипт, он выводит на экран могучий QR-код, который можно использовать, чтобы подцепить настройки подключения, например, мобильным телефоном. Параллельно настройки клиента складываются в каталог, откуда запускается скрипт, в файл с именем wg0-client-S21.conf. В данном случае в имени зашифровано название интерфейса wg0, и наименование клиента S21. Вся эта же информация копируется и в основной конфигурационный файл wg0.conf (тот, который в /etc/wireguard). Если потребуется внести изменения в конфигурацию, то редактировать нужно именно wg0.conf, так как «клиентские» файлы нужны исключительно для импорта в клиентские инсталляции.

Пробежимся по основному конфигурационному файлу, который сгенерировал для моей инсталляции скрипт. Файл сформирован для интерфейса wg0. Разумеется, все ключи, как приватные, так и публичные, удалены из файла, равно как и публичные IP-адреса.

[Interface]
Address = 10.66.66.1/24,fd42:42:42::1/64
ListenPort = 53569
PrivateKey = Частный ключ 1
PostUp = iptables -A FORWARD -i eth0 -o wg0 -j ACCEPT; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i eth0 -o wg0 -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

### Client Dacha
[Peer]
PublicKey = Публичный ключ 2а
PresharedKey = Совместно используемый ключ 2
AllowedIPs = 10.66.66.2/32,192.168.0.0/24,fd42:42:42::2/128

### Client S21
[Peer]
PublicKey = Публичный ключ 3а
PresharedKey = Совместно используемый ключ 3
AllowedIPs = 10.66.66.3/32,fd42:42:42::3/128

В рассматриваем примере есть три секции, соответственно одна Interface для задания настроек «серверной» части WireGuard для конкретного интерфейса и две секции Peer для «клиентов-пиров». Авторами WireGuard предполагается, что система настолько простая, что никакая документация для нее не нужна. Поэтому ее особо и нет. Однако, не все настолько проницательны и готовы перелопатить 4000 строк исходного кода, чтобы разобраться, что к чему. Поэтому в сети появилась неофициальная документация по WireGuard. Я же попробую вкратце пробежаться по всем приведенным параметрам, с дополнительными комментариями там, где они нужны, так как из-за отсутствия официальной документации иногда не просто сообразить какой параметр куда вставлять, чтоб наконец заработало.

Итак, в секции Interface задаются параметры настроек для «серверной части» WireGuard. В параметре Address перечисляются через запятую внутренние адреса интерфейса в нотации CIDR. Тут следует обратить внимание на то, что используется не только внутренний IP-адрес внутри виртуальной частной сети (VPN) в пространстве IPv4, но и в адресном пространстве IPv6. Обратите внимание, что в обоих случаях /24 и /64 назначается целая подсеть. Для IPv4 в эту подсеть можно уместить до 254 адресов, а для IPv6 их будет уже 18.446.744.073.709.551.616 штук, такова особенность IPv6, адресов там невообразимо много. Еще одно замечание, обе подсети относятся к «частным» пулам адресов. Кстати, Address может быть указан и для единственного адреса, а не для сети. В этом случае никакой маршрутизации по сети, к которой относится указанный адрес, производиться не будет. Следующий параметр ListenPort означает порт, который интерфейс «слушает» и принимает входящие соединения. Если не указать порт, то соответственно никто подключиться к интерфейсу извне не сможет, однако, возможность маршрутизации останется.

PrivateKey – частный ключ, который не сообщается ни одному из пиров. Этот ключ используется только на стороне «сервера». При задании ключей можно обратить внимание, что они все оканчиваются на символ '='.

PostUp и PostDown команды выполняемые после включения и отключения интерфейса соответственно. Здесь указываются именно команды в том виде, в котором они будут переданы интерпретатору операционной системы. Команды могут быть перечислены через точку с запятой или же можно указать несколько параметров PostUp и PostDown. В моем примере скриптом-установщиком сгенерированы команды маршрутизации посредством iptables. Соответственно при «поднятии» интерфейса эти правила применяются, а после отключения удаляются. Таким образом сохраняется стабильность сетевого трафика и сетевые пакеты не будут улетать в неизвестном направлении.

Помимо перечисленных параметров в конфигурационном файле могут применяться и другие параметры. PreUp и PreDown параметры аналогичны PostUp и PostDown, но выполняются перед действием «поднятия» или отключения интерфейса. Параметр DNS применяется для передачи подключаемым пирам адресов DNS-серверов посредством DHCP-протокола. Но обычно, клиенты прописывают DNS-сервера на своей стороне и игнорируют DNS-сервера предлагаемые со стороны сервера. Серверов можно указать несколько, через запятую, равно как и использовать не только IPv4, но и IPv6 адреса.

MTU устанавливает максимальный размер величины единичного пакета или фрейма с данными. Как правило, данный параметр устанавливается автоматически, базируясь на настройках подключаемого пира или уже используемой маршрутизации в системе. При настройке секции Interface можно использовать еще один параметр Table. Он указывает на используемую таблицу маршрутизации в операционной системе, что полезно в случае сложного сетевого окружения на крупных узлах.

При настройке секции Peer в WireGuard присутствует правило хорошего тона: каждую секцию предварять строкой комментария с наименованием пира. Когда пиров или клиентов становится много, то понять кто из них кто становится очень не просто. При генерации пиров через скрип-инсталлятор, он каждую секцию Peer предваряет символами комментария ### и последующим наименованием пира. Несмотря на наименования пиров в файле конфигурации, в самом WireGuard, например, при выводе статистики соединений, эти наименования никак не будут отражаться, что, разумеется, не так удобно. Опознать нужный пир можно только по адресу или же по публичному ключу.

PublicKey – публичный ключ для клиента, данные передаваемые клиенту шифруются этим ключом, следует обратить внимание, что в конфигурационных файлах пиров-клиентов этот ключ другой. PresharedKey – еще один уровень защиты применяемый для шифрования канала. Этот ключ смешивается вместе с парой открытого и закрытого ключей и необходим как последний аргумент в защите зашифрованного канала. Если злоумышленник каким-то образом вытащит приватный ключ, то он все равно не сможет расшифровать поток данных, так как ему потребуется узнать и PresharedKey. Однако, этот параметр опциональный, если его не указать, то «совместно используемый ключ» будет состоять из нулей. Разумеется, PresharedKey должен идентичен на стороне сервера и на стороне клиента.

AllowedIPs – список IP-адресов в CIDR нотации, т.е. это могут быть не только адреса конечных машин, но и сетей. Адрес может быть указан из IPv4 или IPv6 адресного пространства. Этот список определяет адреса, которые будут маршрутизироваться непосредственно в этот пир. При запуске интерфейса выполняется команда добавления маршрута на подобии ip route add …. Параметр довольно-таки важный, особенно важно обратить на него внимание, если требуется маршрутизировать целую сеть, которая находится за устройством пира. В рассматриваемом примере для пира Dacha указано целых три адреса, а именно:

  • 10.66.66.2/32 – адрес машины в подсети создаваемой VPN. 10.66.66.1 это адрес собственно сервера WireGuard, а 10.66.66.2 это адрес роутера Keenetic.
  • 192.168.0.0/24 – адрес сети за пиром (роутером Keenetic), я хочу, чтобы WireGuard сервер прокидывал туда пакеты, которые будут попадать на его интерфейс.
  • fd42:42:42::2/128 – адрес машины в подсети создаваемой VPN, но в адресном пространстве IPv6.

С использованием смекалки и параметра AllowedIPs можно городить весьма странные и запутанные конфигурации для маршрутизирования пакетов. Иногда сообразить руками все пересечения сетей и адресов проблематично, но в этом случае можно воспользоваться специализированными калькуляторами, например, от Pro Custodibus-а.

EndPoint – в настройках сервера он не указан, так как все мои клиенты находятся на «серых», непубличных IPv4 адресах и к ним извне невозможно подключиться. Указывается в виде адрес:порт, допускается использование как доменного имени, так и IPv4 или IPv6 адреса. А поскольку на стороне сервера мы только слушаем, то и параметр PersistentKeepalive, определяющий периодическую проверку соединения в секундах и его переинициализацию в случае потери связи, благополучно отсутствует.

Вот, собственно, и все настройки, которые доступны на сервере. На клиенте, в общем-то доступны все те же настройки, так как в WireGuard нет такого понятия как клиент или сервер, есть только пиры. При добавлении пира через скрипт-инсталлятор на VPS-сервере он не только добавляет его в файл для настройки пира, но и в общий конфигурационный файл интерфейса WireGuard (тот самый wg0.conf). Посмотрим на него повнимательнее (это конфигурация пира Dacha).

[Interface]
PrivateKey = Частный ключ 2
Address = 10.66.66.2/32,fd42:42:42::2/128
DNS = 8.8.8.8,1.1.1.1

[Peer]
PublicKey = Публичный ключ 2б
PresharedKey = Совместно используемый ключ 2
Endpoint = адрес:53569
AllowedIPs = 0.0.0.0/0,::/0

При генерации настроек пира скрипт создает уникальные пары ключей, а именно «Частный ключ 2» и «Публичный ключ 2б». Они нигде не фигурируют в общем конфигурационном файле интерфейса wg0.conf. Более того, сгенерированные файлы настроек пиров можно вообще удалить после импорта настроек в клиентов. Дополнительно следует обратить внимание на то, что «Совместно используемый ключ 2» он одинаков как со стороны настроек клиента, так и со стороны настроек сервера.

В секции Interface присутствует всего три параметра:

  • PrivateKey – содержит частный ключ пира, он отличается от серверного ключа.
  • Address – содержит уникальный в разрезе создаваемой VPN адрес пира. Прошу обратить внимание, что тут указывается именно адрес конкретной машины, роутера, телефона, устройства в общем, а не сети.
  • DNS – те сервера DNS, которые будут использоваться для разрешения мнемонических адресов в цифровые, вполне можно не указывать, особенно, если вы не планируете использовать VPN для выхода в интернет.

В секции Peer уже четыре параметра:

  • PublicKey – публичный ключ. Следует обратить внимание, что этот ключ отличается от ключа в настройках сервера.
  • PresharedKey – совместно используемый ключ для улучшения защиты от угона компрометации ключей шифрования. Здесь он совпадает с тем, что указаны в настройках сервера.
  • EndPoint – публичный адрес и порт сервера, на котором он принимает подключения VPN. Может быть IPv4, IPv6 или мнемоническим адресом, типа vpn.microsoft.ucoz.net.
  • AllowedIPs – действует аналогично серверной настройке. В примере указаны '0.0.0.0/0' и '::/0', что означает, что весь трафик с пира должен быть отправлен в VPN-туннель. Если мы хотим, чтобы по туннелю «бегали» пакеты только к подключенным сетям, а весь трафик в Интернет уходил по обычному пути, то тут следует установить что-то типа '10.66.66.0/24,192.168.78.0/24,192.168.13.0/24' или аналогичное, в зависимости от того, какие частные сети подключены к VPN. Более того, поскольку в качестве основных клиентов у меня выступают Keenetic-и, то там маршрутизация WireGuard работает несколько иным способом и это поле теряет свою актуальность при настройке WireGuard на Keenetic-ах.

В примере выше отсутствует такой важный для клиентской части параметр, как PersistentKeepalive (он описан в серверной части). WireGuard относится к так называемым Stateless (или скорее Connection-less) системам, системам, в данном контексте, которые не беспокоятся о состоянии VPN-канала, не поддерживают его в постоянно подключенном состоянии. Так, подключившись однажды и не передавая никакой трафик, система будет думать, что VPN-канал установлен и находится в полном рабочем состоянии. Даже в статистике WireGuard пир будет обозначен как живой, правда последняя активность на нем была, ну скажем 148 часов тому назад. Вот тут и помогает настройка PersistentKeepalive, которую нужно устанавливать на пире, который будет подключаться к серверу. В нашем случае это Keenetic без публичного IP-адреса. Обычно параметр PersistentKeepalive устанавливают равным нескольким десяткам секунд. Именно с этой периодичностью WireGuard со стороны пира, подключающегося к серверу (по сути, он тоже пир, только сам никуда не подключается), будет проверять работоспособность канала и если она нарушена, то будет инициализировать его восстановление.

С серверной настройкой все сделано, теперь очередь за Keenetic-ом. В современных версиях операционной системы для Кинетиков есть возможность установки дополнительных модулей. Для установки WireGuard необходимо выбрать соответствующий компонент в настройках операционной системы роутера. После чего применить настройки. Компонент скачается и установится.

Следующим шагом будет создание интерфейса подключения к «серверу». Подключения через WireGuard настраиваются и создаются на страничке «Другие подключения» в группе «Интернет». В соответствующей части страницы жмем «Добавить подключение» и тут у нас появляется форма для добавления нового интерфейса и заодно пира (или нескольких) для подключения.

Интерфейс настройки WireGuard на Keenetic

Интерфейс настройки WireGuard на Keenetic

Приведу расшифровку полей интерфейса настройки подключения у Keenetic:

  1. Название интерфейса. Следует сделать его понятным, поскольку в дальнейшем он будет использоваться еще в других местах.
  2. Если поставить галку, то весь трафик с роутера во вне будет уходить в установленный туннель. Для соединения локальных сетей не ставим.
  3. Поле для ввода приватного ключа. Генерировать новую пару не стоит, так как эту работу уже проделал скрипт-инсталлятор. Нужно скопировать «Частный ключ 2» из сгенерированного на сервере файла для данного пира и нажать на кнопку «Установить частный ключ».
  4. Вводим адрес данного устройства в сети VPN. Опять же, берем его с сгенерированного на сервере файла. Обязательно указываем модификатор /32, отображающий, что это конкретное устройство, а не подсеть. Используем только IPv4 адрес, так как WireGuard для Keenetic еще не научился работать с IPv6 (и это печально на самом деле).
  5. Указываем имя пира, к которому роутер будет подключаться для установления связи. Пиров можно задавать несколько, но это имеет смысл, если роутер выступает в качестве сервера.
  6. Указываем «Публичный ключ 2б» из файла.
  7. Указываем «Совместно используемый ключ 2» из файла.
  8. Указываем адрес и порт, к которому подключаемся для создания VPN-туннеля. Параметр Endpoint из файла.
  9. Оставляем как есть 0.0.0.0/0.

Дополнительные параметры настройки подключения: порт прослушивания оставляем пустым, так как мы не планируем получать подключения к Keenetic-у, наоборот, он сам будет подключаться к серверу. DNS сервера можно указать, можно не указывать. Они нужны только в случае, если VPN будет использоваться для выхода в Internet. Размер MTU можно оставить пустым, если, конечно, специально нет задачи его изменить. «Подстройка TCP MSS» оставляем включенной.

В поле «Разрешенные подсети», кроме 0.0.0.0/0 правильнее было бы перечислить все сети из AllowedIPs серверного конфигурационного файла (wg0.conf или аналогичного), но в реализации WireGuard для Keenetic это поле не вызывает включение маршрутизации до этих адресов и сетей при «поднятии» туннеля с сервером. Маршрутизация настраивается отдельно. Об этом ниже.

Если сейчас все сохранить и включить ползунком подключение к серверу VPN, то все подключится. Вот только работать не будет. Для включения полной работоспособности нужно настроить «Межсетевой экран» и маршрутизацию.

Настройка межсетевого интерфейса на Keenetic для VPN

Настройка межсетевого интерфейса

Настройка межсетевого экрана осуществляется просто, достаточно разрешить все действия для всех адресов источника и назначения для протокола IP и включить правило на созданном интерфейсе. Можно правила усложнить, фильтровать адреса, перебирать протоколы и так далее.

Настройка маршрутизации на Keenetic

Настройка маршрутизации на Keenetic

Следующим этапом необходимо включить маршрутизацию пакетов к удаленным сетям. Так как у нас не планируется пускать весь трафик через VPN, то следует определиться, к каким сетям следует включить маршрутизацию. В рассматриваемом сетапе необходимо включить маршрут к самой сети VPN, а именно 10.66.66.0/24. Иначе, даже ping работать не будет. Роутер получит ICMP-запрос на ping, обработает его, но ответный пакет отправит не через VPN, а по маршруту по умолчанию, т.е. провайдеру. При задании маршрута адрес сети/устройства можно указывать в формате CIDR, можно только традиционным путем с указанием отдельной маски. Адрес шлюза указывать нет необходимости, так как мы выбираем целиком интерфейс, созданный для подключения к WireGuard VPN. Галочка «Добавлять автоматически» делает ровно то, что делает PostUp/PostDown на сервере: если интерфейс включен, то включается маршрут, если он отключен, то маршрут аналогично отключается.

В приведенном примере в качестве пиров-клиентов у меня указан только смартфон и один роутер Keenetic. В действительности пиров-Keenetic-ов с локальными сетями за ними несколько больше. И на каждом из них следует прописать отдельный маршрут к удаленной сети с прохождением через настроенный WireGuard интерфейс. Иначе роутер не будет отправлять пакеты по VPN, хотя все сети к этой сети подключены. При изменении настроек файрволла (межсетевого экрана) и маршрутизации необходимо учитывать, что на кинетиках данные настройки иногда не включаются моментально, а им требуется некоторое время, прежде чем они заработают.

Как проверять соединение? Самыми обычными средствами, а именно посредством ping и traceroute (tracert). Пинговать следует как со стороны сервера, так и со стороны клиента. Для начала пингуются адреса сервера и клиента в локальной сети VPN-а, в нашем случае это 10.66.66.1 и 10.66.66.2. Затем пингуются устройства, находящиеся внутри подключаемой локальной сети, начать можно с адреса роутера в этой локальной сети, в нашем случае это 192.168.0.1. В сложных случаях понять, что не так, может помочь трассировка, тогда становится понятно, где проблема, если пакет, вместо того чтобы двигаться в туннель, вдруг уходит провайдеру интернета. Одной из интересных и часто встречающихся проблем является ошибка ping: sendmsg: Destination address required. Возникает она, как правило, при забывчивости настройки AllowedIPs на стороне сервера для конкретных клиентов.

Насколько сильно WireGuard грузит сервер? Вопрос очень интересный. Разрабатывался WireGuard не только как простой в использовании инструмент для создания VPN, но еще и весьма быстрое, не требовательное к ресурсам решение. Но, а как оно в реальных условиях? На двухпроцессорном VPS нагрузка при копировании файла между двумя пирами на скорости 80 Мбит составляла порядка 10%. Дополнительный расход памяти на работу WireGuard при активных сетевых операциях зафиксировать не удалось. Другими словами, нагрузка на процессор есть, но она минимальна, тем более что в реальности трафик через VPN не настолько велик и тем более, не постоянен.

Что означает «Последнее рукопожатие» в интерфейсе WireGuard на Keenetic? WireGuard VPN для своей работы использует протокол UPD, в отличии от TCP, в нем не гарантирована доставка пакетов от одного адресата до другого. Пакеты могут не доходить, могут теряться, могут доходить разными маршрутами и, как следствие, в неверном порядке. Все это ведет к тому, что нарушается целостность VPN-соединения. WireGuard автоматически исправит эти нарушения, но ситуация может потребовать переустановления связи. Более того, при нормальной работе, когда не нарушается обмен пакетами, пиры в автоматическом режиме через случайные промежутки времени обмениваются новыми парами ключей шифрования. Делается это специально для усложнения расшифровки зашифрованного потока данных. Обе эти операции приводят к сбросу счетчика последнего рукопожатия.

PS. Кстати, в мире существует еще одно интересное решение для организации VPN в сложных условиях, например, когда нет административных прав на сервере или требуется проходить через довольно строгие NAT и FireWall. Имя ему SoftEther VPN, но для решения моей задачи он излишне тяжеловат.



Соединяю локальные сети через VPS-сервер и Keenetic посредством WireGuard VPN: Один комментарий

  1. Александр

    Шикарная статья, спасибо. Все, вплоть до диагностики сети, было полезным. Еще много времени съел файрволл windows, файрволл антивируса, кое-где шлюз не прописан был

Добавить комментарий