… Казалось бы, что может пойти не так?
Недавно мне потребовалось соеденить две площадки с виртуалками. Обе у нас (ПОДЧЕРКИВАЮ!), обе у достаточно крупных провайдеров. В общем, надо сделать так, чтобы Н машин у одного провайдера видели М машин у другого. Трафик не большой, но достаточно критичный.
“ХА!” – сказал я и нарисовал классическую схему соединения.
Выделяем на каждой площадке машинку (или на одну из доступных вешаем внешний ip), обвешиваемся файрволами и закрываем трафик тем же IPSec. Инструкций много, вариантов много – в общем, прорвемся!
Быстренько собрал, накидал конфиги и получил веслом по морде. Протокол ESP где-то по пути заблокирован. Техподдержка обоих провайдеров клянется, что это не у них, но ipsec не верит и отказывается подниматься. Ладно, хотелось по-корпоративному, пойдем по-молодежному.
OpenVPN шустро поднялся, поначалу начал бодро гонять трафик, но через некоторое время начались проблемы. Он переподсоединялся, слал немного байт и снова уходил в нирвану. Смена протокола с UDP на TCP приносила лишь временное облегчение.
Кто виноват – мне, если честно говорить, абсолютно пофиг. Мне трафик нужно гонять. Поэтому расчехлил тяжелую хипстерскую артиллерию – shadowsocks + v2ray. Качаем с гита, просто распаковываем, плюем в конфиг сервера следующее (1.1.1.1 – это внешний адрес сервера, если что):
{
"server": "1.1.1.1",
"server_port": 888,
"password": "verysecretpass",
"method": "chacha20-ietf-poly1305",
"timeout": 7200,
"no_delay": true,
"fast_open": true,
"mode": "tcp_and_udp",
"plugin": "/opt/shadowsocks/v2ray-plugin_linux_amd64",
"plugin_opts": "server"
}
А в конфиг клиента вот это:
{
"server": "1.1.1.1",
"server_port": 888,
"local_address": "127.0.0.1",
"local_port": 1080,
"password": "verysecretpass",
"method": "chacha20-ietf-poly1305",
"timeout": 7200,
"no_delay": true,
"fast_open": true,
"mode": "tcp_and_udp",
"plugin": "/opt/shadowsocks/v2ray-plugin_linux_amd64",
"plugin_opts": ""
}
Запускаем и получаем на клиенте socks5 сервер на 1080 порту. А теперь – финт конем. В конфиг OpenVPN на клиенте добавляем одну единственную строчку:
socks-proxy 127.0.0.1 1080
Ну и перезапускаем все, чтобы прочитало конфиги. Вуаля! У нас получилась следующая схема:
OpenVPN ходит через ShadowSocks, который ходит через хрен знает как настроенный интернет.
Но через некоторое время проявилась та же самая боль: немного погодя клиент терял соединение с сервером. Причем перезапустишь – все снова начинает бегать. Ставил опции ping
, менял MSS и MTU – пофиг: рандомно теряем коннект.
Ок, перевел openvpn и shadowsock на TCP. Всё магически исправилось. Коннект стабильный, не рвется, пакетики бегают туда-сюда.
Отключил "mode": "tcp_and_udp"
, позакрывал фаирволлами и начал тестить.
Итак, прямой tcp линк безо всяких штук
[ 1] 0.0000-10.2561 sec 112 MBytes 91.8 Mbits/sec
Да, клиент сидит на дешевом тарифном плане в 100 мегабит, поэтому практически упираемся в полку. Теперь через все эти навороты:
[ 1] 0.0000-10.3474 sec 50.8 MBytes 41.1 Mbits/sec
И это без какого-либо тюнинга! Да, tcp-over-tcp-over-tcp еще тот изврат, но ведь работает же! А после тюнинга (банальные буфера и прочее – в любом мануале по openvpn) я получил следующее:
[ 1] 0.0000-100.4276 sec 896 MBytes 74.8 Mbits/sec
Что в плюсах:
- Нам надо платить меньше. На одной стороне не нужен выделенный ip (а они нынче дорогие). Выпускают всех через SNAT и норм.
- Настраивается не просто, а очень просто.
- Снаружи на сервере порт OpenVPN можно спокойно закрыть фаирволлом. Соединение идет с локалхоста. Больше сесуретей богу сесурити!
- Память не жрет. Можно смело брать самую дешевую виртуалку под “роутеры”. Вся вот эта машинерия + FRR с OSPF сьели 200 мегов.
- Оно работает. Реально, за неделю уже не одиного разрыва.
Что в минусах:
- Потеряли в скорости. Немного, но есть. Проблема в том, что на стороне клиента я банально уперся в единственный ЦПУ виртуалки. Когда тесты идут, на той стороне в топе такое:
С другой стороны, там трафик в 20-30 мегабит уже редкость, так что в любом случае все в порядке. Но запас карман не тянет.
Ну и нафига я все это делал: мне нужно было среплицировать один MySQL в другой. Предложенная схема их удовлетворила, значит задача выполнена.