Пользователь
0,0
рейтинг
14 декабря 2012 в 03:55

Администрирование → Как мы снижали пинг с помощью OpenVPN из песочницы

Привет, %username%. Все началось с полуночного звонка в скайп. Суть была такова: «Зять, у меня пинг в игре высокий, помоги». И вот решил помочь. Инструментом помощи стал OpenVPN. Под катом будет много текста, немного конфигов и пояснение сути проблемы. И хотя подобных мануалов уже очень много, некоторые подводные камни в них не описаны, что и послужило поводом написать данный.

Итак, проблема высокого пинга актуальна для всех клиентов украинского провайдера «УкрТелеком» (Сразу замечу, смена провайдера не вариант решения проблемы, по причине частного сектора, где альтернатив, за разумные деньги, нет). С Харькова до Москвы пинг проходит чуть больше 100 мс. По результатам трассировки было видно, что связь идет через, то ли Германию, то ли Швейцарию, в которых была потеря около 50 мс. «Хм» — подумал я, и решил исправить это дело. Письма и звонки провайдеру ничего не дали, ответ был один: «Маршрут менять нельзя». Ну, где наша не пропадала?! Решено: OpenVPN сервер в Киеве (до него связь прямая) с прямым маршрутом до Москвы. Забегая вперед, сообщу, что пинг снизился в 2 раза, с 100-120 до 50-60 мс.

Задача:
  • OpenVPN сервер с базовыми настройками
  • OpenVPN клиент на Windows машине, настроенный так, что бы весь трафик шел по стандартному маршруту и только трафик к определенной подсети шел через сервер (дабы не засорять канал сервера всякими торрентами, ведь мы потом на него ещё что-нибудь прикрутим)
  • Организовать аутентификацию не только по сертификатам, но и по паре «логин: пароль». Ну не верит наш тесть в надежность «каких-то там» сертификатов, а [sarcasm]логин-пароль – это да, это надежно[/sarcasm]


Все настройки касаются Ubuntu 11.04 на серверной стороне и Windows 7 на клиенте.
Итак, для начала оформляем заявку на тест VDS или VPS сервера. Как оказалось, у техподдержки лучше сразу уточнить, включен модуль «tun» в ядре Ubuntu на их VDS или VPS. А то мне пришлось настраивать второй сервер с нуля, так как в первом банальное «ограничение технологии OpenVZ», как сказал мне саппорт. Хотя об этом нюансе ни в одном мануале так и не увидел. В итоге -4 часа времени(2 на ожидании подтверждения заявки на тест сервера, ещё 1 на настройку и ещё 1 на «почему оно не работает»).

Сервер


Основы настройки сервера под управлением Ubuntu не пишу, этого добра и так в сети валом. Поэтому сразу к делу.
Для начала устанавливаем сам OpenVPN:
 apt-get install openvpn

После этого приступаем к созданию сертификатов для сервера и клиента.
cd /usr/share/doc/openvpn/examples/easy-rsa/2.0/

Можно сменить переменные(что не обязательно, в принципе)
vi ./vars #сам файл переменных
export KEY_SIZE=1024 #длина ключа, оставляем по-умолчанию, так как у нас онлайн игра, а не сервер ЦРУ
export KEY_EXPIRE=3650 #сколько будет действителен сертификат в днях. Думаю, этих 10 лет нам хватит с головою
#дальше можем внести немного приватной информации
set KEY_COUNTRY=UA
set KEY_PROVINCE=KH
set KEY_CITY=Kharkov
set KEY_ORG=Zadrot`s_Home
set KEY_EMAIL=mail@host.domain


#настоятельно рекомендую глянуть параметр и запомнить или записать имя файла, которое указано здесь, так как у меня именно этот параметр вызывал ошибку (и опять же, ни в одном мануале… эх)
KEY_CONFIG=***.cnf

Далее генерируем несколько сертификатов. Сразу предупреждаю, если сертификаты не хотят генерироваться, проверьте, есть ли файл именем, указанном в параметре «KEY_CONFIG», в этой директории. А то у меня в параметре было прописано «openssl.cnf», а в директории было несколько файлов «openssl-0-9-0.cnf», «openssl-1.0.0-old.cnf» и так далее. Я просто взял и переименовал «openssl-1.0.0.cnf» в «openssl.cnf» и, о чудо, заработало.
 ./build-ca			
./build-key-server server	
./build-dh
# переносим их в /etc/openvpn/
mv ./keys/ca.crt  /etc/openvpn
mv ./keys/server.crt  /etc/openvpn
mv ./keys/server.key  /etc/openvpn
mv ./keys/dh1024.pem  /etc/openvpn

# и генерируем сертификаты для пользователей
./build-key-pkcs12 gamer   #вместо gamer указываем любе имя пользователя, и запоминаем Export password, он нам понадобится ещё


Приступаем к настройке самого сервера
# копируем и распаковываем “образец“ конфига
cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/

gzip –d server.conf.gz
# начинаем править сам конфиг файл
Vi server.conf
# менять нам надо самую малость
    local внешний_ip_сервера

push "redirect-gateway def1 bypass-dhcp" # если хотите направить ВЕСЬ трафик через наш сервер, то раскомментируем эту строку

#можно прописать свои dns сервера, которые будут передаваться клиенту при подключении(сработает легко только для Windows клиентов, для других танцы с бубном на стороне клиента, о чем тоже часто забывают в мануалах)
  push "dhcp-option DNS *.*.*.*"
  push "dhcp-option DNS *.*.*.*"

verb 6 # эта строка указывает серверу вести более детальные логи, чем по умолчанию. Полезно для отлова ошибок после настройки

# Так же для аутентификации по логину-паролю добавляем, если Вам это не нужно - пропускайте
auth-user-pass-verify /etc/openvpn/verify.sh via-file # Передаем проверку логина и пароля скрипту
#client-cert-not-required # Раскомментируйте, если хотите аутентификацию только по логину-паролю, без клиентских сертификатов
username-as-common-name # Комментировать, если не используется аутентификация по логину-паролю
tmp-dir /etc/openvpn/tmp # Не забываем сами создавать папку командой “mkdir tmp”
script-security 2


Далее создаем скрипт verify.sh который и выполняет проверку логина и пароля.
Под спойлером текст скрипта
verify.sh
#!/bin/sh
## format: username:password username:password ...
## you can even have same usernames with different passwords
# USERS='user1:pass1 user2:pass2 user3:pass3'
## you could put username:password in
## a separate file and read it like this
USERS=`cat /etc/openvpn/user.pass`
vpn_verify() {
if [ ! $1 ] || [ ! $2 ]; then
#echo "No username or password: $*"
exit 1
fi
## it can also be done with grep or sed
for i in $USERS; do
if [ "$i" = "$1:$2" ]; then
## you can add here logging of users
## if you have enough space for log file
#echo `date` $1:$2 >> your_log_file
exit 0
fi
done
}
if [ ! $1 ] || [ ! -e $1 ]; then
#echo "No file"
exit 1
fi
## $1 is file name which contains
## passed username and password
vpn_verify `cat $1`
 #echo "No user with this password found"
 exit 1

И делаем его исполняемым: chmod +x verify.sh
Создаем файл user.pass в формате “user1:pass1 user2:pass2 и тд” через пробел.


И финальный аккорд – настройка NAT и добавление в автозапуск
vi /etc/sysctl.conf
net.ipv4.ip_forward=1 # раскомментируем строку
vi /etc/rc.local
# вписываем следующее:
iptables -A FORWARD -s 10.8.0.0/24 -j ACCEPT
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE #интерфейс может быть другой, проверяем ifconfig

Ну что же, сервер готов, можем перезагружать его и настраивать клиент.

Клиент


Для начала устанавливаем OpenVPN для Win. Так как конечный пользователь нашего «сервиса» (он же «Тесть») слабо подкован в околокомпьютерной тематике, в настройках ярлыка ставим «Запуск от имени администратора», что бы не щелкать каждый раз ПКМ(в противном случае не прописываются маршруты)
Вытягиваем по SSH или FTP с нашего сервера файлы:
/usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/ca.crt
/usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/gamer.crt
/usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/gamer.csr
/usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/gamer.key
/usr/share/doc/openvpn/examples/easy-rsa/2.0/keys/gamer.p12

И копируем их в
%ProgramFiles%\OpenVPN\config

Там же создаем файл обычный текстовый config.ovpn со следующим содержанием:
# 123123
Client # указываем программе режим работы клиент
dev tun 
proto udp
remote *.*.*.* 1194 #сообщаем ip и порт нашего сервера(через пробел)
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt #имя корневого сертификата
cert client.crt #имя сертификата клиента
key client.key #имя ключа клиента
comp-lzo
verb 3
remote-cert-tls server
pull
route 109.105.0.0 255.255.0.0 #маршрут к подсети серверов нашей игры, если не добавить, то весь трафик пойдет через OpenVPN, а не только игровой
auth-user-pass #если не нужна аутентификация через логин-пароль, то комментируем строку 


Ну что же, все готово, перезагружаем сервер, и пробуем подключится к нему через иконку OpenVPN в трее клиента и соответствующий пункт «Подключится». Вводим пароль от сертификата, логин, пароль и вуаля:



Проверка до и после подключения к нашему серверу:
Было
Обмен пакетами с pointblank.ru [109.105.130.101] с 32 байтами данных:
Ответ от 109.105.130.101: число байт=32 время=107мс TTL=245
Ответ от 109.105.130.101: число байт=32 время=111мс TTL=245
Ответ от 109.105.130.101: число байт=32 время=104мс TTL=245
Ответ от 109.105.130.101: число байт=32 время=108мс TTL=245

Статистика Ping для 109.105.130.101:
Пакетов: отправлено = 4, получено = 4, потеряно = 0
(0% потерь)
Приблизительное время приема-передачи в мс:
Минимальное = 104мсек, Максимальное = 111 мсек, Среднее = 107 мсек


Стало
Обмен пакетами с pointblank.ru [109.105.130.101] с 32 байтами данных:
Ответ от 109.105.130.101: число байт=32 время=55мс TTL=248
Ответ от 109.105.130.101: число байт=32 время=55мс TTL=248
Ответ от 109.105.130.101: число байт=32 время=58мс TTL=248
Ответ от 109.105.130.101: число байт=32 время=55мс TTL=248

Статистика Ping для 109.105.130.101:
Пакетов: отправлено = 4, получено = 4, потеряно = 0
(0% потерь)
Приблизительное время приема-передачи в мс:
Минимальное = 55мсек, Максимальное = 58 мсек, Среднее = 55 мсек


Все довольны, пинг упал с 107 мс до 55 мс.

Итоги



Что мы получили:
  • Уменьшение пинга до Москвы в 2 раза
  • Сервер OpenVPN, которым мы можем пользоваться не только для первоначальных целей, но и как личный шифрованный канал
  • Довольного как пластилиновый слон тестя.


Потрачено:
  • Часа 2 чистого времени (при условии, что не столкнетесь с некоторыми граблями, описанными в посте)
  • 6$/мес на VDS сервер


Вывод: Все довольны, все работает уже 2 недели, без единого сбоя.

PS: Прошу указать мне на мои ошибки (как грамматические, так и все прочие), допущенные в этом посте.

UPD: Как заметил psyX, что бы добавить возможность одновременного подключения клиентов с одинаковыми сертификатами, нужно в файл server.conf добавить строку:
 duplicate-cn

<
Дмитрий Кожин @DimaZZ
карма
28,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Администрирование

Комментарии (19)

  • –4
    А почему не подключиться через обычный pppoe? В винде оно по умолчанию есть.
    • +5
      PPPoE — это VPN, который будет работать только через L2-сегмент. Он не позволяет поднимать тунели до L3-connected серверов.
      Ваш вопрос был бы правильнее, если бы спросили, почему не L2TP или PPTP — это как раз те L3-VPN, которые есть по умолчанию в Windows.
      • 0
        PPPoE можно поднять через L3, правда, через жопу.
  • 0
    Этот комментарий был удален.
  • –4
    100-120 мс — большой пинг… да Вы видимо просто не знаете что такое большой пинг…
    • +1
      … да Вы видиом просто не знаете что такое шутеры PointBlank?
  • +7
    В который раз мы видим стандартный мануал по настройке openvpn, только под другим названием…
    • 0
      Спасибо за замечание, но ведь именно в тексте поста я указал, что есть далеко не одни грабли, которые не описаны ни в одном мануале в сети. Скажу Вам честно, вместо 2-х часов на настройку, потратить 6-7 из-за отлова таких мелких глюков, было совсем не круто. Пост изначально направлен на людей не сталкивающихся с VPN до этого. А опытные и без этого поста разберутся
  • 0
    Эх, помню кваку вторую и инет через диалап… Пинг 300 был за счастье, чаще 600-800. Упреждение до автоматизма доходило.
    • 0
      [нытик mode =on]Даже немного завидую Вам, у меня тогда вообще интернета небыло
  • 0
    что будет, если два клиента с одним логином-паролем будут подключаться?
    • 0
      наверное, то же самое, что и с ключами — первый отключится, что бы этого не происходило надо в server.conf добавить duplicate-cn
      • 0
        Спасибо за такой нюанс, добавлю в статью
  • 0
    Можно было бы всё очень сильно упростить, если использовать режим point-to-point. Тогда вся конфигурация занимает три строки. Ну и easyrsa не нужен.
  • 0
    Клевый у вас тесть :)
  • 0
    Использование маскарадинга, при статическом IP является моветоном, нужно использовать SNAT:
    $IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source $INET_IP
    
  • 0
    для этих целей проще было Squid поднять, а клиенту Proxifier.
    • 0
      Proxifier не бесплатен, а мы за легальное ПО
  • 0
    Может ли автор или кто еще посоветовать конфигурацию и шаги для уменьшения потребления клиентом openvpn трафика и потребления процессорного времени, если этот клиент поднят на openwrt, соответственно имеем только tcp и невозможность заюзать comp-lzo?
    Роутер — mr3020.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.