Прямой VPN-туннель между двумя компьютерами находящимися за NAT провайдеров с использованием UDP hole punching
Статья о том, как мне удалось организовать прямой (точка-точка) VPN-туннель между двумя компьютерами, каждый из которых находился за NAT’ом провайдеров, при помощи VPS и простых скриптов, используя стандартные утилиты Linux, без каких-либо настроек сетевого оборудования.
Введение

Существует множество программ (TeamViewer, Hamachi) для удаленного управления компьютером, передачи данных и т.п. Работают они на удивление хорошо и в любых условиях. Но как правило это платные сервисы. Как устроены эти программы неизвестно, да и особого желания их использовать они у меня не вызывают. Я как пользователь ОС Linux (в основном Ubuntu) использовал для передачи данных и управлением своими ПК связку из OpenVPN, SSH, VNC, RDP и прочие сервисы в зависимости от потребности. Для того чтобы организовать сеть между двух компьютеров я использовал VPN-сервер, что бы эти компьютеры подключались к OpenVPN серверу и весь трафик шел через сервер. Это не совсем хорошо, ведь трафик проходит двойной путь, в следствии этого терялась скорость.
Классическая схема организации VPN-туннелей и передачи данных между узлами через сервер
Теория
Я давно задумался о решении по организации канала передачи данных непосредственно от узла к узлу, которые находятся за NATом провайдеров, без использования серверов-посредников. Перебрав некоторое количество статей о различных технологиях типа GRE-туннелей, IPsec, UDP Hole Punching, OpenVPN и прочего, я понял, что узлы должны пробивать соединение навстречу друг другу, то есть посылать пакеты на IP и порт удаленного узла. Поставил несколько опытов по организации GRE-туннеля через NAT, передачу сообщения при помощи NetCat навстречу друг другу, иногда это работало, иногда нет, всё зависело от типа используемого провайдером NAT. Не так давно попалась на глаза интересная статья, в которой было описание организации работы OpenVPN соединения между двумя компьютерами (далее узлами). Я прочитал, проверил и заработало, но при условии, что локальный порт узла и внешний порт будут совпадать, то есть мой провайдер будет использовать Cone NAT. Мне же стало интересно организовать туннель между двумя компьютерами при условии, что оба будут находятся за любым типом (Cone или Symmetric) NAT, то есть локальный порт может не совпадать с внешним портом. Задача уперлась в невозможность определения текущего порта внешнего интерфейса без внешней помощи. Если внешний IP-адрес хоть как-то можно узнать (например: curl ifconfig.me), а вот с определением текущего внешнего порта возникла трудность.
Практика
Для решения этой задачи пришлось использовать VPS (S-синий овал), на нем я поднял скрипт который выполнял роль «Соединителя», что-то типа STUN-сервера: при помощи утилиты TCPDump получал UDP-пакет (далее везде используется UDP протокол) на определенный интерфейс и порт, парсил содержимое пакета, определял IP-адрес/порт источника и отвечал утилитой NetCat возвращая текущие параметры (IP-адрес и порт) соединения, а так же параметры (IP-адрес и порт) удаленного узла к которому нужно подключиться, если эти данные были доступны, иначе ждал пока они не появятся. Все это дело сопоставлялось с идентификатором (ID) соединения, так как несколько соединений могли мешать друг другу, при использовании ID все решалось. Также была проблема того, что узел получал свои же старые данные и пытался по ним подключиться и это решилось с помощью хеша Hostname.


На узлах A и B я использовал скрипт и сгенерированный заранее ключ для авторизации VPN-соединения, работало это так: запускался скрипт, случайно выбирался локальный порт в диапазоне от 20000 до 65000 и с этого порта отправлялся пакет на VPS, который содержал в себе ID соединения и хеш hostname, с помощью утилиты NetCat и тут же запускался TCPDump ожидая ответа. В ответ приходил пакет который содержал в себе текущие данные (IP-адрес/порт) этого узла, а при наличие данных удаленного узла, они тоже приходили и начинался обмен приветствиями между узлами. Если же данных удаленного узла не было, то опрос повторялся с периодичностью 30-45 секунд, для поддержания сессии. В момент когда все необходимые данные (IP-адрес и порт текущего узла и удаленного) были на узлах, начинался обмен пакетами, пакет содержал в себе число m=0 и сгенерированное число от 0 до 254 (это число использовалось для генерации внутреннего IP-адреса VPN-соединения). Удаленный узел получив пакет с m=0 отправлял в ответ m=1 и так далее до 10. При получении пакета m=10 инициировалась посылка пачки пакетов с периодичность в 1 секунду с m=13 и запуск OpenVPN, удаленный узел получив m=13 тоже запускал OpenVPN используя локальный порт, IP-адрес и порт удаленного узла, а также сгенерированный внутренний IP вида 10.X.X./30.
Схема прямого VPN-туннеля и передачи данных между узлами, без участия сервера
Внимание: скрипты написаны и проверены на ОС Ubuntu 18.04 и Debian 9
Скрипт на VPS:
#!/bin/bash if [[ $1 == '' ]]; then echo -e "Укажите номер порта который нужно слушать"; exit; fi iface=`ip route get 8.8.8.8 | head -n 1 | sed 's|.*dev ||' | awk ''` a=0 until (( $a == 500)); do packet=`tcpdump -i $iface udp port $1 -vvn -c1 -A` if [[ "$packet" == *"Ident"* ]]; then pack=`echo "$packet" | grep -e "udp sum ok" -e "Ident"` myip=`echo $pack | sed 's/\./ /g' | awk ''` myport=`echo $pack | sed 's/\./ /g' | awk ''` id=`echo $pack | sed 's|.*Ident:||' | awk ''` myname=`echo $pack | sed 's|.*Ident:||' | awk ''` echo "$myip:$myport $myname" > /tmp/vpn2-$id-$myname echo "MyData $myip:$myport $(cat /tmp/vpn2-$id-* | grep -v $myname | awk )" | nc $myip $myport -u -p $1 -w 1 cat /tmp/vpn2-$id-* topoint=`cat /tmp/vpn2-$id-* | grep -v "$myname" | sed 's/:/ /g'` if [[ $topoint != '' ]]; then ip=`echo $topoint | awk ''` port=`echo $topoint | awk ''` echo "MyData $ip:$port $(cat /tmp/vpn2-$id-* | grep $myname | awk )" | nc $ip $port -u -p $1 -w 1 fi fi done
Запускается автоматически строкой в /etc/rc.local
#!/bin/bash nohup /путь-до-скрипта/connector2.sh 13013 > /var/log/connector2.log & exit
где 13013 — это порт который нужно слушать, /var/log/connector2.log — лог.
Скрипт на узлах: # cat vpn7.sh
#!/bin/bash ######################## Задаем цветной текст ### WARN='\033[37;1;41m' # END='\033[0m' # RED='\033[0;31m' # $ # GREEN='\033[0;32m' # $ # ################################################# ####################### Проверяем наличие необходымих приложений ######################################################### al="ip echo readlink dirname ps grep awk kill md5sum shuf nc curl sleep openvpn tcpdump cat" ch=0 for i in $al; do which $i > /dev/null || echo -e "$Для работы необходим $i $"; which $i > /dev/null || ch=1; done if (( $ch > 0 )); then echo -e "$Ой, отсутствуют необходимые для корректной работы приложения$"; exit; fi ####################################################################################################################### if [[ $1 == '' ]]; then echo -e "$Введите идентификатор соединения (любое уникальное слово, должно быть одинаковое с двух сторон!) $ \t $Для запуска в автоматическом режиме при включении компьютера можно прописать в /etc/rc.local строку nohup //vpn7.sh > /var/log/vpn7.log 2>/dev/hull & $"; exit; fi ABSOLUTE_FILENAME=`readlink -f "$0"` # полный путь до скрипта DIR=`dirname "$ABSOLUTE_FILENAME"` # каталог в котором лежит скрипт ############################### Проверка наличия и загрузка конфигурационного файла ################################## cfg="$DIR/vpn.cfg" if [[ -f "$cfg" ]]; then echo "$(date) Загружаю конфигурационный файл $cfg" source "$cfg" else echo "$(date) Конфигурационный файл не обнаружен!" fi ############################### Проверка наличия секретного ключа ################################## key="$DIR/secret.key" if [ ! -f "$key" ]; then echo -e "$Секретный ключ VPN-соединения не найден, для генерации ключа выполните: \ openvpn --genkey --secret secret.key Внимание: ключ используется для авторизации и должен \ быть одинаковым с двух сторон. $ # ls -l secret.key -rw------- 1 root root 637 ноя 27 11:12 secret.key # chmod 600 secret.key"; exit; fi ######################################################################################### localport=`shuf -i 20000-65000 -n 1` # Выбор локального порта name=`uname -n | md5sum | awk ''` # Имя узла ipsrv="45.141.103.45" # IP-адрес сервера получения данных о второй стороне portsrv="13013" ############################### Запуск цикла ########### until [[ $count > 100 ]]; do ######################################################################################### until [[ -n "$iftosrv" ]]; do echo "$(date) Определяю сетевой интерфейс"; iftosrv=`ip route get $ipsrv | head -n 1 | sed 's|.*dev ||' | awk ''`; sleep 5; done # Определение интерфейса netcattosrv="nc -u $ipsrv $portsrv -p $localport -w 1" # Команда посылки пакета NC tcpdumptosrv="tcpdump -i $iftosrv udp and src port $portsrv and src $ipsrv and dst port $localport -n -c1 -A" # Команда приема пакета id=`echo $1| md5sum | awk ''` # Преобразеум имя узла в md5 что бы не светить реальное имя ##################### Получение данных о себе и удаленного узла ################################### echo -e "$(date) $Фаза 1 - Получение данных с сервера $ipsrv:$portsrv $" echo -e "$(date) $Использую интерфейс $iftosrv и локальный порт $localport $" until [[ -n "$ip" && -n "$port" ]]; do if [[ -z "$data" ]]; then sleep 1 && echo "Ident: $id $name" | $netcattosrv > /dev/null & sleep 4 && pid=`ps xa | grep "$tcpdumptosrv" | grep -v grep | awk ''` && if [[ -n $pid ]]; then kill $pid; echo "$(date) Нет ответа от сервера, пробую еще раз. "; fi & data=`$tcpdumptosrv` sleep 2 fi if [[ -n "$data" ]]; then #echo "Ответ: $data" data=`echo "$data" | grep "MyData" | sed 's|.*MyData ||' | sed 's/:/ /g'` myip=`echo "$data" | awk ''` myport=`echo "$data" | awk ''` ip=`echo "$data" | awk ''` port=`echo "$data" | awk ''` data='' if [[ -z $tst ]]; then echo -e "$(date) $Мой внешний IP: $myip и порт: $myport $"; fi if [[ -n $localport && -n $myport && -z $tst ]];then if [[ $localport == $myport ]]; then echo -e "$(date) $Мой локальный порт $localport и внешний порт $myport одиноковые, используется CONE NAT $"; tst=1 else echo -e "$(date) $Мой локальный порт $localport и внешний порт $myport разные, используется SYMMETRIC NAT $"; tst=1 fi fi fi if [[ -n "$ip" && -n "$port" ]]; then echo -e "$(date) $Получил данные об удаленном узле: IP: $ip Порт: $port, переходим на следующий этап. $"; else sleep=`shuf -i 30-45 -n 1`; echo -e "$(date) $Нет данных удаленного узла, возможно он еще не вышел на связь, ожидаю данных $sleep секунд и проверяю еще раз. $"; sleep $sleep && pid=`ps xa | grep "$tcpdumptosrv" | grep -v grep | awk ''` && if [[ -n $pid ]]; then kill $pid; fi & data=`$tcpdumptosrv` fi done ###################### Организация соединения с удаленным узлом iftopeer=`ip route get "$ip" | head -n 1 | sed 's|.*dev ||' | awk ''` echo -e "$(date) $Фаза 2 - Установка соединения с удаленным узлом $ip:$port$" echo -e "$(date) $Попытка установки соединения: $myip:$myport -> $ip:$port $" m=0 t=0 connect=0 until (( $connect >= 10 )); do if [ -z "$oktet" ]; then echo "$(date) Октета нет, генерирую и сохраняю в $cfg" oktet=`shuf -i 0-254 -n 1` echo "oktet=$oktet" >> $cfg fi netcattopeer="nc -u $ip $port -p $localport -w 1" tcpdumptopeer="tcpdump -i $iftopeer udp and port $localport and src "$ip" -n -c1 -A" until (( $m >= 10 )); do for w in ; do for pid1nc in `ps xa | grep "$netcattopeer" | grep -v grep | awk ''`;do kill $pid1nc; done; echo "445Hi: $m $oktet" | $netcattopeer > /dev/null & sleep 1 for pidnc in `ps xa | grep "$netcattopeer" | grep -v grep | awk ''`;do kill $pidnc; done done & sleep 4 && pid=`ps xa | grep "$tcpdumptopeer" | grep -v grep | awk ''` && sleep 10 && if [[ -n $pid ]]; then kill $pid && echo -e "$(date) $ Нет ответа от пира, пробую еще раз. $"; fi & peer=`$tcpdumptopeer` if [[ -n $peer ]]; then newport=`echo "$peer" | grep " IP " | sed "s|.* $ip.||" | awk ''` if (( $newport != $port )); then echo -e "$(date) $Порт изменился $port -> $newport $"; port=$newport; netcattopeer="nc -u $ip $port -p $localport -w 1" fi mm=`echo "$peer" | grep "445Hi: " | sed 's|.*445Hi: ||' | awk ''` echo -e "$(date) $ Получил: $mm - передаю: $mm+1 $" if (( $m <= $mm )); then m=$(( $mm + 1 )); fi text=`echo "$peer" | grep "445Hi: " | sed 's|.*445Hi: ||' | awk ''` else (( t++ )) echo -e "$(date) $ Данных нет $t раз $" if (( $t > 5 ));then echo -e "$(date) $ Превышен интервал ожидания, переподключаюсь $"; m=10; connect=1012; ip=''; port=''; fi fi done if (( $connect < 1012 )); then echo -e "$(date) $Значение: $m $" if [[ -n $endoktet ]]; then echo "$(date) Обнаружен конечный октет = $endoktet" if [[ $endoktet == 1 ]]; then ipaddress="10.$text.$oktet.1" else ipaddress="10.$oktet.$text.2" fi else echo "$(date) Не обнаружен конечный октет, генерирую и сохраняю в $cfg" if [[ $port > $myport ]]; then ipaddress="10.$text.$oktet.1" echo "endoktet=1" >> $cfg else ipaddress="10.$oktet.$text.2" echo "endoktet=2" >> $cfg fi fi m=12 for w in ; do for pid2nc in `ps xa | grep "$netcattopeer" | grep -v grep | awk ''`;do kill $pid2nc; done; echo "445Hi: $m $oktet" | $netcattopeer > /dev/null; sleep 0.5; done for pidnc in `ps xa | grep "$netcattopeer" | grep -v grep | awk ''`; do kill $pidnc && echo -e "$(date) $Завершен процесс $pidnc (NetCat) для освобождения порта $localport$"; done rpfilter=`cat /proc/sys/net/ipv4/conf/all/rp_filter` if [[ $rpfilter == 1 ]]; then echo -e "$(date) $rp_filter=$rpfilter - активна защита от подмены адресов (спуфинга)$"; else echo -e "$(date) $Внимение, rp_filter=$rpfilter! Включаю (sysctl -w net.ipv4.conf.all.rp_filter=1) «строгий режим» проверки для защиты от подмены адресов (спуфинга) $"; sysctl -w net.ipv4.conf.all.rp_filter=1 fi echo -e "$(date) $ Запускаюсь. IP-адрес: $ipaddress. $" $(which lsmod) | grep tun || $(which modprobe) tun openvpn --remote $ip --rport $port --lport $localport \ --proto udp --dev tap --float --auth-nocache --verb 3 --mute 20 \ --ifconfig "$ipaddress" 255.255.255.252 \ --secret "$DIR/secret.key" \ --auth SHA256 --cipher AES-256-CBC \ --ncp-disable --ping 10 --ping-exit 40 \ --comp-lzo yes echo -e "$(date) $ Соединение прервано. $" m=0 t=0 (( connect++ )); fi done done
Скопировать скрипт в буфер и вставить в тектовый редактор, например:
# nano vpn7.sh
Сделать скрипт исполняемым:
# chmod +x vpn7.sh
Для первого запуска сгенерируем ключ авторизации secret.key, на удаленной стороне генерировать не надо, нужно скопировать его:
# openvpn --genkey --secret secret.key
Запустим скрипт, например так:
# ./vpn7.sh 517vA0051smB4dE
Ключ 517vA0051smB4dE сгенерировал на strongpasswordgenerator.com
Запускается автоматически строкой в /etc/rc.local
#!/bin/bash nohup /путь-до-скрипта/vpn7.sh >/var/log/vpn7.log 2>/dev/hull & exit
где ID-соединения — это любая уникальная фраза для вашего соединения, /var/log/vpn7.log — лог соединения, ipsrv=«45.141.103.45» — IP-адрес узла где запущен connector2.sh (первый скрипт).
Если все настроено правильно, то будет работать как часы: включил и через пару минут у тебя есть связь с удаленным узлом. В скриптах используются бесконечные циклы и временные задержки, то есть скрипт работает пока включен узел и при потере связи будет пытаться восстановить её. Скрипты не идеальные но, сам факт того что эта технология работает дает мне массу новых идей, например:
- использовать узел для хранения особо важных данных, и иметь к ним доступ, допустим, в случае утери ноутбука все данные будут на узле
- использовать на ноутбуке удаленный рабочий стол компьютера
- организовать связи с компьютером друга и поиграть в сетевую игру
- иметь доступ к домашней камере видеонаблюдения с рабочего компьютера или просмотреть веб-камеру ноутбука
- простота в настройке и использовании
- трафик идет напрямую
- трафик шифруется и защищен от перехвата
- нет необходимости пробрасывать порты
- скрипт запускается автоматически
- главный недостаток это использования VPS как источника данных для соединения, но я думаю над этим
- некоторые провайдеры блокируют трафик между другими провайдерами (замечено у сотовых операторов)
- при использовании с обоих сторон одного провадера может не сработать, зависит от типа NAT
- при использовании провадером «жесткого» NAT может не сработать
Думаю на фоне дефицита белых IPv4 адресов моё решение будет актуально, ровно до тех пор, пока в каждый дом не придет IPv6.
- команда активации защиты от подмены адресов, уязвимость CVE-2019-14899
- команды завершающие зависшие процессы NC, ускоряется процесс установки соединения
- внутренние IP-адреса генерируются при первом запуске и их составляющие хранятся в vpn.cfg
Другая моя реализация VPN-туннеля, без использования VPS, с использованием STUN и Яндекс.Диска опубликована тут
- udp hole punching
- openvpn
- vpn over NAT
- Сетевые технологии
- Разработка для интернета вещей
Развертывание VPN-сети
Интернет прочно вошел в нашу жизнь, и если ранее, в годы господства аналоговых модемов, для выхода в Интернет приходилось учитывать и объем трафика, и время соединения, то сегодня нормой стало безлимитное подключение к Интернету. То есть если Интернета нет в любое время и в любом «объеме», то это уже что-то из ряда вон выходящее. Причем если раньше наличие безлимитного Интернета считалось стандартом де-факто для корпоративных сетей, то сегодня это уже стало нормой для конечных пользователей. Вместе с развитием Интернета меняется и концептуальная модель его использования. Появляются все новые сервисы, например видео по запросу и VoIP, развиваются пиринговые файлообменные сети (BitTorrent) и пр. В последнее время очень популярной стала организация виртуальных частных сетей (VPN) через Интернет с возможностью организации удаленного доступа к любому компьютеру в составе этой сети. О том, как это можно сделать, и пойдет речь в настоящей статье.
Зачем это нужно
Организация VPN-сетей через Интернет или внутри локальной сети имеет много сценариев использования: сетевые игры в Интернете в обход игровых серверов (точно так же, как игры по локальной сети), создание закрытой от посторонних сети для передачи конфиденциальной информации, возможность удаленного и безопасного управления компьютерами (полный контроль над удаленным ПК), организация защищенного доступа для сотрудников, находящихся в командировке, к ресурсам корпоративной сети, связь по виртуальной сети отдельных офисов (локальных сетей).
Традиционный подход к развертыванию такой виртуальной частной сети заключается в том, что в корпоративной сети поднимается и конфигурируется VPN-сервер (обычно на базе ОС Linux) и удаленные пользователи заходят в корпоративную сеть по VPN-соединениям.
Однако такой подход неприменим в случае, когда пользователю необходимо получить удаленный доступ к своему домашнему компьютеру. Вряд ли ситуацию, когда дома поднимается отдельный VPN-сервер, можно считать обычной. Впрочем, не стоит отчаиваться. Задача создания VPN-сети решаема и под силу даже начинающему пользователю. Для этой цели существует специальная программа Hamachi, которую можно свободно скачать из Интернета (http://www.hamachi.cc/download/list.php). Что особенно радует, так это наличие ее русифицированной версии, так что освоить программу сможет любой пользователь.
Hamachi 1.0.2.2
Итак, Hamachi (текущая версия — 1.0.2.2) — это программа, позволяющая создать виртуальную частную сеть (VPN) через Интернет и объединить в ней несколько компьютеров. После создания такой сети пользователи могут устанавливать VPN-сессии между собой и работать в этой сети точно так же, как в обычной локальной (LAN) сети с возможностью обмена файлами, удаленного администрирования компьютеров и т.д. Преимущество VPN-сети заключается в том, что она полностью защищена от несанкционированного вмешательства и невидима из Интернета, хотя и существует в нем.
Программа Hamachi должна быть установлена на всех компьютерах, которые предполагается объединить в виртуальную частную сеть.
Виртуальная сеть создается с помощью специализированного сервера Hamachi в Интернете. Для соединения с этим сервером используются порты 12975 и 32976. Первый порт (12975) применяется только для установки соединения, а второй — во время работы. Впрочем, обычным пользователям вряд ли потребуется столь подробная информация.
После того как с помощью сервера Hamachi создается виртуальная сеть между выбранными компьютерами, обмен информацией между клиентами VPN-сети происходит уже напрямую, то есть без участия сервера Hamachi. Для обмена данными между клиентами VPN-сети используется протокол UDP.
Установка программы
Программа Hamachi устанавливается на компьютеры с операционной системой Windows 2000/XP/2003/Vista. Существуют также консольные версии программы для Linux и Mac OS X. Далее мы рассмотрим установку и настройку программы на примере операционной системы Windows XP.
Установка программы Hamachi достаточно проста и не вызывает проблем (особенно учитывая, что интерфейс запускаемого мастера установки русский). После начала установки программы на компьютере запускается мастер установки, который предложит согласиться с лицензионным соглашением, выбрать папку для установки программы (рис. 1), создать иконку на рабочем столе и т.д.
Среди полезных опциональных возможностей, которые можно активировать в процессе установки программы, — автоматический запуск Hamachi при загрузке компьютера и блокирование уязвимых служб для соединений Hamachi (рис. 2). В последнем случае будет заблокирована служба Windows File Sharing для виртуального сетевого адаптера Hamachi. В результате другие пользователи VPN-сети не получат доступа к имеющимся в вашем компьютере файлам и папкам, открытым для совместного использования. При этом данные файлы и папки останутся доступными для обычных пользователей локальной сети, для соединения с которыми не применяется VPN-соединение.

Рис. 1. Мастер установки программы Hamachi позволяет указать папку
для размещения программы, создать иконку на рабочем столе
и выбрать опциональную возможность автоматического запуска программы
при загрузке компьютера
Кроме блокирования службы Windows File Sharing, блокирование уязвимых служб для соединений Hamachi также приводит к блокированию удаленного доступа к определенным службам Windows, которые часто подвергаются атакам. Соответственно если вы используете программу Hamachi для соединения с надежными клиентами, которым вы доверяете, то опцию блокирования уязвимых служб лучше отключить.

Рис. 2. Мастер установки программы Hamachi позволяет заблокировать
уязвимые службы для соединений Hamachi
На последнем этапе мастер установки предложит выбрать, какой вариант программы установить: базовую версию или Premium. Программа Hamachi существует в двух версиях. Базовая версия является бесплатной, а версия Premium, обладающая более широкими возможностями, — платной. Отметим, что для большинства пользователей вполне достаточно бесплатной базовой версии программы (о детальных отличиях базовой версии от версии Premium мы расскажем чуть позже), но стандартный поход следующий: сначала устанавливается Premium-версия на 45 дней (бесплатно), а по истечении этого периода автоматически происходит переход к базовой версии.
После установки и запуска программы Hamachi на компьютере в том случае, если программа устанавливалась впервые, запустится краткий путеводитель по Hamachi, в котором описывается, как работать с программой.
Первый запуск программы
При первом запуске программы будет создана ваша учетная запись. На этом этапе необходимо задать имя компьютера, под которым он будет виден другим пользователям VPN-сети (рис. 3).

Рис. 3. Задание имени компьютера, под которым
он будет виден другим пользователям VPN-сети
Когда имя компьютера задано, программа устанавливает соединение с сервером базы данных Hamachi и запрашивает IP-адрес, который будет присвоен виртуальному сетевому адаптеру Hamachi и будет использоваться в дальнейшем для установления VPN-соединения. Каждому клиенту Hamachi присваивается IP-адрес из диапазона 5.0.0.0/8 (маска подсети 255.0.0.0), который в принципе не относится к зарезервированным для применения в Интернете диапазонам адресов. К таким зарезервированным для частного использования в локальных сетях относятся следующие диапазоны: 10.0.0.0/8 (диапазон от 10.0.0.0 до 10.255.255.254), 172.16.0.0/12 (диапазон от 172.16.0.0 до 172.31.255.254) и 192.168.0.0/16 (диапазон от 192.168.0.0 до 192.168.255.254). Однако диапазон 5.0.0.0/8 на протяжении уже более 10 лет зарезервирован организацией IANA (Internet Assigned Numbers Authority — американская организация, управляющая пространствами IP-адресов) и не используется в качестве публичных (внешних) адресов Интернета. Таким образом, диапазон 5.0.0.0/8, с одной стороны, относится к диапазону внешних (публичных) адресов Интернета, то есть исключена вероятность, что присвоенный вам IP-адрес уже применяется в вашей локальной сети (в локальных сетях используются только зарезервированные для частного применения IP-адреса), а с другой — эти адреса еще никем не заняты.
После присвоения вам IP-адреса из диапазона 5.0.0.0/8 он становится своеобразным идентификатором вашего компьютера в виртуальной частной сети. Этот IP-адрес присваивается виртуальному сетевому адаптеру Hamachi. Так, если набрать в командной строке команду ipconfig/all, то кроме настроек сетевого интерфейса реального сетевого адаптера (который физически присутствует в вашем ПК) можно обнаружить, что появился еще один виртуальный Ethernet-адаптер Hamachi с присвоенными ему MAC-адресом, IP-адресом, маской подсети, IP-адресом шлюза и т.д. (рис. 4).
Рис. 4. После первого запуска программы виртуальному сетевому адаптеру
Hamachi присваивается IP-адрес из диапазона 5.0.0.0/8 и производится настройка
сетевого интерфейса
Итак, после того как программа Hamachi сконфигурировала виртуальный сетевой адаптер, можно приступать к работе с программой.
На этом этапе ваш компьютер еще не является членом какой-либо виртуальной частной сети, поэтому первым делом нужно подключиться к уже существующей виртуальной частной сети или создать новую VPN-сеть.
Работа с программой
Интерфейс программы очень прост (рис. 5). Имеется всего три функциональных кнопки: «включить/выключить», кнопка сетевого меню и кнопка системного меню.
Рис. 5. Интерфейс программы
Hamachi очень простой —
всего три функциональные кнопки
Для создания новой VPN-сети или присоединения компьютера к уже существующей нажмите на кнопку сетевого меню и выберите соответствующий пункт (рис. 6).
Рис. 6. Кнопка сетевого меню позволяет
создать новую VPN-сеть или присоединить
компьютер к уже существующей
Присоединение ПК к существующей виртуальной сети и выход из нее
Если требуется подсоединить компьютер к уже существующей виртуальной сети и известно ее название и пароль (в случае, если он используется), то в сетевом меню выберите пункт Войти в существующую сеть… Далее откроется окно, в котором необходимо задать имя сети и пароль (рис. 7).

Рис. 7. Добавление компьютера
в существующую виртуальную сеть
После этого в окне программы появятся название сети и список присоединенных к ней компьютеров (кроме вашего) — рис. 8.

Рис. 8. После присоединения компьютера
к виртуальной сети в окне программы
отображается список присоединенных
к ней компьютеров
Если рядом с названием компьютера стоит зеленая точка или звезда, то это означает, что связь с компьютером установлена. Мигание зеленой точки свидетельствует о том, что связь находится в процессе установки. Светлый круг вокруг зеленой точки указывает на то, что с данным компьютером идет обмен информацией.
Хуже всего, когда рядом с названием компьютера стоит желтая точка — это означает, что прямое соединение с ним по каким-то причинам установить не удалось. Если желтым цветом отображается название компьютера, то это означает, что связь с ним потеряна.
Появление голубой точки указывает на то, что прямое соединение с компьютером установить не удалось и связь осуществляется через сервер Hamachi. Проблема заключается в том, что в этом случае канал связи с компьютером имеет очень низкую пропускную способность и большие задержки.
Если название компьютера и точка около его имени отображаются серым цветом, то это означает, что компьютер хотя и присоединен к данной виртуальной сети, но недоступен (например, ПК выключен, нет соединения с Интернетом или не запущена программа Hamachi).
Для того чтобы выйти из сети, достаточно щелкнуть правой кнопкой мыши на ее названии и в ниспадающем списке выбрать пункт Отключиться или Покинуть сеть. В первом случае вы лишь временно покидаете сеть и список присоединенных к ней компьютеров остается для вас видимым. Во втором случае для входа в сеть придется заново повторить всю процедуру присоединения компьютера к существующей сети.
Создание новой сети и удаление созданной сети
Если требуется создать новую виртуальную сеть, то в сетевом меню выберите пункт Создать новую сеть… Откроется окно, в котором необходимо задать имя создаваемой сети и пароль, который будут использовать другие пользователи для присоединения к этой сети (рис. 9).

Рис. 9. Создание новой VPN-сети
После создания новой сети к ней можно присоединять компьютеры пользователей. Если сеть создана вами, то вы являетесь ее администратором и получаете полный контроль над нею, которого лишены другие пользователи. При этом важно помнить, что управлять созданной сетью можно только с того компьютера, на котором она была создана. Если точнее, то управлять сетью можно только с компьютера, которому присвоен точно такой же виртуальный IP-адрес, как тот, что использовался при создании виртуальной сети. Почему это замечание так важно? Представьте себе ситуацию: вы установили программу Hamachi и создали новую VPN-сеть. Потом вы полностью удалили (включая все конфигурационные файлы) программу Hamachi и через некоторое время установили ее вновь. Вам будет присвоен новый виртуальный IP-адрес, но, используя его, вы уже не сможете контролировать созданную вами ранее VPN-сеть.
Если вы являетесь администратором сети, то можете удалить ее. Для этого щелкните правой кнопкой мыши по названию сети и в ниспадающем списке выберите пункт Удалить. Отметим, что при удалении сети полностью уничтожаются все связи между другими ее пользователями.
Другие действия с компьютерами сети
Если вы присоединились к сети, то можете совершать над присоединенными к ней компьютерами следующие действия:
- проверка доступности;
- просмотр папок;
- отправка сообщения;
- копирование адреса;
- блокирование;
- установка метки.
Для того чтобы выполнить одно из них, щелкните на имени компьютера правой кнопкой мыши и в ниспадающем меню выберите соответствующий пункт (рис. 10).
Рис. 10. Список возможных действий
с выбранным компьютером сети
При выборе пункта Проверить доступность будет выполнена обычная команда ping по адресу соответствующего компьютера.
Пункт Просмотреть папки позволяет получить доступ к открытым для совместного доступа (Sharing) папкам на компьютере.
Пункт Отправить сообщение дает возможность обмениваться сообщениями между отдельными компьютерами сети наподобие тому, как это делается в ICQ.
Пункт Копировать адрес вставляет в буфер обмена IP-адрес выбранного компьютера, что удобно, если требуется использовать этот адрес в других программах (например, удаленного администрирования).
Пункт Блокировать позволяет временно заблокировать выбранный компьютер, то есть ваш с ним VPN-канал окажется заблокированным и обмен информацией будет невозможен.
Пункт Установить метку позволяет выбрать формат отображения атрибутов компьютера в сети. По умолчанию отображается IP-адрес компьютера и его название. Можно задать отображение только имени компьютера или только IP-адреса.
Настройка программы
Для того чтобы получить доступ к настройке программы, необходимо нажать на кнопку системного меню и выбрать пункт Установки… (рис. 11).
Рис. 11. Получение доступа к настройкам
программы
После этого откроется окно Статус и конфигурация, позволяющее произвести детальную настройку программы (рис. 12).

Рис. 12. Окно детальной конфигурации программы
Собственно, здесь все достаточно просто, и вряд ли нужны подробные комментарии, поэтому просто перечислим возможности, которые можно реализовать в окне конфигурации. Итак, в этом окне можно изменить имя компьютера, произвести детальную настройку соединения, задать тип запуска программы, заблокировать или разблокировать уязвимые службы Windows, заблокировать новых членов сети и реализовать другие, менее значимые опции. Среди важных возможностей отметим отключение шифрования при передаче данных между отдельными компьютерами сети. Для того чтобы сделать это, необходимо нажать на иконку Окно и в группе Внешний вид отметить пункт Show «Advanced…» per menu item (рис. 13).

Рис. 13. Добавление пункта Advanced…
в ниспадающее меню
После этого, если на имени компьютера, присоединенного к сети, щелкнуть правой кнопкой мыши, в ниспадающем меню появится пункт Advanced… Если выбрать его, то откроется окно Tunnel Configuration, позволяющее изменить настройки VPN-туннеля. Для отключения шифрования в пункте Encryption необходимо выбрать значение Оff. В этом случае данные с вашего компьютера будут передаваться на выбранный ПК в незашифрованном виде. Однако в обратном направлении данные будут передаваться зашифрованными. Для того чтобы полностью отключить шифрование для VPN-туннеля между двумя компьютерами, его нужно отключить на обоих компьютерах.
Отметим, что отключать шифрование следует только в исключительных случаях, поскольку сама процедура шифрования вряд ли отразится на трафике. Дело в том, что трафик будет определяться пропускной способностью вашего интернет-канала, а отнюдь не применением или отсутствием шифрования. Только в том случае, если VPN-туннель образуется между компьютерами в пределах одной локальной сети и его пропускная способность составляет порядка 100 Мбит/с, использование шифрования может немного снизить максимальную скорость передачи (до 70-80 Мбит/с).
Заключение
Программа Hamachi — это мощный инструмент, позволяющий очень быстро создавать VPN-сети. Отметим, что изначально она была создана для того, чтобы пользователи могли играть в сетевые игры в обход игровых серверов. Однако возможные сценарии применения этой программы значительно шире. Так, создав виртуальную сеть и присоединив к ней компьютеры, можно, воспользовавшись стандартными программами удаленного администрирования, получить удаленный доступ к любому компьютеру виртуальной сети, поскольку каждый компьютер такой сети имеет свой выделенный IP-адрес.
В то же время нужно отметить, что далеко не всегда удается установить прямое соединение между отдельными компьютерами. И несмотря на то, что на сайте производителя утверждается, что программа легко «пробивает» маршрутизаторы и NAT-устройства, на самом деле все не столь оптимистично. В документации к программе утверждается, что в 5% случаев прямое соединение между отдельными компьютерами установить не удается, однако, как нам кажется, эта цифра явно занижена. Реальная ситуация такова: если речь идет о соединении двух компьютеров, которым присваивается динамический или статический публичный IP-адрес, то проблем не возникает. То есть если у вас дома имеется всего один компьютер с выходом в Интернет и вам нужно соединиться с пользователем, у которого также один компьютер с выходом в Интернет, то никаких проблем не будет. Как показывает практика, не возникает проблем установления соединения и между компьютером пользователя с присвоенным ему динамическим или статическим публичным IP-адресом и компьютером в составе локальной сети, защищенной маршрутизатором. Однако если связь устанавливается между двумя компьютерами, принадлежащими разным локальным сетям, защищенным маршрутизаторами, то возможны проблемы и не факт, что прямое соединение будет установлено. То есть соединение может быть установлено, но с большой вероятностью оно будет не прямое, а через сервер Hamachi. Соответственно скорость такого канала связи окажется очень низкой и проку от такого соединения будет не много. К примеру, у вас дома выход в Интернет реализован с использованием беспроводного маршрутизатора, то есть ваш компьютер находится в составе домашней локальной сети и ему присваивается IP-адрес из диапазона зарезервированных для частного применения адресов, а публичный адрес присваивается WAN-порту маршрутизатора, через который вы выходите в Интернет. Если вы пытаетесь установить соединение с другим компьютером, который также находится в составе локальной сети (например, с рабочим компьютером в офисе или с компьютером пользователя, у которого дома развернута локальная сеть и используется маршрутизатор), то в большинстве случаев появляются проблемы.
В руководстве пользователя программы Hamachi описывается, каким образом можно избежать подобных проблем. Для этого предлагается использовать фиксированный (а не динамический) UDP-порт и реализовать функцию перенаправления портов на маршрутизаторе. Однако, как показывает практика, перенаправление портов или применение демилитаризованной зоны в маршрутизаторе далеко не всегда помогает.
Создание и настройка локальной сети через Интернет
В 21 в. актуальность присутствия сотрудника в офисе компании постепенно теряет смысл. Корпоративный дух и доступность коллег под рукой, конечно, приносят преимущества, но домашний уют и удобства становятся все равно в приоритете у многих сотрудников. Людям просто удобней работать из дома, к тому же у них есть такая возможность благодаря технологии создания локальной сети через Интернет. О том, как все настроить, пойдет речь ниже.
Принцип работы локальных сетей через Интернет
Локальная сеть, безусловно, полезна в случае удалённой работы для группы людей. Внешние ресурсы не слишком надежны, если речь идет про степень защиты, и к тому же не слишком удобны в использовании нескольких человек. На помощь в решение этой непростой ситуации приходят программы и сервисы для создания виртуального сетевого пространства, подключение к которому происходит через Интернет.

В Сети есть как бесплатные варианты подобных программ, так и платные, но с более расширенным функционалом. Один пользователь, создавший сеть, становится администратором. Далее он либо приглашает новых участников в новую сеть, либо дает им адрес для самостоятельного подключения. Сервер виртуальной сети находится в облаке. Это значит, что остальным участникам при работе в сети не нужно присутствие администратора.
Программы для настройки сети
Рассматривая варианты, как создать локальную сеть через Интернет, стоит обратить внимания на такие сервисы.
Программа Hamachi и ее настройка
Это одним из самых популярных сервисов для простого и быстрого создания виртуальных сетей.
Обратите внимание! Есть две вариации утилиты: бесплатная, которая способна создать одновременный доступ к сети для 16-ти человек, и платная расширенная версия с большим функционалом, созданным для упрощения работы.
Стоимость составляет примерно 200 $ в год. Эта программа очень проста в настройке и в использовании в целом. Подключение Hamachi происходит в несколько шагов:

- Сперва нужно запустить само приложение и открыть подменю «Параметры» во вкладке «Система».
- В данном меню найти два ключевых параметра: «Шифрование» и «Сжатие». Во всплывающем списке следует установить значение «Любой».
- Далее для настройки программы стоит перейти во вкладку «Дополнительные параметры» и запретить использование прокси-сервера. Там же установить параметр разрешения имен по протоколу mDNS. Стоит также проследить, чтобы для опции «Фильтрация трафика» было выбрано «Разрешить все».

Важно! Когда подключение к Интернету происходит через роутер, в настройках Hamachi нужно открыть порты для исправного функционирования.
После проделанных операций можно считать, что локальная сеть через Интернет настроена. Программа будет функционировать в полном объёме, другие пользователи могут смело подключаться.
Создание виртуальной сети, используя OpenVPN
Для создания более безопасного подключения к LAN через Интернет стоит рассмотреть вариант установки OpenVPN. Эта программа использует вместо стандартных ключей известные сертификаты TLS/SSL. Для создания сети рекомендуется использовать ОС CentOS. Но официальном сайте OpenVPN можно найти вариации и для других ОС. Для установки и настройки нужно подключить репозиторий EPEL Linux.
![]()
Затем из распакованного репозитория устанавливается сам OpenVPN. Для настройки виртуальной сети используется конфигурационный файл, который копируется в используемую папку. Затем следует запустить редактор Nano для открытия и корректировки файла. Там нужно убрать комментарий из строки со словом «push» в начале. Это позволит клиентской версии программы маршрутизироваться через OpenVPN.
Важно! Аналогичную операцию стоит проделать и для строк, отвечающих за корневые DNS-сервера Google.

Генерация ключей и сертификатов
После того как конфигурационный файл был отредактирован и готов к работе, нужно создать ключи и сертификаты для подключения. Подходящие скрипты можно найти в корневой папке программы. Для генерации ключей сначала стоит создать новую папку и скопировать в нее все ключевые файлы.
![]()
После этого нужно найти и внести изменения в файл «vars», в нем можно будет найти всю необходимую информацию для скрипта: vim/etc/openvpn/easy-rsa/vars.
В заданном файле должны интересовать строки, начинающиеся на «KEY_». В них и заполняется нужная для создания ключа информация.
После проделанных операций следует создание сертификатов для клиентов, использующих VPN. Это нужно сделать в отдельности для каждого устройства, которое будет подключаться при помощи VPN.
![]()
Настройка параметров маршрутизации
Для запуска нужно создать правило для Firewall Iptables для обеспечения правильной маршрутизации VPN подсети. Стоит также проверить возможность маршрутизации пакетов сервером, для чего стоит отредактировать файл Sysctl.

После всех правок настройки Sysctl применяются, и сервер можно запускать. Как только он начнет работать, стоит поместить его в автозагрузку.

Только тогда VPN сервер настроен и готов к работе.
Как создавать конфигурации параметров клиентов OpenVPN
После настройки работы самого сервера нужно создать возможность подключаться к нему с клиентской версии программы. Для этого пользователям рекомендуется получить несколько файлов, а именно: ca.crt, client.crt и client.key. Их можно найти в папке /etc/openvpn/easy-rsa/keys. Затем нужно создать еще один файл с названием client.ovpn, где будут храниться данные о самом клиенте.
Важно! Рекомендуется хранить файл в безопасном месте, именно через него совершается подключение к рабочей сети и серверу в целом.

Пользоваться данной сетью могут клиенты как с ОС Windows, так и Linux. В первом случае нужно скачать инсталляционный файл OpenVPN и установить его, после чего поместить четыре упомянутых ранее файла в корневую папку клиента. Для любителей Linux так же устанавливается клиент из официального репозитория и запускается с параметрами файла «.ovpn».
Обратите внимание! После проделанных операций локалка через Интернет будет работать, и появится возможность раздавать доступ другим участникам.
В обоих ранее указанных вариантах виртуальная локальная сеть создается довольно просто. Пошаговые инструкции понятны даже новичку. Главное, чтобы был доступ к Интернету.

Подгорнов Илья Владимирович Всё статьи нашего сайта проходят аудит технического консультанта. Если у Вас остались вопросы, Вы всегда их можете задать на его странице.
Похожие статьи

«Шина» — топология локальной сети: описание Топология локальной сети «шина»: описание разновидности топологии и ее плюсы. . Чтобы выбрать наиболее эффективный способ подсоединения компьютеров и оборудования в общую сеть, необходимо учитывать их количество. Если соединятся менее десяти устройств при помощи.
Прямой VPN-туннель между двумя компьютерами находящимися за NATами провайдеров
Статья о том, как мне удалось организовать прямой (точка-точка) VPN-туннель между двумя компьютерами, каждый из которых находился за NAT’ом провайдеров, при помощи VPS и простых скриптов, используя стандартные утилиты Linux, без каких-либо настроек сетевого оборудования.
Введение
Существует множество программ (TeamViewer, Hamachi) для удаленного управления компьютером, передачи данных и т.п. Работают они на удивление хорошо и в любых условиях. Но как правило это платные сервисы. Как устроены эти программы неизвестно, да и особого желания их использовать они у меня не вызывают. Я как пользователь ОС Linux (в основном Ubuntu) использовал для передачи данных и управлением своими ПК связку из OpenVPN, SSH, VNC, RDP и прочие сервисы в зависимости от потребности. Для того чтобы организовать сеть между двух компьютеров я использовал VPN-сервер, что бы эти компьютеры подключались к OpenVPN серверу и весь трафик шел через сервер. Это не совсем хорошо, ведь трафик проходит двойной путь, в следствии этого терялась скорость.
Теория
Я давно задумался о решении по организации канала передачи данных непосредственно от узла к узлу, которые находятся за NATом провайдеров, без использования серверов-посредников. Перебрав некоторое количество статей о различных технологиях типа GRE-туннелей, IPsec, UDP Hole Punching, OpenVPN и прочего, я понял, что узлы должны пробивать соединение на встречу друг другу, то есть посылать пакеты на IP и порт удаленного узла. Поставил несколько опытов по организации GRE-туннеля через NAT, передачу сообщения при помощи NetCat навстречу друг другу, иногда это работало, иногда нет, всё зависело от типа используемого провайдером NAT. Не так давно попалась на глаза интересная статья, в которой было описание организации работы OpenVPN соединения между двумя компьютерами (далее узлами). Я прочитал, проверил и заработало, но при условии, что локальный порт узла и внешний порт будут совпадать, то есть мой провайдер будет использовать Cone NAT. Мне же стало интересно организовать туннель между двумя компьютерами при условии, что оба будут находятся за любым типом (Cone или Symmetric) NAT, то есть локальный порт может не совпадать с внешним портом. Задача уперлась в невозможность определения текущего порта внешнего интерфейса без внешней помощи. Если внешний IP-адрес хоть как-то можно узнать (например: curl ifconfig.me), а вот с определением текущего внешнего порта возникла трудность.
Практика
Для решения этой задачи пришлось использовать VPS (S-синий овал), на нем я поднял скрипт который выполнял роль «Соединителя», что-то типа STUN-сервера: при помощи утилиты TCPDump получал UDP-пакет (далее везде используется UDP протокол) на определенный интерфейс и порт, парсил содержимое пакета, определял IP-адрес/порт источника и отвечал утилитой NetCat возвращая текущие параметры (IP-адрес и порт) соединения, а так же параметры (IP-адрес и порт) удаленного узла к которому нужно подключиться, если эти данные были доступны, иначе ждал пока они не появятся. Все это дело сопоставлялось с идентификатором (ID) соединения, так как несколько соединений могли мешать друг другу, при использовании ID все решалось. Так же была проблема того, что узел получал свои же старые данные и пытался по ним подключиться и это решилось с помощью хеша Hostname.

На узлах A и B я использовал скрипт и сгенерированный заранее ключ для авторизации VPN-соединения, работало это так: запускался скрипт, случайно выбирался локальный порт в диапазоне от 20000 до 65000 и с этого порта отправлялся пакет на VPS, который содержал в себе ID соединения и хеш hostname, с помощью утилиты NetCat и тут же запускался TCPDump ожидая ответа. В ответ приходил пакет который содержал в себе текущие данные (IP-адрес/порт) этого узла, а при наличие данных удаленного узла, они тоже приходили и начинался обмен приветствиями между узлами. Если же данных удаленного узла не было, то опрос повторялся с периодичностью 30-45 секунд, для поддержания сессии. В момент когда все необходимые данные (IP-адрес и порт текущего узла и удаленного) были на узлах, начинался обмен пакетами, пакет содержал в себе число m=0 и сгенерированное число от 0 до 254 (это число спользовалось для генерации внутреннего IP-адреса VPN-соединения). Удаленный узел получив пакет с m=0 отправлял в ответ m=1 и так далее до 10. При получении пакета m=10 инициировалась посылка пачки пакетов с периодичность в 1 секунду с m=13 и запуск OpenVPN, удаленный узел получив m=13 тоже запускал OpenVPN используя локальный порт, IP-адрес и порт удаленного узла, а также сгенерированный внутренний IP вида 10.X.X./30.
Внимание: скрипты написаны и проверены на ОС Ubuntu 18.04 и Debian 9
Скрипт на VPS:
#!/bin/bash if [[ $1 == '' ]]; then echo -e "Укажите номер порта который нужно слушать"; exit; fi iface=`ip route get 8.8.8.8 | head -n 1 | sed 's|.*dev ||' | awk ''` a=0 until (( $a == 500)); do packet=`tcpdump -i $iface udp port $1 -vvn -c1 -A` if [[ "$packet" == *"Ident"* ]]; then pack=`echo "$packet" | grep -e "udp sum ok" -e "Ident"` myip=`echo $pack | sed 's/\./ /g' | awk ''` myport=`echo $pack | sed 's/\./ /g' | awk ''` id=`echo $pack | sed 's|.*Ident:||' | awk ''` myname=`echo $pack | sed 's|.*Ident:||' | awk ''` echo "$myip:$myport $myname" > /tmp/vpn2-$id-$myname echo "MyData $myip:$myport $(cat /tmp/vpn2-$id-* | grep -v $myname | awk )" | nc $myip $myport -u -p $1 -w 1 cat /tmp/vpn2-$id-* topoint=`cat /tmp/vpn2-$id-* | grep -v "$myname" | sed 's/:/ /g'` if [[ $topoint != '' ]]; then ip=`echo $topoint | awk ''` port=`echo $topoint | awk ''` echo "MyData $ip:$port $(cat /tmp/vpn2-$id-* | grep $myname | awk )" | nc $ip $port -u -p $1 -w 1 fi fi done
Запускается автоматически строкой в /etc/rc.local
nohup /путь-до-скрипта/connector2.sh 13013 > /var/log/connector2.log &
где 13013 — это порт который нужно слушать, /var/log/connector2.log — лог.
Скрипт на узлах: # cat vpn5.sh
#!/bin/bash ######################## Задаем цветной текст ### WARN='\033[37;1;41m' # END='\033[0m' # RED='\033[0;31m' # $ # GREEN='\033[0;32m' # $ # ################################################# ####################### Проверяем наличие необходымих приложений ######################################################### al="echo readlink dirname ps grep awk kill md5sum shuf nc curl sleep openvpn tcpdump" ch=0 for i in $al; do which $i > /dev/null || echo -e "$Для работы необходим $i $"; which $i > /dev/null || ch=1; done if (( $ch > 0 )); then echo -e "$Ой, отсутствуют необходимые для корректной работы приложения$"; exit; fi ####################################################################################################################### if [[ $1 == '' ]]; then echo -e "$Введите идентификатор соединения (любое уникальное слово, должно быть одинаковое с двух сторон!) $ \t $Для запуска в автоматическом режиме при включении компьютера можно прописать в /etc/rc.local строку nohup //vpn5.sh > /var/log/vpn5.log 2>/dev/hull & $"; exit; fi ABSOLUTE_FILENAME=`readlink -f "$0"` # полный путь до скрипта DIR=`dirname "$ABSOLUTE_FILENAME"` # каталог в котором лежит скрипт ################################################################# if [ ! -f "$DIR/secret.key" ]; then echo -e "$Секретный ключ VPN-соединения не найден, для генерации ключа выполните: \ openvpn --genkey --secret secret.key Внимание: ключ используется для авторизации и должен \ быть одинаковым с двух сторон. $ # ls -l secret.key -rw------- 1 root root 637 ноя 27 11:12 secret.key # chmod 600 secret.key"; exit; fi localport=`shuf -i 20000-65000 -n 1` # Выбор локального порта until [[ $count > 100 ]]; do ######################################################################################### name=`uname -n | md5sum | awk ''` # Имя узла ipsrv="45.141.103.45" # IP-адрес сервера получения данных о второй стороне portsrv="13013" # Порт сервера iftosrv=`ip route get $ipsrv | head -n 1 | sed 's|.*dev ||' | awk ''` # Определение интерфейса netcattosrv="nc -u $ipsrv $portsrv -p $localport -w 1" # Команда посылки пакета NC tcpdumptosrv="tcpdump -i $iftosrv udp and port $portsrv and src $ipsrv -n -c1 -A" # Команда приема пакета id=`echo $1| md5sum | awk ''` # Преобразеум имя узла в md5 что бы не светить реальное имя ##################### Получение данных о себе и удаленного узла ################################### echo -e "$(date) $Фаза 1 - Получение данных с сервера $" echo -e "$(date) $Использую интерфейс $iftosrv и локальный порт $localport $" until [[ -n "$ip" && -n "$port" ]]; do if [[ -z "$data" ]]; then sleep 1 && echo "Ident: $id $name" | $netcattosrv > /dev/null & sleep 4 && pid=`ps xa | grep "$tcpdumptosrv" | grep -v grep | awk ''` && if [[ -n $pid ]]; then kill $pid; echo "$(date) Нет ответа от сервера, пробую еще раз. "; fi & data=`$tcpdumptosrv` sleep 2 fi if [[ -n "$data" ]]; then #echo "Ответ: $data" data=`echo "$data" | grep "MyData" | sed 's|.*MyData ||' | sed 's/:/ /g'` myip=`echo "$data" | awk ''` myport=`echo "$data" | awk ''` ip=`echo "$data" | awk ''` port=`echo "$data" | awk ''` data='' if [[ -z $tst ]]; then echo -e "$(date) $Мой внешний IP: $myip и порт: $myport $"; fi if [[ -n $localport && -n $myport && -z $tst ]]; then if [[ $localport == $myport ]]; then echo -e "$(date) $Мой локальный порт $localport и внешний порт $myport одиноковые, используется CONE NAT $"; tst=1 else echo -e "$(date) $Мой локальный порт $localport и внешний порт $myport разные, используется SYMMETRIC NAT $"; tst=1 fi fi fi if [[ -n "$ip" && -n "$port" ]]; then echo -e "$(date) $Получил данные об удаленном узле: IP: $ip Порт: $port $"; else sleep=`shuf -i 30-45 -n 1`; echo -e "$(date) $Нет данных об удаленном узле, ожидаю данных $sleep секунд и оповещаю еще раз. $"; sleep $sleep && pid=`ps xa | grep "$tcpdumptosrv" | grep -v grep | awk ''` && if [[ -n $pid ]]; then kill $pid; fi & data=`$tcpdumptosrv` fi done ###################### Организация соединения с удаленным узлом iftopeer=`ip route get "$ip" | head -n 1 | sed 's|.*dev ||' | awk ''` echo -e "$(date) $Фаза 2 - Установка соединения со второй стороной $" echo -e "$(date) $Попытка установки соединения: $myip:$myport -> $ip:$port $" m=0 t=0 connect=0 until (( $connect >= 10 )); do if [ ! -f "$DIR/.mes" ]; then mes=`shuf -i 0-254 -n 1` echo $mes > $DIR/.mes else mes=`cat $DIR/.mes` fi netcattopeer="nc -u $ip $port -p $localport -w 1" tcpdumptopeer="tcpdump -i $iftopeer udp and port $localport and src "$ip" -n -c1 -A" until (( $m >= 10 )); do for w in ; do sleep 1 && echo "445Hi: $m $mes" | $netcattopeer > /dev/null; done & sleep 4 && pid=`ps xa | grep "$tcpdumptopeer" | grep -v grep | awk ''` && sleep 10 && if [[ -n $pid ]]; then kill $pid && echo -e "$(date) $ Нет ответа от пира, пробую еще раз. $"; fi & peer=`$tcpdumptopeer` if [[ -n $peer ]]; then newport=`echo "$peer" | grep " IP " | sed "s|.* $ip.||" | awk ''` if (( $newport != $port )); then echo -e "$(date) $Порт изменился $port -> $newport $"; port=$newport; netcattopeer="nc -u $ip $port -p $localport -w 1" fi mm=`echo "$peer" | grep "445Hi: " | sed 's|.*445Hi: ||' | awk ''` echo -e "$(date) $ Получил: $mm - передаю: $mm+1 $" if (( $m <= $mm )); then m=$(( $mm + 1 )); fi text=`echo "$peer" | grep "445Hi: " | sed 's|.*445Hi: ||' | awk ''` else (( t++ )) echo -e "$(date) $ Данных нет $t раз $" if (( $t > 5 ));then echo -e "$(date) $ Превышен интервал ожидания, переподключаюсь $"; m=10; connect=1012; ip=''; port=''; fi fi done if (( $connect < 1012 )); then echo -e "$(date) $Значение: $m $" if [[ $port > $myport ]]; then ipaddress="10.$text.$mes.1"; else ipaddress="10.$mes.$text.2"; fi m=12 for w in ; do echo "445Hi: $m $mes" | $netcattopeer > /dev/null; done echo -e "$(date) $ Запускаюсь и использую $ipaddress. $" $(which lsmod) | grep tun || $(which modprobe) tun openvpn --remote $ip --rport $port --lport $localport \ --proto udp --dev tap --float --auth-nocache --verb 3 --mute 20 \ --ifconfig "$ipaddress" 255.255.255.252 \ --secret "$DIR/secret.key" \ --auth SHA256 --cipher AES-256-CBC \ --comp-lzo --ncp-disable --ping 10 --ping-exit 50 echo -e "$(date) $ Соединение прервано. $" m=0 t=0 (( connect++ )); fi done done
Запускается автоматически строкой в /etc/rc.local
sleep 15 && nohup /путь-до-скрипта/vpn5.sh >/var/log/vpn5.log 2>/dev/hull &
где ID-соединения — это любая уникальная фраза для вашего соединения, /var/log/vpn5.log — лог соединения, ipsrv=«45.141.103.45» — IP-адрес узла где запущен connector2.sh (первый скрипт), sleep 15 — нужно чтобы за это время поднялись сетевые интерфейсы.
Если все настроено правильно, то будет работать как часы: включил и через пару минут у тебя есть связь с удаленным узлом. В скриптах используются бесконечные циклы и временные задержки, то есть скрипт работает пока включен узел и при потере связи будет пытаться восстановить её. Скрипты не идеальные но, сам факт того что эта технология работает дает мне массу новых идей, например:
- использовать узел для хранения особо важных данных, и иметь к ним доступ, допустим, в случае утери ноутбука все данные будут на узле
- использовать на ноутбуке удаленный рабочий стол компьютера
- организовать связи с компьютером друга и поиграть в сетевую игру
- иметь доступ к домашней камере видеонаблюдения с рабочего компьютера или просмотреть веб-камеру ноутбука
- простота в настройке и использовании
- трафик идет напрямую
- трафик шифруется и защищен от перехвата
- нет необходимости пробрасывать порты
- скрипт запускается автоматически
- главный недостаток это использования VPS как источника данных для соединения, но я думаю над этим
- некоторые провайдеры блокируют трафик между другими провайдерами (замечено у сотовых операторов)
- при использовании с обоих сторон одного провадера может не сработать, зависит от типа NAT
- при использовании провадером «жесткого» NAT может не сработать
Думаю на фоне дефицита белых IPv4 адресов моё решение будет актуально.