Настройка VPN (использование pptpclient)

Часто задаваемые вопросы (FAQ)

Многие провайдера, т.н. ISP предлагают достув в интернет с использованием т.н. VPN. Это удобно для Windows машин т.к. настройка VPN соединения производится в этих ОС как обычно, ткунуть тут, ткнуть там, не забыть выбрать галочку на одной вкладочке, войти в контекстное меню в слудующем окошке итд.

Что же нам предоставляет Gentoo Linux? Исследование показало, что нам потребуется пакет net-dialup/pptpclient
и его ближайщие зависимости, например, net-dialup/ppp. Пакет pptpclient предоставляет "консольный" интерфейс для управления VPN сессиями (настройка, подключение, отключени). В качестве графической оболочки могу назвать пакет net-dialup/pptpconfig, но в данный момент он "нестабильный" т.е. замаскаирван как ~x86. Мало того я считаю, что GUI для такой простой задачи как запуск демона pppd совсвем не нужен, графичсеких библиотек может не быть, например, на сервере. Я решил, что для "выхода в Интернет" лучше справится скрипт подобный тем, что распаложенны в каталоге /etc/init.d. Таким образом, можно "включать" и "выключать" канал в Интернет стандартными средсвами не прибегая к несколько неудобному интерфейсу пакета pptpclient или даже включить запуск скрипта в процесс загрузки посредсвом утилиты rc-update. Ниже я приведу скрипт /etc/init.d/pptp который и реализует сервис VPN клиента на моих машинах и скромный конфигурационный файл с выбором провайдера, если их может быть несколько в традиционном месте /etc/conf.f/pptp.
Отмечу, что для работы VPN тунелей требуется поддержка протокола GRE в ядре.
Теперь немного о работе пакета pptpclient т.к. мой вариант стартового скрипта является лишь надстройкой над конфигурационными файлами получаемыми посредсвом утилиты pptp-command входящей в пакет pptpclient. И так с помощью утилиты pptp можно настроить набор конфигурационных файлов, можно также это сделать и "вручную" с использованием текстового редактора. Perl скрипт pptp-command позволает настоить тунел, установить соединение, прервать соединение. Приведу свои соображение что происходит, когда вы устанавливаете соединение с провайдером с помощью pptp-cmmand (опция меню - "start"). pptp-command главным образом от пользовате root запускает демон pppd, как говорят UNIX'оиды "поднимающий" сетевой интерфейс ppp (Point-to-Point-Protocol). Опции для запуска pppd извлекаются из конфигурационного файла описывающего вашего провайдера из каталога /etc/ppp/peers/. По умолчанию используется файл /etc/ppp/peers/__default, который является символической ссылкой на текстовый файл. Рассмотрим пример такого файла описывающего моего провайдера под номером #0:
cat /etc/ppp/peers/vpn.0

#
# PPTP Tunnel configuration for tunnel azorg
# Server IP: 192.168.7.254
# Route: add default TUNNEL_DEV
#

#
# Tags for CHAP secret selection
#

name azorg
remotename bastion

#
# Include the main PPTP configuration file
#
file /etc/ppp/options.pptp

Из файла видно, что используется имя (мой логин) 'azorg', имя ответной части bastion.
Остальные многочисленные опции для pppd извлекаются из файла "/etc/ppp/options.pptp".
Таким образом, можно использовать одни и теже опции при использовании нескольких провайдеров.
Прочитать про опции pppd можно выполнив `man pppd`.

Приведу пример опций, которые я использую при соединении со своим провайдером.
cat /etc/ppp/options.pptp[b]

# Указать программу для общения с сервером.
# Здесь можно указать IP-адрес PPTP сервера.
# Так же можно указать это при вызове pppd.
# Надо отметить, что при "штатном" использовании программы pptp-command
# из пакета pptpclient указания данной опции НЕ требуется!
# Адрес сервера извлекается из комментариев в соответсвующих
# файлах /etc/ppp/peers/*
#pty "/usr/sbin/pptp 192.168.7.254 --nolaunchpppd"

# name in chap-secrets
# имя клиента в файле /etc/chap-secrets
# НЕ указывать! Оно указано в соответвующем
# файле /etc/ppp/peers/*
#name azorg

# turn pppd syslog debugging on
# Включить подробный отчет о соединении в логах
#debug #!!! раскоменируйте для поробных логов в случае проблемм

# Lock the port
# Попросить pppd блокировать последовательное устройство, используемое
# для соединения, для эксклюзивного использования
lock

# We don't need the tunnel server to authenticate itself
# Не требовать аутентификации от сервера, это сервер аутентифицирует нас
noauth

# Turn off transmission protocols we know won't be used
# Запретить использование BSD-компрессии
nobsdcomp

# Устанавливаем метод сжатия пакетов в 0.
nodeflate

# При разрыве соединения не завершать работу, а продолжать
# попытки соединения.
persist

# Прекратить попытки автосоединения после 5000 неудач.
#maxfail 5000

# Подождать 10 секунд после разрыва соединения перед
# повторным соединением
holdoff 10

# Если это не указать, параметр holdoff игнорируется
connect /bin/true

#
# Time this thing out of it goes poof
#
# Каждые 15 секунд посылать запросы серверу для проверки соединения
#lcp-echo-interval 15
# После 10 неудачных запросов разорвать соединение
#lcp-echo-failure 10

# We want MPPE
#mppe-40
#mppe-128
#mppe-stateless

# We want a sane mtu/mru
mtu 1000
mru 1000

Конечно мои настройки могут и не подойти вам. Начните с того, что попробуйте с настройками Gentoo по-умолчанию. Здесь не обсуждаеются вопросы использования шифрования и сжатия при использовании VPN соединений. Внимательный читатель, что IP фдрес сервера моего провайдера (192.168.5.2) был указан в коментарии в файле "/etc/ppp/peers/vpn.0", а в /etc/ppp/options.pptp опция "pty" закоментирована. Сделано это не спроста! Так работает pptp-command! Уж простите, не я придумал. pptp-command извлекает адрес сервера из файла иписывающего провайдера (что и логично) и подсовывает его pppd, а фалй "options.pptp" может быть один для нескольких провайдеров.
После успешного "поднятия" интерфейса ppp, который можно проконтролировать с помощью утилиты ifconfig запускается скрпипт "/etc/ppp/etc/ppp/ip-up", который в моем Gentoo "из коробки" вызывает скрипт "/etc/ppp/ip-up.local", который я и использовал для своих целей настроийка маршруто по-умолчанию. Я решил, что первый ppp интерфейс, (т.е. ppp0) это и есть соединение с провайдером. Какой IP адрес мне дает провайдер я узнал с помощью ifconfig (можно было этого и не делать). Теперь привожу cвой "/etc/ppp/ip-up.local" в качестве примера.
[b]cat /etc/ppp/ip-up.local[b]
#!/bin/sh

# the followings parameters are available:
# $1 = interface-name      ('ppp0')
# $2 = tty-device          ('/dev/pts/2' or '')
# $3 = speed               ('115200')
# $4 = local-IP-address
# $5 = remote-IP-address
# $6 = ipparam             ('' ???)

export PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin

# if ppp0 is external interface set it to default route
if [ "$5" = "172.16.1.254" ] ||
   [ "$5" = "10.1.1.254" ] ||
   [ "$5" = "192.168.254.254" ]
then
  if [ "$1" = "ppp0" ]; then
    #echo "-$1-$2-$3-$4-$5-$6-" >> /_ppp_ #!!! debug
    route del $5
    [ -n "$(route -n | awk '{print $1}' | grep '0.0.0.0')" ] && route del default
    route add default dev $1
  fi
fi

Отмечу сразу, что 172.16.1.254, 10.1.1.254 и 192.168.254.254 это IP адреса которые мне могут назначать мои провайдеры. Необходимость включения такого `if` возникла по причине того, что на моей машине могут "подниматься" и другие "серверные" ppp интерфейсы (ppp1, ppp2, ppp3, итд) в случаях в которых мой хост является сервер-провайдером для домашних ПК в домашней сети, конечно в простейшем случае, если у вас нет шлюза по-умолчанию (указанного например в /etc/conf.d/net), то вам хватит строчки с `/sbin/route add default dev $1`. Немного о DNS, я использую фиксированный DND сервер, который указал в "/etc/resolve.conf", а "лишний" код получения IP адреса DNS от провайдера в сценарии "/etc/ppp/ip-up" я закоментировал.
При рызрыве соединения (при падении интерфейса ppp0) в моем Gentoo Linux запускаются скрипты "/etc/ppp/ip-down" и "/etc/ppp/ip-down.local" соответсвенно. Вот мой "/etc/ppp/ip-down.local", для примера:
[b]cat /etc/ppp/ip-down.local
#!/bin/sh

# the followings parameters are available:
# $1 = interface-name      ('ppp0')
# $2 = tty-device          ('/dev/pts/2' or '')
# $3 = speed               ('115200')
# $4 = local-IP-address
# $5 = remote-IP-address
# $6 = ipparam             ('' ???)

# Default gateway if ppp0 unavaiable
#GATEWAY="192.168.30.254"

export PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin

# if ppp0 was external interface set another default route
if [ "$5" = "172.16.1.254" ] ||
   [ "$5" = "10.1.1.254" ] ||
   [ "$5" = "192.168.254.254" ]
then
  if [ "$1" = "ppp0" ]; then
    if [ -n "$GATEWAY" ]; then
      [ -n "$(route -n | awk '{print $1}' | grep '0.0.0.0')" ] && route del default
      route add default gw $GATEWAY
    fi
  fi
fi

Теперь о том, что же я предлагаю. Вот обещанный initrc скрипт для соединения с провайдером:
cat /etc/init.d/pptp

#!/sbin/runscript
# System init script for start/stop PPTP based VPN client under Gentoo Linux
# (C) 2004 Alex Zorg
# Distributed under the terms of the GNU General Public License v2
# Config is in /etc/conf.d/pptp

opts="start stop"

depend() {
  before ntp-client
  need net
}

checkconfig() {
  if [ ! -x "$(which pppd)" ] ||  [ ! -x "$(which pptp)" ] ||
     [ ! -x "$(which ifconfig)" ]
  then
    eerror "pppd, pptp, ifconfig needs to be installed (pptpclient package)"
    return 1
  fi

  if [ "${FUNCT}" = "start" ] &&
     [ -e "/var/run/ppp-ppp0.pid" -o -e "/var/run/ppp0.pid" ]
  then
    eerror "ppp0 is already up"
    return 1
  fi

  PEER=${PEER:-'__default'}
  PEER_FILE="/etc/ppp/peers/$PEER"

  if [ ! -f "$PEER_FILE" ]; then
    eerror "Error of config pptp! Can't read '$PEER_FILE' file"
    return 1
  fi

  PEER_IP=`grep "Server IP:" "$PEER_FILE" | \
           sed 's/^.*Server IP: *//' | awk '{print $1}'`

  if [ -z "$PEER_IP" ]; then
    eerror "Can't specify 'Server IP:' from '$PEER_FILE!'"
    return 1
  fi
}

start() {
  checkconfig || return 1

  ebegin "Starting pptp  (VPN based client) Connect to $PEER_IP"
    if [ -n "$(ifconfig | grep ppp0)" ]; then
      ewarn "Interface ppp0 seems to be already up"
      exit 1
    fi

    # bringing ppp0 up over PPTP-tunnel (VPN)
    pppd pty "/usr/sbin/pptp $PEER_IP --nolaunchpppd" call "$PEER"
  eend $?
}

stop() {
  checkconfig || return 1

  ebegin "Stopping pptp  (VPN based client)"
    if [ -z "$(ifconfig | grep ppp0)" ]; then
      ewarn "Interface ppp0 seems to be already down"
    else
      ifconfig ppp0 down
    fi

    if [ -e /var/run/ppp-ppp0.pid ]; then
      kill $(grep -v "ppp0" /var/run/ppp-ppp0.pid)
    elif [ -e /var/run/ppp0.pid ]; then
      kill $(grep -v "ppp0" /var/run/ppp0.pid)
    fi
  eend $?
}

Если не существует символическая ссылка /etc/ppp/peers/__default на файл провайдера, например "/etc/ppp/peers/vpn.0", то файл провайдера можно указать в файле "/etc/conf.d/pptp", привожу для примера:
cat /etc/conf.d/pptp
# /etc/conf.d/pptp
# Config file for /etc/init.d/pptp
# (C) 2004 Alex Zorg
# Distributed under the terms of the GNU General Public License v2

# Define peer (aka ISP)
# by default used /etc/ppp/peers/__default symbolic link
# For setup your Poin-To-Point connection you may use pptp-command
#PEER="MyISP"
#!!!
PEER="vpn.0"

Надеюсь я помог Русскому сообществу Gentoo Linux. А еще бы хорошо, чтобы подобный скрипт включили при установке пакета pptpclient его руководитли. Был приятно удивлен, когда обнаружил в один прекрасный момент после обновления Gentoo сценарий "/etc/init.d/pptpd", который был почти что копией того скрипта (и назывался так же!), который я использовал для "поднятия" VPN серверов.

Ой-Ой-Ой! Сколько ошибок! Пазор!

новое

Хотел бы исправить ошибки, но интерфейс drupal мне это не позволяет? Как же быть, как же быть? Подправлю сначало статью на www.devlab.ru и сообщю ссылку: http://devlab.ru/node/10

новое

Кинь исправленный вариант тут в комменты, а я поменяю... твой www.devlab.ru не открывается
_________________
GNU/Wonderland -- GNU/Страна чудес, страна, в которой вы часто бываете, но, в которую, что примечательно, не надо оформлять визу.