Назад | Перейти на главную страницу

Как связать два (множественных) подключения к Интернету для повышения скорости и аварийного переключения

Мы находимся в сельской местности с двумя медленными ADSL-подключениями (3,5 / 0,5 Мбит / с) и хотели улучшить скорость и надежность подключения, как-то «объединив» их. Ниже описывается наше решение, которое пока работает очень хорошо.

Следовательно, это не вопрос, который нам нужно решать, а скорее документирование того, что работает, потому что было очень трудно найти инструкции, и я надеюсь, что это поможет кому-то еще в подобной ситуации. И, возможно, кто-то более продвинутый, чем я, обнаружит ошибку, о которой я был бы рад узнать и исправить.

Эта документация была составлена ​​на основе рабочей системы и должна быть немного скорректирована с учетом требований, специфичных для нашего местоположения, которые не имеют отношения к более общему описанию. Итак, хотя были предприняты все усилия для обеспечения надежной точности, я не переделывал всю эту документацию, поэтому может быть что-то упущено или неправильно. Оставьте комментарий, если это не сработает для вас, и я постараюсь помочь.

Следующие два источника очень помогли заставить это работать, поэтому сердечно благодарим обоих авторов!

Это решение применяет Linux Ethernet Bonding к двум независимым соединениям OpenVPN от локального сервера шлюза к серверу в облаке, к которому у вас есть root-доступ, например, Linode или DigitalOcean Droplet. Два подключения к Интернету, на которых основаны подключения OpenVPN, используют два маршрутизатора ADSL в режиме прозрачного моста, то есть мы используем только их функции модема и создаем подключения через драйвер PPP через Ethernet (PPPoE). И брандмауэры реализованы с FireHOL на обоих концах связанного соединения.

График дает обзор. Компьютеры в локальной сети подключены к eth0, 192.168.1.1/24, на сервере шлюза. Два маршрутизатора подключены через отдельные физические сетевые интерфейсы eth1, 192.168.10.1/24 и eth2, 192.168.11.1/24. (Не удалось заставить PPPoE работать с виртуальными интерфейсами на eth0.) Драйвер PPPoE создает интерфейсы ppp0 и ppp1 для индивидуальных подключений к ISP. OpenVPN привязывается к адресам 192.168.10.1/24 и 192.168.11.1/24 серверов шлюза на стороне LAN, а также к портам 1194 и 1195 интерфейса eth0 облачного сервера, 50.60.70.80/24. Затем эти два соединения OpenVPN связываются для создания виртуальных интерфейсов 10.80.0.2/30 на стороне LAN и 10.80.0.1/30 на стороне облачного сервера. Определение адреса 10.80.0.1 облачного сервера в качестве шлюза по умолчанию на сервере шлюза локальной сети позволяет всем компьютерам локальной сети получать доступ к Интернету почти в два раза быстрее, чем одно отдельное соединение PPPoE.

Следующая конфигурация основана на Ubuntu Server (здесь работает с 16.04 на стороне LAN и 18.04 на стороне облака). Все команды предполагают привилегии root.

Сторона облачного сервера

OpenVPN туннели

Установите последняя версия OpenVPN (заменить bionic за 18.04 с xenial для 16.04)

cloud-server# wget -O - https://swupdate.openvpn.net/repos/repo-public.gpg|apt-key add -
cloud-server# echo "deb http://build.openvpn.net/debian/openvpn/stable bionic main" > /etc/apt/sources.list.d/openvpn-aptrepo.list
cloud-server# apt update && apt install openvpn

В /etc/default/openvpn удостовериться

AUTOSTART="none"

активен. Отключить сервис, туннели будут управляться из /etc/network/interfaces:

cloud-server# systemctl disable openvpn

Создайте /etc/openvpn/tap0.conf

# disable encryption, traffic continues unencrypted anyways
auth none
cipher none

dev tap0
mode p2p
port 1194
local 50.60.70.80
proto udp

log /var/log/tap0.log
verb 3

ping 2
ping-restart 10
persist-tun

compress lz4-v2

daemon

и /etc/openvpn/tap1.conf лайк /etc/openvpn/tap0.conf Кроме

dev tap1
...
port 1195
...
log /var/log/tap1.log

Связывание Ethernet в Linux

С помощью ifupdown для управления сетью на облачном сервере измените свой /etc/network/interfaces (отрегулировать gateway для вашей среды):

auto eth0
iface eth0 inet static
  address 50.60.70.80
  netmask 255.255.255.0
  gateway 50.60.70.1
  post-up /usr/local/bin/vpn-start
  pre-down /usr/local/bin/vpn-stop

Опции для склеивающего устройства могут быть сохранены в /etc/modprobe.d/bonding.conf:

options bonding mode=0 miimon=100

mode=0 означает использовать связанные линии в циклическом режиме, который должен обеспечивать как аварийное переключение, так и повышение скорости.

Следующие два сценария создают / разрушают связывающее устройство. Создайте /usr/local/bin/vpn-startchmod +x):

#!/bin/bash
openvpn --config /etc/openvpn/tap0.conf
openvpn --config /etc/openvpn/tap1.conf

ip link add bond0 type bond
ip addr add 10.80.0.1/30 dev bond0

ip link set tap0 master bond0
ip link set tap1 master bond0

ip link set bond0 up mtu 1440
ip route add 192.168.1.0/24 via 10.80.0.2

Возможно, вам придется отрегулировать mtu в вашу среду. Создайте /usr/local/bin/vpn-stopchmod +x):

#!/bin/bash
ip route del 192.168.1.0/24 via 10.80.0.2
ip link set bond0 down
ip link del bond0

pkill 'openvpn'

Брандмауэр

Для ваших нужд брандмауэра вы можете установить FireHOL:

cloud-server# apt install firehol

Покинуть START_FIREHOL=NO в /etc/default/firehol и вместо этого создайте /etc/systemd/system/firehol.service

[Unit]
Description=FireHOL Stateful Packet Filtering Firewall
Documentation=man:firehol(1) man:firehol.conf(5)

DefaultDependencies=no

Before=network-pre.target
Wants=network-pre.target

Wants=systemd-modules-load.service local-fs.target
After=systemd-modules-load.service local-fs.target

Conflicts=shutdown.target
Before=shutdown.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/firehol start
ExecStop=/usr/sbin/firehol stop

[Install]
WantedBy=multi-user.target

и включите это

cloud-server# systemctl enable firehol

Создайте /etc/firehol/firehol.conf:

version 6

server_vpn_ports="udp/1194-1195"
client_vpn_ports="default"

snat4 to 50.60.70.80 outface eth0 dst not 50.60.70.80

interface eth0 web
  protection strong
  server ssh accept
  server vpn accept
  # more servers here as per your needs
  client all accept

interface bond0 vpn
  policy accept

router4 web2vpn inface eth0 outface bond0 dst 192.168.1.0/24,10.80.0.2
  client all accept

Активировать и проверить

Перезагрузите облачный сервер. Проверить склеивающее устройство:

cloud-server# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)

Bonding Mode: load balancing (round-robin)
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0

Slave Interface: tap0
MII Status: up
Speed: 10 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: aa:04:0b:ea:33:48
Slave queue ID: 0

Slave Interface: tap1
MII Status: up
Speed: 10 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 1e:70:4f:4b:2a:e8
Slave queue ID: 0

Сторона LAN

Подключение к Интернету PPPoE

Вам нужно будет выяснить для своих модемов, как перевести их в режим прозрачного моста и назначить адреса LAN. С помощью ifupdown для управления сетью на сервере шлюза LAN добавьте в /etc/network/interfaces:

auto eth1
iface eth1 inet static
  address 192.168.10.1
  netmask 255.255.255.0
  network 192.168.10.0
  broadcast 192.168.10.255

auto eth2
iface eth2 inet static
  address 192.168.11.1
  netmask 255.255.255.0
  network 192.168.11.0
  broadcast 192.168.11.255

Установите драйвер PPPoE:

lan-server# apt update
lan-server# apt install pppoe pppoeconf

Создайте два файла конфигурации PPP, /etc/ppp/peers/dsl1:

plugin rp-pppoe.so eth1
unit 0
user "YourUsername1"
noauth
hide-password
persist
mtu 1492
noipdefault
defaultroute
replacedefaultroute

и /etc/ppp/peers/dsl2:

plugin rp-pppoe.so eth2
unit 1
user "YourUsername2"
noauth
hide-password
persist
mtu 1492
noipdefault
defaultroute

replacedefaultroute в /etc/ppp/peers/dsl1 перед связыванием делает это соединение Интернет-соединением по умолчанию.

Введите пароли в /etc/ppp/chap-secrets и /etc/ppp/pap-secrets:

"YourUsername1" * "Password1"
"YourUsername2" * "Password2"

Убедитесь, что оба файла принадлежат root и chmod 600.

Добавьте в конец /etc/network/interfaces:

auto dsl1
iface dsl1 inet ppp
  provider dsl1

auto dsl2
iface dsl2 inet ppp
  provider dsl2

Это автоматически установит соединения PPPoE, как определено в файлах конфигурации, их имена даны provider директивы.

VPN-туннели и связывающее устройство управляются двумя сценариями, которые запускаются, когда два PPP-соединения устанавливаются / отключаются. Создайте /etc/ppp/ip-up.d/bond0chmod +x):

#!/bin/bash
nPpp=`ls -1 /etc/ppp/peers/* | wc -l`
if [[ `ip addr | grep -E 'ppp[0-9]:' | wc -l` -eq $nPpp ]] && \
    [[ `ip addr | grep -E 'tap[0-9]:' | wc -l` -eq 0 ]]; then
  /usr/local/bin/vpn-start
fi

и /etc/ppp/ip-down.d/bond0chmod +x):

#!/bin/bash
if [[ `ip addr | grep -E 'ppp[0-9]:' | wc -l` -eq 0 ]]; then
  /usr/local/bin/vpn-stop
fi

См. Ниже реализацию vpn-* скрипты.

OpenVPN туннели

Для установки OpenVPN действуйте как на облачном сервере. OpenVPN здесь будет управляться скриптами, запускаемыми при установке / разрыве PPPoE-соединений.

Создайте /etc/openvpn/tap0.conf

remote 50.60.70.80

auth none
cipher none

dev tap0
mode p2p
port 1194
local 192.168.10.1
proto udp

log /var/log/tap0.log
verb 3

ping 2
ping-restart 10
persist-tun

compress lz4-v2

daemon

и /etc/openvpn/tap1.conf лайк /etc/openvpn/tap0.conf Кроме

dev tap1
...
port 1195
local 192.168.11.1
...
log /var/log/tap1.log

Связывание Ethernet в Linux

/usr/local/bin/vpn-start (chmod +x) создает туннели VPN, настраивает устройство связывания и создает записи в таблице маршрутизации, которые гарантируют, что трафик проходит по нужным каналам в соответствии с запросами драйвера связывания:

#!/bin/bash
openvpn --config /etc/openvpn/tap0.conf
ip route add 192.168.10.0/24 dev eth1 scope link table dsl1
ip route add default dev ppp0 table dsl1
ip rule add pref 10 from 192.168.10.0/24 table dsl1

openvpn --config /etc/openvpn/tap1.conf
ip route add 192.168.11.0/24 dev eth2 scope link table dsl2
ip route add default dev ppp1 table dsl2
ip rule add pref 11 from 192.168.11.0/24 table dsl2

ip route flush cache

ip link add bond0 type bond
ip addr add 10.80.0.2/30 dev bond0

ip link set tap0 master bond0
ip link set tap1 master bond0

ip link set bond0 up mtu 1440

/usr/local/bin/gw bond0

Имена для таблиц маршрутизации должны быть объявлены в /etc/iproute2/rt_tables:

...
10  dsl1
11  dsl2

Убедитесь, что номера уникальны в этом файле конфигурации.

В mtu должен соответствовать настроенному на облачном сервере.

/usr/local/bin/gw (chmod +x) позволяет переключить шлюз по умолчанию:

#!/bin/bash
newGw=$1
if [[ ! $newGw =~ ^ppp[0-9]$ && $newGw != bond0 ]]; then
  echo "$0 {ppp[0-9]|bond0}"
  exit -1
fi

ip addr show dev $newGw >/dev/null 2>&1
ret=$?
if [[ $ret -ne 0 ]]; then
  echo "$newGw is not available"
  exit -1
fi

via=0.0.0.0
if [[ $newGw == bond0 ]]; then
  via=10.80.0.1
fi
ip route repl default via $via dev $newGw
ip route show

Создайте /usr/local/bin/vpn-stop (chmod +x):

#!/bin/bash
/usr/local/bin/gw ppp0

ip link set bond0 down
ip link del bond0

pkill 'openvpn'

ip rule del pref 10 from 192.168.10.0/24 table dsl1
ip route del default dev ppp0 table dsl1
ip route del 192.168.10.0/24 dev eth1 scope link table dsl1

ip rule del pref 11 from 192.168.11.0/24 table dsl2
ip route del default dev ppp1 table dsl2
ip route del 192.168.11.0/24 dev eth2 scope link table dsl2

ip route flush cache

Два vpn-* и gw сценарии, конечно, можно запускать вручную и при необходимости.

Брандмауэр

Установите FireHOL, как на облачном сервере, со следующими /etc/firehol/firehol.conf конфигурация:

version 6

lan="eth0"
web="ppp+"
vpn="bond+"

tcpmss auto "${web}"
masquerade "${web}"

interface "${lan}" lan
  policy accept

interface "${web}" web
  protection bad-packets
  server ident reject with tcp-reset
  client all accept

interface "${vpn}" vpn
  policy accept

router web2lan inface "${web}" outface "${lan}"
  protection bad-packets
  server ident reject with tcp-reset
  client all accept

router vpn2lan inface "${vpn}" outface "${lan}"
  policy accept

Активировать и проверить

Перезагрузите LAN-сервер и проверьте связующее устройство:

lan-server# cat /proc/net/bonding/bond0

Вывод должен напоминать Cloud Server.

Если вы сейчас перейдете, например, к https://www.whatsmyip.org/ в вашем браузере вы должны увидеть IP-адрес вашего облачного сервера.

Вы можете проверить свое улучшение скорости, например, бегом

lan-server# wget -4 -O /dev/null http://proof.ovh.net/files/1Gio.dat

Здесь мы видим, что связанная скорость всего на 5% меньше, чем сумма скоростей отдельных линий.

Отработка отказа с помощью Link Balancer

Если одно из подключений к Интернету выходит из строя, устройство связывания не поддерживает оставшееся подключение, как можно было бы ожидать. К этому событию можно подготовиться, настроив Балансировщик ссылок FireHOL.

Один из способов сделать это - создать подходящий /etc/firehol/link-balancer.conf и расписание /usr/sbin/link-balancer в качестве задания cron для периодической (например, каждые 2 минуты) проверки соединений и переключения на то, что еще доступно, если это необходимо. Последующий link-balancer.conf продолжит доступ в Интернет на оставшейся хорошей линии, если одна из них выйдет из строя:

check_bond0() {
  for dev in ppp0 ppp1 bond0; do
    /sbin/ip addr show dev $dev >/dev/null 2>&1
    ret=$?
    if [[ $ret -ne 0 ]]; then
      break
    fi
  done
  if [[ $ret -eq 0 ]]; then
    /bin/ping -w 8 -c 4 -I 10.80.0.2 10.80.0.1 >/dev/null 2>&1
    ret=$?
  fi
  return $ret
}

gateway bond dev bond0 gw 10.80.0.1 check bond0
gateway dsl1 dev ppp0
gateway dsl2 dev ppp1

table main
  default via bond weight 100
  fallback via dsl1
  fallback via dsl2

Проверка по умолчанию для связанного соединения, похоже, не позволяет надежно определить его состояние, поэтому пользовательский check_bond0.

Когда плохое соединение снова восстановится, Link Balancer сделает оба соединения шлюзами по умолчанию, которые будут сбалансированы на основе соединения. Невозможно с разумными усилиями восстановить связанное соединение, поэтому в этих редких случаях придется вручную перезапускать потенциально оба конца VPN.