Поиск
Показаны результаты для тегов 'трафик'.
Найдено 1 результат
-
Вступление или зачем нам вообще это надо? В наше интересное время все чаше приходиться использовать VPN, но тут начинается другая проблема часть местных интернет ресурсов может быть недоступна через сервер VPN. И начинается постоянное передергивание включения выключения VPN соединения. Существует много вариантов концепции разделения трафика и обхода региональных блокировок я решил рассмотреть вариант реализации с использованием wireguard. Да это скорее всего (даже наверняка) не самый лучший инструмент для организации разделения трафика но во первых уже был работающий сервер wg во вторых заинтересовала сама идея реализации. Практически все материалы по разделению трафика были заимствованы и доработаны из статьи с хабр Укрощаем одноглазого змея. Разбираемся с WireGuard и делаем свой умный VPN я не претендую на авторство метода, скриптов или любых материалов из оригинальной статьи. А так же настоятельно рекомендую ознакомиться с оригиналом статьи для лучшего понимания идеи. Цель данной публикации познакомить с вариантом разделения трафика, предоставить сжатую инструкцию по настройке. Так же в отличии от оригинальной статьи настройка выполнялась с установкой веб интерфейса в виде wg-easy так как ручная генерация новых клиентов описанная автором мне кажется мягко говоря неудобной и не оправданной. Для реализации надо: 1. Удаленный сервер с настроенным wg сервером 2. Локальная машина Linux (желательно виртуальная отдельно от других приложений) для работы достаточно 256 мб ОЗУ но зависит от количества клиентов и объема трафика. Подготовка сервера Выполним первоначальную настройку сервера для установки. Основная настройка будет выполнятся с использованием скрипта, но для создания клиентских подключений используется wg-easy установленным с использованием docker-compose. Обновляем репозитории и пакеты: apt update -y && apt upgrade -y Устанавливаем Docker: apt install curl && curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh Запускаем и включаем службу Docker systemctl start docker && systemctl enable docker Устанавливаем Docker Compose: curl -L --fail https://raw.githubusercontent.com/linuxserver/docker-docker-compose/master/run.sh -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose Так же устанавливает пакеты необходимые для работы wg и скрипта настройки маршрутов. apt install -y wireguard iptables ipcalc qrencode curl jq traceroute net-tools netscript Настройка соединения с внешним сервером Наш внутренний сервер подключается как клиент к внешнему серверу с настроенным wireguard. Для этого на внешнем сервере разворачиваем серверную часть wg (рекомендую использовать скрипты dwg) или заходим на ранее созданный и генерируем нового клиента. Нам необходимо получить файл конфигурации для подключения клиента вида: [Interface] PrivateKey = <Seckret> Address = 10.10.10.14/24 DNS = 10.2.0.100 MTU = 1280 [Peer] PublicKey = <Seckret> PresharedKey = <Seckret> AllowedIPs = 0.0.0.0/0, ::/0 PersistentKeepalive = 25 Endpoint = <Seckret>:51820 Данные этого файла конфигурации необходимо в неизменном виде разместить в wg-external.conf cd /etc/wireguard nano wg-external.conf Запускаем туннель до внешнего сервера wg-quick up wg-external Для проверки работы туннеля команда wg На текущий момент мы получили такую схему подключения Теперь нам надо обеспечить возможность конечным пользователям ходить в интернет через наш внутренний сервер. Настройка клиентской части внутреннего сервера Для настройки клиентской части был выбран WG-EASY но можно использовать любой вариант настройки wg от ручного как предлагает автор оригинальной статьи так и различные графические интерфейсы. Создадим каталог с docker-compose файлом для запуска wg-easy mkdir wg-easy && cd wg-easy nano docker-compose.yml Вставляем в файл следующее содержимое version: "3" services: wg-easy: environment: - WG_HOST=192.168.0.132 - PASSWORD=MySecretPassword - WG_PORT=51820 - WG_DEFAULT_ADDRESS=10.10.9.x - WG_DEFAULT_DNS=192.168.0.1 - WG_ALLOWED_IPS=0.0.0.0/0, ::/0 - WG_MTU=1280 image: ditek/wg-easy container_name: wg-easy volumes: - /wg-easy:/etc/wireguard ports: - "51820:51820/udp" - "51821:51821/tcp" restart: unless-stopped cap_add: - NET_ADMIN - SYS_MODULE sysctls: - net.ipv4.ip_forward=1 - net.ipv4.conf.all.src_valid_mark=1 dns: - 192.168.0.1 Для корректной работы необходимо скорректировать некоторые параметры с учетом вашей сети. В параметр WG_HOST указываем IP адрес в вашей сети по которому можно будет обратиться к серверу WG. Сервер разделения трафика должен иметь фиксированный IP адрес. В параметр PASSWORD указываем пароль от веб интерфейса. Параметр WG_DEFAULT_ADDRESS можно оставить без изменений, но если планируете использовать на одном устройстве несколько подключений WG в активном состоянии одновременно необходимо что бы сети не пересекались (актуально для роутеров kenetik). Для этого достаточно изменить на 10.10.8.x или любую другую не используемую подсеть. Параметр WG_DEFAULT_DNS если мы используем только внутри локальной сети то указываем наш роутер или ip на котором установлен локальный DNS. Так же указываем его в секции dns. Запускаем сборку и установку контейнера docker-compose up -d Выходим в корневой каталог cd Проверяем работу контейнера docker ps Теперь нам доступно создание клиентов на локальном сервере через веб интерфейс по адресу http://IP_server:51821 Заходим с паролем указанным в докер файле и создаем клиента. Подключаемся к локальному серверу с любого устройства и проверяем работу сети. Проверяем IP адрес и видим наш адрес удаленного сервера. Теперь схема подключения выглядит так: Фактически мы сделали туннель до внешнего сервера через промежуточную точку, осталось сделать разделение трафика на промежуточном сервере. Настройка скрипта разделения Идея как и сам скрипт позаимствован из оригинальной статьи автора (рекомендую ознакомится для более точного понимания), Я же перескажу основную идею скрипта. Мы хотим что бы наш локальный интернет не ходил на удаленный сервер а выходил через обычный интернет. Создадим скрипт в отдельной директории mkdir exclude_routes nano update_exclude_routes.sh И вставляем сюда скрипт #!/bin/bash #To crontab (export EDITOR=nano; crontab -e) #@reboot sleep 30 && bash /root/update_exclude_routes.sh > /root/update_routes_log.txt 2>&1 #0 3 * * mon bash /root/update_exclude_routes.sh > /root/update_routes_log.txt 2>&1 function ProgressBar { let _progress=(${1}*100/${2}*100)/100 let _done=(${_progress}*4)/10 let _left=40-$_done _fill=$(printf "%${_done}s") _empty=$(printf "%${_left}s") printf "\rAdd routes to route table (${1}/${2}): [${_fill// /#}${_empty// /-}] ${_progress}%%" } #Variables file_raw="russian_subnets_list_raw.txt" file_user="subnets_user_list.txt" file_user_hostnames="hosts_user_list.txt" file_for_calc="russian_subnets_list_raw_for_calc.txt" file_processed="russian_subnets_list_processed.txt" gateway_for_internal_ip=`ip route | awk '/default/ {print $3; exit}'` interface=` ip link show | awk -F ': ' '/state UP/ && !/docker/ && !/veth/ {print $2}' | head -n 1 | sed 's/@.*//' ` #interface="eth0" #Get addresses RU segment echo "Download RU subnets..." curl --progress-bar "https://stat.ripe.net/data/country-resource-list/data.json?resource=ru" | jq -r ".data.resources.ipv4[]" > $file_raw echo "Deaggregate subnets..." cat $file_raw |grep "-" > $file_for_calc cat $file_raw |grep -v "-" > $file_processed for line in $(cat $file_for_calc); do ipcalc $line |grep -v "deaggregate" >> $file_processed; done if [ -e $file_user ] then echo "Add user subnets..." cat $file_user |grep -v "#" >> $file_processed fi if [ -e $file_user_hostnames ] then echo "Add user hostnames..." for line in $(cat $file_user_hostnames); do nslookup line |grep "Address" |grep -v "#" |awk '{print $2"/32"}' >> $file_processed; done fi #Flush route table echo "Flush route table (down interface $interface)..." ifdown $interface > /dev/null 2>&1 echo "Up interface $interface..." ifup $interface > /dev/null 2>&1 #Add route routes_count_in_file=`wc -l $file_processed` routes_count_current=0 for line in $(cat $file_processed); do ip route add $line via $gateway_for_internal_ip dev $interface; let "routes_count_current+=1" ; ProgressBar ${routes_count_current} ${routes_count_in_file}; done echo "" echo "Remove temp files..." rm $file_raw $file_processed $file_json $file_for_calc routes_count=`ip r | wc -l` echo "Routes in routing table: $routes_count" Сохраняем и проверяем работу: bash update_exclude_routes.sh Данный скрипт можно использовать не только для разделения на Ru и не RU сегмент интернета. Можно использовать любые списки сетей, фактически скрипт делает автоматическое добавление маршрутов. На данном этапе разделение по подсетям уже готово, все ip адреса которые относятся к RU сегменту будут идти через основной интернет. Дополнительно мы можем положить в данную папку файлы со списком сайтов и подстей которые мы хотим тоже пустить по короткому маршруту через основной интеренет. subnets_user_list.txt – для подсетей hosts_user_list.txt – для сайтов, адреса определяются через nslookup Отдельно хочу обратить внимание на параметр interface он должен указывать на ваш основной интерфейс по которому сервер подключен к интернету. Скрипт должен автоматически определить данный интерфейс, но если вы столкнулись с ошибкой вида «Cannot find device "eth0@if27"» при запуске необходимо скорректировать скрипт и вписать руками конкретный интерфейс. Для этого нам надо определить основной интерфейс подключения. Это можно сделать командой ifconfig Нас интересует имя того интерфейса который получил адрес в нашей локальной сети. Корректируем в файле скрипта параметр: interface="eth0" И запускаем скрипт bash update_exclude_routes.sh Фактически мы получили нашу целевую схему: Нам осталось только настроить автоматический запуск при перезагрузке и периодическое обновление таблицы маршрутов. Добавим авто запуск wg туннеля до удаленного сервера systemctl enable [email protected] И добавим запуск скрипта при перезапуске в крон export EDITOR=nano; crontab -e Добавляем в конец следующие строчки @reboot sleep 30 && bash exclude_routes/update_exclude_routes.sh > exclude_routes/update_routes_log.txt 2>&1 0 3 * * mon bash exclude_routes/update_exclude_routes.sh > exclude_routes/update_routes_log.txt 2>&1 Перезапускаем сервер и проверяем. Для проверки наличия маршрутов можно воспользоваться командой: ip r | wc -l Команда возвращает количество прописанных маршрутов, по моим наблюдениям количество маршрутов должно быть более 10000 при корректной работе скрипта. Подключаем наших конечных пользователей (рекомендую напрямую роутер) и пользуемся. Заключение Скрипт не совершенен и в некоторых ситуациях выпадает с ошибками по типу блокировки записей маршрутов и т.д. Я не являюсь автором данного скрипта, моя задача была применить схему и показать другим как ее можно использовать. На текущий момент на моей системе происходит обкатка работы такой схемы разделения. Буду благодарен за идеи как можно доработать скрипт или другие варианты. Возможно кто то предложит телеграмм бота для управления скриптом или еще какие то идеи по улучшению. P.S. В оригинальной статье разобран так же разобран кейс добавления конкретных маршрутов на удаленный сервер которые мы должны были направить на обычный доступ в интернет. Я разбирал работу этой части скрипта но она полностью еще не адаптирована для использования с WG-EASY, по этому возможно позднее дополню публикацию.