Несколько различных VPN подключений с локальными DNS серверами

от автора

Откуда появилась проблема

Многие из вас пользуются VPN подключением к рабочей локальной сети из дома.
Благодаря этому, подключив VPN вы работаете с рабочей сетью «как будто находясь в ней».

Как выглядит типичная настройка в linux?
В /etc/resolv.conf прописывается (при помощи openresolv или NetworkManager)

search local.company.name nameserver 10.0.20.186 

Где local.company.name — домен компании, а 10.0.20.186 — ip адрес локального (в рабочей сети) DNS сервера.

Как выглядит работа?

root@t510 0 /usr/share/openvpn # ping -c 1 cdash-master PING cdash-master.local.company.name (10.0.20.237) 56(84) bytes of data. 64 bytes from 10.0.20.237: icmp_seq=1 ttl=63 time=214 ms ... 

Что произошло?

  1. search добавил к cdash-master суффикс local.company.name
  2. DNS сервер в рабочей сети преобразовал cdash-master.local.company.name в 10.0.20.237

Всё прекрасно работает, пока у вас VPN подключение… одно.
Мне захотелось подключать одновременно два VPN и прописывать два DNS — один для рабочей сети, другой для локальной сети на hetzner, где крутятся мои виртуальные машины.

Казалось бы, что может быть проще? Однако путь к решению был долгим и извилистым.

Подробное описание результата

Рабочая сеть

Локальная подсеть — 10.0.20.0/24 (т.е. 10.0.20.* — из подсети)
Домен — *.local.company.name
DNS сервер — 10.0.20.186

ping -с 1 somename  

должен определить somename как somename.local.company.name, а somename.local.company.name превратить в IP адрес через DNS 10.0.20.186

Если VPN подключение выключено — имя не будет найдно

Личный сервер на hetzner

С ним всё немного хитрее

Локальная подсеть — 10.10.10.0/24 (т.е. 10.10.10.* — из подсети)
Домен — *.my.domain
Локальный DNS сервер — 10.10.10.253

Сервер my.domain имеет белый IP адрес и доступен извне
На сервере стоит nginx, который проксирует запросы вида subdomain.my.domain машинам из локальной подсети.

С одной стороны, если пользователь зашёл браузером на subdomain.my.domain, то DNS сервера регистратора вернут белый IP адрес my.domain, браузер отправит по данному IP адресу HTTP запрос, и дальше nginx разберётся куда его проксироват.

С другой стороны, при включенном VPN мои подключения вида:

ssh subdomain 

должны попадать напрямую на машину из локальной подсети.
Зачем?

Мне так удобно. Я один раз настроил рабочую машину, и прозрачно гуляю по рабочей сети и личной сети.
Снаружи по *.my.domain пользователи видят ровно один сервер (который по совместительству и VPN) и к локальным машинам доступа не имеют
Я же могу напрямую подключать по ssh как к машинам из рабочей сети, так и из личной

«Подожди», скажет мне юзер.
«Я просто пропишу /etc/resolv.conf»:

search local.company.name my.domain 

И всё будет работать.

Не будет. Для каждой зоны — local.company.name и my.domain требуется прописать свой DNS сервер. Через resolv.conf, openresolv эта проблема не решается.

Решение

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

Итак, прежде всего нужно поставить bind. Рабочая машина у меня на Arch Linux:

pacman -S bind systemctl enable named 

Дальше настраиваем /etc/named.conf, добавляет туда

zone "local.company.name" IN { 	type forward; 	forwarders { 10.0.20.186; }; };  include "/usr/share/openvpn/named.conf.my.domain";  zone "." IN { 	type forward;         forwarders { 8.8.8.8; 8.8.4.4; }; }; 

Настраиваем NetworkManager либо редактируем /etc/resolv.conf. Результатом в обоих случаях должен быть:
root@t510 0 /usr/share/openvpn # cat /etc/resolv.conf

# Generated by NetworkManager search local.company.name my.domain nameserver 127.0.0.1 

В openvpn скрипт для my.domain добавляем

up "/usr/share/openvpn/update-dns-my.domain" down "/usr/share/openvpn/update-dns-my.domain" 

Добавляем скрипт /usr/share/openvpn/update-dns-my.domain который будет обновлять настройки bind и перезапускать его после установления VPN подключения

#!/bin/bash  set -eu  NAME=/usr/share/openvpn/named.conf.my.domain TEMPLATE=${NAME}.template  function restart_bind () {     /usr/bin/systemctl restart named }  case $script_type in     up) 	cat ${TEMPLATE} > ${NAME} 	restart_bind 	;;     down) 	cat /dev/null > ${NAME} 	restart_bind 	;; esac 

Добавляем /usr/share/openvpn/named.conf.my.domain.template

zone "my.domain" IN {      type forward;      forwarders { 10.10.10.253; }; }; 

Как это работает?

При установлении VPN подключения к личному серверу:

  1. openvpn запускает скрипт /usr/share/openvpn/update-dns-my.domain
  2. скрипт в файл /usr/share/openvpn/named.conf.my.domain записывает содержимое /usr/share/openvpn/named.conf.my.domain.template
  3. скртипт перезапускает bind
  4. bind вычитывает настройки зоны my.domain из обновлённого файла

При отключении VPN подключения

  1. openvpn запускает скрипт /usr/share/openvpn/update-dns-my.domain
  2. скрипт очищает содержимое /usr/share/openvpn/named.conf.my.domain.template
  3. скртипт перезапускает bind
  4. bind вычитывает настройки зоны my.domain из обновлённого файла (забывает про зону)
  5. зона my.domain теперь ресолвится общедоступными DNS

Как это выглядит на практике?

root@t510 0 /usr/share/openvpn # ping -c 1 cdash-master PING cdash-master.local.company.name (10.0.20.237) 56(84) bytes of data. 64 bytes from 10.0.20.237: icmp_seq=1 ttl=63 time=214 ms ...  root@t510 0 /usr/share/openvpn # ping -c 1 db PING db.my.domain (10.10.10.200) 56(84) bytes of data. 64 bytes from 10.10.10.200: icmp_seq=1 ttl=63 time=233 ms ...  root@t510 0 /usr/share/openvpn # systemctl stop openvpn@hetzner    root@t510 0 /usr/share/openvpn # ping -c 1 db                   PING db.my.domain (178.63.28.181) 56(84) bytes of data. 64 bytes from wesnoth.in (178.63.28.181): icmp_seq=1 ttl=55 time=124 ms ...  root@t510 0 /usr/share/openvpn # systemctl start openvpn@hetzner   root@t510 0 /usr/share/openvpn # ping -c 1 db                    PING db.my.domain (10.10.10.200) 56(84) bytes of data. 64 bytes from 10.10.10.200: icmp_seq=1 ttl=63 time=118 ms ... 

Забавно, что для получения такого простого поведения пришлось проделать столько работы.

ссылка на оригинал статьи http://habrahabr.ru/post/182924/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *