Jump to content

source (policy) based routing или как пустить через vpn только одного клиента


Recommended Posts

Здравствуйте!

Это мое первое сообщение, так что для начала хочу сказать спасибо всем за проект entware и за всю полезную информацию, которую нашел на этом форуме.

Хочу настроить роутер таким образом, чтобы можно было все соединения от одного из клиентов в сети пустить через vpn, а остальные клиенты чтобы шли через isp подключение как обычно.

Это нужно племяннику для play station 4, потому как sony иногда блокирует внешний ip адрес провайдера, кроме того, для совсем полноценной работы требуется куча портов открытых для входящих соединений. Заодно я сам хотел немного подучиться настраивать сеть, на этом примере.

План был такой:

  • Cоздать в zyxel keenetic omni ii подключение pptp с низким приоритетом
  • Прибить ps4 к конкретному ip адресу в локальной сети
  • Настроить роутинг таким образом, чтобы шлюзом по умолчанию для ps4 было ppp0 соединение
  • Настроить проброс портов на ps4

Все внутренние адреса прибиты и заранее известны (адрес ps4, адрес выдаваемый pptp сервером)

Да, ps4 не умеет vpn.

Поставил прошивку 2.0.5 с OPKG (v2.05(AAUS.4)C4), включил opkg, зашел по ssh. Долго искал в каком пакете находится программа ip (оказалось ip-legacy), но выяснилось, что поддержка advanced routing и multiple tables судя по всему выключена в ядре.

Теперь вопросы

  • Правильным ли путём иду?
  • Можно ли включить в ядре CONFIG_IP_ADVANCED_ROUTER, CONFIG_IP_MULTIPLE_TABLES и еще параметры необходимые для policy based routing?
  • Как собрать своё ядро/прошивку с нужными параметрами (если это вообще возможно)?
  • Может быть в экспериментальной прошивке 2.0.7 с ядром 3.4 уже включены нужные опции?

PS

Немного погрепал по прошивке выложенной в gpl_release, для некоторых target опция ADVANCED_ROUTER выключена, для некоторых включена, не знаю с чем связано. В любом случае, собрать это пока не получилось.

Link to comment
Share on other sites

Более менее получилось сделать задуманное.

Если совсем кратко, то достаточно поставить один пакет и выполнить пару команд.

Подготовка роутера (в моем случае Omni II):

  • Ставим прошивку 2.07 - экспериментальную из этой темы (кстати iproute2 и необходимые настройки ядра имеются также в стабильной прошивке 2.06 на Giga III).
  • Включаем OPKG по инструкции в этой теме.
  • Заходим по ssh на роутер
  • Ставим пакет ip-legacy
    opkg install ip-legacy


  • Проверяем что ядро поддерживает advanced router, команда ip rule должна вернуть дефолтные таблицы
    > ip rule
    0:      from all lookup local
    32766:  from all lookup main
    32767:  from all lookup default
    

Настройки

В роутере должно быть установлено vpn подключение, приоритет подключения должен быть ниже, чем у основного (иначе, ясное дело, все будут ходить через vpn)

Далее предполагаем, что клиент, который должен ходить через vpn, имеет в локальной сети адрес 192.168.73.33 (адрес можно прибить в разделе hosts через веб интерфейс)

vpn интерфейс называется ppp0 , peer адрес тоннеля (шлюз vpn) 192.168.212.1 (можно посмотреть командой ip a), номером таблицы пусть будет 200

  • Добавляем правило для таблицы с условием по исходящему адресу клиента
    ip rule add from 192.168.73.33 table 200
    


  • Добавляем роут по умолчанию через vpn для таблицы 200
    ip route add default via 192.168.212.1 dev ppp0 table 200
    


  • Очищаем кеш (хотя у меня работало и без этого)
    ip route flush cache
    

После этого клиент 192.168.73.33 должен ходить через vpn, остальные клиенты через основное соединение.

Проброс портов настраивается через веб-интерфейс, но это дело индивидуальное и отдельная тема, для play station 4 требуется целая куча портов.

Чтобы эти настройки выжили после перезагрузки, можно, в принципе, добавить скрипт в /opt/etc/init.d, который будет выполнять эти команды при старте роутера.


if [ "$1" = "start" ]; then
ip rule add from 192.168.73.33 table 200
ip route replace default via 192.168.212.1 dev ppp0 table 200
ip route flush cache
fi

Стоит не забыть добавить права на исполнение файла


chmod u+x /path/to/file

Я хотел сделать, чтобы этот маршрут отключался при падении vpn и включался при восстановлении. Пытался сделать скрипт в /opt/etc/ndm/wan.d, однако оказалось что (в этой прошивке во всяком случае) скрипт из wan.d всегда запускается с параметром start (что бы там ни происходило на самом деле). В итоге пришел к выводу, что удобнее использовать cron, получилось несколько громоздко, но вроде бы работает. Привожу для примера, может кому-то будет полезно, пока толком не тестировал, но вроде работает.

crond уже есть в составе busybox, нужно только сделать init.d скрипт и создать каталог


mkdir -p /opt/var/spool/cron/crontabs

init скрипт скопировал из скрипта для dropbox и поменял команду и аргументы, получилось вот что

cat /opt/etc/init.d/S51crond


#!/bin/sh

ENABLED=yes
PROCS=crond
ARGS="-L /dev/null"
PREARGS=""
DESC=$PROCS
PATH=/opt/sbin:/opt/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

. /opt/etc/init.d/rc.func

Содержимое crontab (редактирутся командой crontab -e, либо файл /opt/var/spool/cron/crontabs/root)

crontab -l


* * * * * /opt/vpn-upstream monitor

Ну и далее сам скрипт, который я положил в файл /opt/vpn-upstream

Состояние интерфейса ppp0 проверяется каждую минуту, если оно изменилось, то запускается start или stop в зависимости от наличия нужного ip адреса на интерфейсе. Статус файл записывается в /tmp/, чтобы при рестарте автоматически очищаться.

Тоже стоит не забыть добавить права на исполнение файла:


chmod u+x /opt/vpn-upstream


vpnIface="ppp0"
vpnGateway="192.168.212.1"
# clients to be always routed via vpnIface, separated by spaces
# vpnClients="192.168.73.33 192.168.73.34"
vpnClients="192.168.73.33"

routeTable="vpn-upstream"
routeTableId="200"

verbose=""

statusFile="/tmp/vpn-upstream.status"


flushRules() {
# Drop all rules from $routeTable
ip rule l|grep $routeTable|cut -f0 -d:|xargs -rn1 ip rule del pref
}

# Update status of vpn interface
updateStatusFile() {
ip a|grep $vpnIface > $statusFile;
}

stop() {
debugMsg stop;
# echo `date` stopping >> /opt/vpn-up.log;
updateStatusFile;
# do nothing if routeTable is not defined
grep -v '^#' /opt/etc/iproute2/rt_tables|grep "$routeTable" > /dev/null || return 0;

# delete default route from table if exists
if ip route l table $routeTable|grep default > /dev/null; then
ip route del default table $routeTable;
fi
flushRules
ip route flush cache
}

start() {
debugMsg start;
updateStatusFile;
# echo `date` starting >> /opt/vpn-up.log;
# Add new table routeTable if not exist
grep -v '^#' /opt/etc/iproute2/rt_tables|grep "$routeTable" > /dev/null || echo "$routeTableId $routeTable" >> /opt/etc/iproute2/rt_tables
flushRules
for client in $vpnClients; do
ip rule add from $client table $routeTable
done
ip route replace default via $vpnGateway dev $vpnIface table $routeTable
ip route flush cache

}

# monitor vpn interface status change and run autoStartStop if changed
monitor() {
debugMsg monitor;
state=$(ip a|grep $vpnIface)
if [ ! -f $statusFile ]; then
touch $statusFile
fi
oldState=$(cat $statusFile);
stateHash=$(echo $state|sha1sum);
oldStateHash=$(echo $oldState|sha1sum);
if [ ! "$oldStateHash" = "$stateHash" ]; then
debugMsg 'auto start or stop';
autoStartStop;
fi
echo -n $state > $statusFile
}

autoStartStop() {
debugMsg "auto start or stop";
# start if has vpnGateway, stop otherwise
if ip a l|grep $vpnGateway > /dev/null; then
start;
else
stop;
fi
}

debugMsg() {
[ "$verbose" = "1" ] && echo `date` "$@"
}

status() {
debugMsg status
grep -v '^#' /opt/etc/iproute2/rt_tables|grep "$routeTable" > /dev/null || return 0;
ip rule l|grep $routeTable
ip route l table $routeTable
}

if [ "$2" = "-v" ]; then
verbose="1"
fi

case $1 in
"monitor")
monitor;
;;
"stop")
stop;
;;
"start")
start;
;;
"auto")
autoStartStop;
;;
*)
status;
;;
esac

Ну и, конечно, LARTC, другая документация и этот форум в помощь.

Link to comment
Share on other sites

  • 7 months later...

правильно я понимаю, что если у меня

~ # cat /proc/sys/net/ipv4/conf/all/accept_source_route
0
~ # cat /proc/sys/net/ipv4/conf/all/rp_filter
0
то PBR у меня не будет?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...