Подключение к VPN через Openconnect на Linux и OpenBSD

THE HOLY BIBLE - King James Version - БИБЛИЯ в Синодальном переводе
"Нас Атакуют!" Изобличи козни лукавого, запрети диаволу

Подключение к VPN через Openconnect на Linux и OpenBSD

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

В то же время пользователям становится всё более необходимо оставаться подключёнными к нескольким сетям одновременно, выполняя отдельные задачи для разных частей организации (или вообще для разных клиентов). В такой ситуации очень часто приходится использовать несколько компьютеров, перезагружаться в разные ОС или, как минимум, постоянно переподключаться к разным VPN серверам.

В предлагаемой заметке я показываю как подобные неудобства могут быть легко устранены при использовании всего одного клиента VPN на одной и той же физической системе, под управлением Linux или OpenBSD. Приводится простой пример одновременного подключения к двум независимым VPN сетям.

Прежде чем мы продолжим, я хотел бы привести строки из Евангелия:


..................... == Вторая книга Паралипоменон == .........................
=== Глава 7, Стих 13 ===
13 Если Я заключу небо и не будет дождя, и если повелю саранче поядать  землю, или пошлю моровую язву на народ Мой,
14 и смирится народ Мой, который именуется именем Моим, и будут молиться, и  взыщут лица Моего, и обратятся от худых путей своих, то Я услышу с неба и  прощу грехи их и исцелю землю их.

Лично для вас благая весть - Единородный Сын Божий Иисус Христос любит вас, Он взошёл на крест за ваши грехи, был распят и на третий день воскрес, сел одесную Бога и открыл нам дорогу в Царствие Небесное.

В жизни каждого случаются беды и несчастия, они преслeдуют почти неотступно нас, наши семьи и нашу страну. И мы в глубоком недоумении и с разочарованием спрашиваем "За что нам эта беда?". Нам кажется что мы живём честно, стараемся не делать зла, помогать другим - каким же образом постигают нас все эти напасти?

Господь Бог видит наши сердца и знает истинные намерения наших душ. Даже в те моменты, когда мы успешно убедили себя что делаем добро или "зло во имя добра"... И Он наказывает нас по мере наших проступков - и наказание сие постигает каждого, от простолюдина до президента, охватывая всю страну, за преступления, совершаемые в ней. Так что винить в своих бедах мы должны самих себя - а точнее, наше отступление от Библейских ценностей и Божиих заповедей. Перечитаем их прямо сейчас! Сверим курс наших жизней со Словом Божиим. И, как написано, исправив свои пути, заслужим Божие прощение - а с ним придёт и избавление от бед и несчастий. При этом мы должны пройти дорогой исправления полностью и до конца, решительно оставляя позади такие соблазнительные и уже привычные мирские удовольствия.

Покайтесь, примите Иисуса как вашего Спасителя, ибо наступают последние времена и время близко - стоит Судья у ворот.

Пожалуйста, в своих каждодневных трудах, какими бы занятыми вы себе ни казались - находите время для Бога, Его заповедей и Библии.

На главной странице этого сайта вы найдете программу для чтения Библии в командной строке - буду очень рад если программа окажется полезной. Пожалуйста, читайте Библию, на экране или в печатном виде - вы будете искренне удивлены как много там сказано лично про вас и ваши обстоятельства.


Вернёмся к нашим техническим деталям.

В заметке я рассмотрю достаточно простой и часто встречающийся случай. Предположим что по специфике работы нам необходимо подключиться к какой-либо сети клиента "A", где находится так называемый "jump host", с которого осуществляются все последующие подключения к компьютерам клиента "А". В это же самое время мне надо быть подключенным к сети клиента "Б", где находится вебсайт системы мониторинга и где я слежу за производительностью только что введённого в строй сервера. На фоне всего этого мне необходим стабильный доступ к моим собственным серверам в Интернет, откуда я получаю почту, загружаю файлы и звоню по телефону через VOIP. Компании клиентов А и Б используют свои собственные VPN сети, мои сервера находятся в открытом интернете, в датацентре одного из глобальных VPS провайдеров.

Я вынужден использовать единственную рабочую станцию под управлением OpenBSD (или Linux, если пожелаете) и мне необходимо иметь открытыми и одновременно работающими следующие программы:

  • эмулятор терминала с ssh сессией, подключенной через VPN "A" к "jump host" клиента "А" с адресом 10.1.1.100;
  • вебброузер Опера, подсоединённый через VPN "Б" к внутреннему вебсайту клиента "Б" с адресом 192.168.1.192;
  • эмулятор терминала с ssh сессией, подключенной через открытый интернет к одному из моих серверов с адресом 83.125.20.101;
  • FTP клиент, постоянно соединённый с сервером 83.125.20.101;
  • Программы для VOIP телефонии и Skype, периодически подключающиеся к серверам соответствующих компаний.
  • Для всех VPN подключений я использую последнюю версию программы "openconnect". Доступ в интернет предоставляется моим ISP через default gateway 10.0.0.138.

    Как результат, я не могу использовать стандартный скрипт "/etc/vpnc/vpnc-script", поскольку каждое VPN подключение будет изменять мою таблицу маршрутизации, делая работу с другими клиентами невозможной. Кроме того, я хочу понимать что происходит "за сценой" при подключении к каждому из клиентов и иметь полную уверенность что пакеты клиента "А" не попадают к клиенту "Б" и тому подобное.

    Про типы VPN и клиентов для них

    Прежде чем обсуждать подробности подключения, я приведу краткую информацию o VPN вообще и клиенте openconnect.

    Типы VPN

    Изначально одним из самых распространённых и наверняка самым надёжным являлся набор протоколов iPSec. Моё мнение - он и остаётся на сегодня единственным более или менее приемлемым решением.

    Поскольку IPSec "на коленках" настраивался плохо и надо было всё-таки нанимать специалиста для его внедрения (что является безусловным плюсом, если интересует результат), понадобилось удешевить и упростить процесс. Так появились SSL VPNы, которыми мы и пользуемся сейчас.

    Технически, IPSec работает на уровне L3 OSI модели и реализован внутри ядра ОС. Отсюда и происходят его основные преимущества - производительность, прозрачность, защищённость и т.п. Напротив, SSL VPN работает вне ядра ОС (в userspace) и использует "верхние" уровни OSI модели. SSL VPN может работать "через вебброузер" (SSL Portal VPN) или как туннель (SSL Tunnel VPN).

    Реализация VPN

    Для "аппаратной" реализации обоих типов VPN (IPSec и SSL VPN) традиционно используются Cisco продукты - например, старенький Cisco VPN 3000 Concentrators или поновее ASA 5500.

    Естественно были предприняты (весьма успешные) попытки создания бесплатных "софтверных" конкурирующих с Cisco реализаций SSL VPN - именно таковым и является OpenVPN. (Читайте дальше про openconnect)

    Клиентский доступ к VPN

    В мире Windows всё просто - открыл Cisco VPN Client (Anyconnect или более старый Easy Cisco VPN Client), вбил данные - и ты уже в корпоративной сети.

    В большинстве простых ситуаций подключения к единственному корпоративному VPN лично я порекомендовал бы именно такой подход - устанавливаете отдельный лаптоп с Windows, на нём используете стандартный Cisco клиент, подключаетесь к VPN. На лаптопе работает VNC server или Remote Desktop, который вы используете с вашей линукс машины. Просто и всегда работает (но такое решение нельзя назвать изящным).

    Естественно, появились и альтернативные клиенты, конкурирующие с Cisco AnyConnect клиентом.

    Их два на сегодня:

  • vpnc - используется для подключения к "старым" Cisco VPN устройствам
  • openconnect - для работы с текущими версиями Cisco VPN аппаратуры, именно поэтому я пользуюсь этим клиентом
  • При этом openconnect может работать и как VPN сервер, выполняя те же функции что и OpenVPN server.

    Подводя итоги

    Для организации VPN инфраструктуры в вашей компании у вас есть выбор:

  • 1) Cisco VPN hardware и на нём:
  • -IPSec
  • или
  • -SSL VPN
  • 2) OpenVPN server (aka SSL VPN)
  • 3) OpenConnect Server (также SSL VPN)
  • Клиентский доступ осуществляется:

  • 1) Через правильно организованный IPSec
  • или
  • 2) Cisco Anyconnect VPN client для Windows
  • 3) vpnc (старые системы) или openconnect (новые системы) client на unix-like ОС
  • Предлагаемое решение

    Для поддержания моего окружения в работоспособном состоянии я буду создавать VPN "тоннель", используя openconnect, но при этом не допуская выполнения никаких скриптов. Необходимые изменения в таблице маршрутизации будут сделаны вручную. Таким образом я смогу сохранить маршрут "по умолчанию" и организовать доставку нужных пакетов к соответствующему клиенту.

    Предоставляемое провайдером интернет соединение обеспечивает доступ к моим "открытым" серверам, но при этом default gateway не должен изменяться при подключении к VPN.

    Число запущенных одновременно программ "openconnect" будет соответствовать числу VPN сетей клиентов, в моём примере двум.

    Каждое VPN соединение будет создавать соответствующий "tun" интерфейс, при этом VPN сервер сообщит какой IP адрес был выдан нам как клиенту. Этот IP адрес должен быть присвоен интерфейсу "tun" вручную.

    После "поднятия" интерфейса с присвоенным IP адресом, я создам соответствующее правило для маршрутизации пакетов, применяемое только ко вновь созданному "tun" интерфейсу и не изменяющее шлюза "по умолчанию".

    После этого необходимая подсеть клиента станет доступной для работы.

    Остальные веб-ресурсы "общего назначения" внутри клиентской сети доступны через "SSL VPN Gateway" - специальный прокси веб-сервер, предоставляемый по адресу VPN шлюза. Войдя на этот сервер под именем пользователя, используемым с openconnect, я могу ввести адрес интересующей меня страницы в корпоративной интранет сети и увидеть на экране её "отображение". Такой вид доступа является стандартным в системе SSL VPN и не требует клиентской настройки.

    Реализация решения

    Для быстрого создания VPN соединения я создам скрипт, выполняющий необходимые действия. Последовательное выполнение скриптов будет устанавливать нужные соединения, не влияя на уже существующие подключения.

    Подключение одного VPN клиента

    Скрипт для подключения к клиенту "А" приведен ниже:

    ........ == Послание к Ефесянам святого апостола Павла == ............
    === Глава 5, Стих 19 ===
    18 И  не  упивайтесь  вином,  от  которого   бывает   распутство;   но
    исполняйтесь Духом,
    19 назидая  самих  себя  псалмами  и  славословиями   и   песнопениями
    духовными, поя и воспевая в сердцах ваших Господу,
    20 благодаря всегда  за  все  Бога  и  Отца,  во  имя  Господа  нашего
    Иисуса Христа,
    21 повинуясь      друг      другу      в      страхе           Божием.
    
    (b+/b-, c+/c-, +/-, *) >
    ~:$ cat vpnA.sh
    # Run this as root
    export LC_CTYPE=en_US.UTF-8
    
    VPNHOST=vpn.clientA.com
    GROUP=A-VPN
    USER=remote1
    PWD=secret1
    FILE=/tmp/vpn.out
    # Add error handling yourself - I am too lazy for this.
    
    date
    echo $PWD | openconnect -b -s empty --no-xmlpost --authgroup $GROUP \
    -u $USER --passwd-on-stdin $VPNHOST > \
    $FILE 2>&1
    #  cat $FILE
    grep "Continuing in background" $FILE
    echo To stop use \"kill -HUP pid\"
    IP=`grep "^Connected tun" $FILE | cut -f 4 -d ' ' | cut -f 1 -d ',' `
    rm $FILE
    
    if [[ `uname` == "Linux" ]]
    then
    echo Линукс
    
    ifconfig tun0 $IP up
    ifconfig tun0
    
    route -A inet add -net 10.1.0.0/16 gw $IP dev tun0
    route -n -4
    
    ps -ef | grep openconnect | grep -v grep
    else
    echo ОпенБСД
    
    ifconfig tun0 inet $IP
    ifconfig tun0
    
    route add -iface -net 10.1/16 $IP
    route -n show -inet
    
    ps -ax | grep openconnect | grep -v grep
    fi
    
    date
    

    Зная диапазон адресов (10.1.0.0/16), выдаваемых клиентам VPN сервером, я могу определить правило маршрутизации, как показано выше. Я предполагаю, что все мои сервера находятся в пределах этой DMZ подсети и не требуют дальнейшей маршрутизации. Если ваша ситуация требует более сложных правил - заведите для каждого клиента отдельный лаптоп и пользуйтесь стандартным клиентом от Cisco.

    Параметр "--no-xmlpost" требуется при работе со старыми или плохо сконфигурированными VPN шлюзами, "-s empty" исключает выполнение "vpnc" скриптов, поставляемых вместе с openconnect.

    После запуска скрипта "vpnA.sh" команда ifconfig покажет мне новый интерфейс "tun0" с DHCP адресом из подсети 10.1/16, a route покажет новое правило для обмена пакетами с этой сетью напрямую через интерфейс "tun0". Уже существующее правило для отправки всех остальных пакетов через default gateway 10.0.0.138 останется неизменным, обеспечивая доступ к интернету в нормальном режиме, при наличии VPN подключения к сети клиента "А".

    Вот как будет выглядеть результат запуска скрипта "vpnA.sh":

    lo0: flags=8049 mtu 33144
    ...
    inet 127.0.0.1 netmask 0xff000000
    iwn0: flags=8843 mtu 1500
    ...
    inet 10.0.0.2 netmask 0xffffff00 broadcast 10.0.0.255
    tun0: flags=51 mtu 1300  <---*
    ...
    inet 10.1.19.19 --> 0.0.0.0 netmask 0xffff0000
    
    
    Routing tables
    
    Internet:
    Destination        Gateway            Flags   Refs      Use   Mtu  Prio Iface
    default            10.0.0.138         UGS        4       64     -    12 iwn0
    10.0.0/24          link#2             UC         1        0     -     4 iwn0
    10.0.0.2           127.0.0.1          UGS        0        0 33144     8 lo0
    10.0.0.138         aa:bb:cc:11:44:22  UHLc       1        9     -     4 iwn0
    127/8              127.0.0.1          UGRS       0        0 33144     8 lo0
    127.0.0.1          127.0.0.1          UH         2        0 33144     4 lo0
    10.1/16 <---**---> 10.1.19.19         US         0        0     -     8 tun0
    224/4              127.0.0.1          URS        0        0 33144     8 lo0
    

    Всего лишь одна предпоследняя строка была добавлена моим скриптом в уже существующую таблицу маршрутизации.

    Подключение двух VPN клиентов

    Подобным образом мы подключимся ко второй сети через VPN шлюз клиента "Б". Скрипт очень похож и отличается некоторыми параметрами команды openconnect, именем туннельного интерфейса и адресами сети.

    ..... == Первое послание к Тимофею святого апостола Павла == .........
    === Глава 6, Стих 3 ===
    3 Кто учит иному и не следует здравым  словам  Господа  нашего  Иисуса
    Христа и учению о благочестии,
    4 тот горд, ничего не знает, но заражен  _страстью_  к  состязаниям  и
    словопрениям,  от  которых  происходят  зависть,  распри,  злоречия,
    лукавые подозрения.
    
    (b+/b-, c+/c-, +/-, *) >
    ~:$ cat vpnB.sh
    # Run this as root
    export LC_CTYPE=en_US.UTF-8
    
    VPNHOST=vpn.clientB.ru
    USER=remote2
    PWD=secret2
    FILE=/tmp/vpn.out
    
    date
    echo $PWD | openconnect -b -s empty -i tun1 \
    -u $USER --passwd-on-stdin $VPNHOST > \
    $FILE 2>&1
    # cat $FILE
    grep "Continuing in background" $FILE
    echo To stop use \"kill -HUP pid\"
    IP=`grep "^Connected tun" $FILE | cut -f 4 -d ' ' | cut -f 1 -d ',' `
    rm $FILE
    
    if [[ `uname` == "Linux" ]]
    then
    echo Линукс
    
    ifconfig tun1 $IP up
    ifconfig tun1
    
    route -A inet add -net 192.0.0.0/8 gw $IP dev tun1
    route -n -4
    
    ps -ef | grep openconnect | grep -v grep
    else
    echo ОпенБСД
    
    ifconfig tun1 inet $IP
    ifconfig tun1
    
    
    route add -iface -net 192.0/8 $IP
    route -n show -inet
    ps -ax | grep openconnect | grep -v grep
    fi
    
    date
    

    После выполнения этого скрипта мы получим уже два одновременно работающих VPN подключения:

    tun1: flags=51 mtu 1300
    ...
    inet 192.168.135.236 --> 0.0.0.0 netmask 0xff000000
    
    Routing tables
    
    Internet:
    Destination        Gateway            Flags   Refs      Use   Mtu  Prio Iface
    default            10.0.0.138         UGS        4       64     -    12 iwn0
    ...
    10.1/16            10.1.19.19         US         0        0     -     8 tun0
    ...
    192/8 <---**--->   192.168.135.236    US         0        0     -     8 tun1
    

    Список UNIX процессов теперь будет показывать две копии программы openconnect с разными параметрами и использующими разные "tun" устройства.

    Интернет и обе сети клиентов "А" и "Б" могут быть использованы одновременно. Убедитесь что ваша система не позволяет маршрутизировать пакеты между интерфейсами и не может работать как роутер. Неправильное использование такой конфигурации может привести к открытию клиентских сетей напрямую в интернет.

    Отключить любое из VPN соединений можно посылкой сигнала "HUP" соответствующему процессу openconnect.

    Я надеюсь что эта заметка сделает вашу работу более удобной и покажет на примере что же происходит "за кулисами" VPN подключения. Как мы уже видели, просто создания туннеля и соответствующего устройства недостаточно. Нам необходимо понять работу и организацию клиентских сетей и внести изменения в маршрутизацию. При этом стандартные VPN клиенты часто нарушают работоспособность нашей собственной сети, делая дальнейшую работу невозможной.

    Спасибо что зашли, Будьте благословенны! Денис

    16 Декабря 2013 года.