Мы находимся в сельской местности с двумя медленными 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 (заменить 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
С помощью 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-start
(и chmod +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-stop
(и chmod +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. С помощью 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/bond0
(и chmod +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/bond0
(и chmod +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 здесь будет управляться скриптами, запускаемыми при установке / разрыве 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
/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% меньше, чем сумма скоростей отдельных линий.
Если одно из подключений к Интернету выходит из строя, устройство связывания не поддерживает оставшееся подключение, как можно было бы ожидать. К этому событию можно подготовиться, настроив Балансировщик ссылок 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.