Pull to refresh

Как мы снижали пинг с помощью OpenVPN

Network technologies *
Sandbox
Привет, %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

<
Tags:
Hubs:
Total votes 20: ↑13 and ↓7 +6
Views 93K
Comments Comments 20