Я ооочень боролся с этим, так что вот ПОЛНОЕ решение. Это проверено на Ubuntu 15 и 16. В частности, вы можете использовать его с OpenVPN для маршрутизации определенных приложений вне интерфейса VPN-туннеля.
Полное решение "cgroup"
Как это работает?
- Ядро Linux поместит приложение в контрольную группу. Сетевой трафик от приложений в этой группе будет идентифицироваться по их идентификатору класса на уровне сетевого контроллера.
- iptables отметит этот трафик и заставит его выйти с нужным IP
- ip route будет обрабатывать помеченный трафик в другой таблице маршрутизации с маршрутом по умолчанию на любой IP-адрес шлюза, который вы хотите.
Автоматический скрипт
Я сделал скрипт novpn.sh для автоматизации установки и запуска зависимостей. Проверено на Ubuntu.
Сначала запустите свой VPN.
wget https://gist.githubusercontent.com/kriswebdev/a8d291936fe4299fb17d3744497b1170/raw/cf8b37fbe6c3f50a0be825eb77cafa3e0134946f/novpn.sh
# If you don't use eth0, edit the script setting.
sudo chmod +x novpn.sh
./novpn.sh traceroute www.google.com
./novpn.sh --help
Ручная инструкция
Сначала установите поддержку cgroup и инструменты:
sudo apt-get install cgroup-lite cgmanager cgroup-tools
Перезагрузка (может и не понадобиться).
Вам нужен iptables 1.6.0+. Получите исходный код iptables 1.6.0, распакуйте его, затем запустите этот файл ( флаг --disable-nftables
позволит избежать ошибок) из директории источника iptables:
sudo apt-get install dh-autoreconf bison flex
./configure --prefix=/usr \
--sbindir=/sbin \
--disable-nftables \
--enable-libipq \
--with-xtlibdir=/lib/xtables
make
sudo make install
iptables --version
Теперь настоящий конфиг. Определите контрольную группу с именем novpn
. Процессы в этой группе будут иметь класс 0x00110011
(11:11).
sudo su
mkdir /sys/fs/cgroup/net_cls/novpn
cd /sys/fs/cgroup/net_cls/novpn
echo 0x00110011 > net_cls.classid
Теперь предположим, что интерфейс, который вы хотите использовать для конкретного приложения, это eth0
с IP-адресом шлюза 10.0.0.1
. Замените их тем, что вы действительно хотите (получите информацию по ip route
). Запустите еще как root:
# Add mark 11 on packets of classid 0x00110011
iptables -t mangle -A OUTPUT -m cgroup --cgroup 0x00110011 -j MARK --set-mark 11
# Force the packets to exit through eth0 with NAT
iptables -t nat -A POSTROUTING -m cgroup --cgroup 0x00110011 -o eth0 -j MASQUERADE
# Define a new "novpn" routing table
# DO THIS JUST ONCE !
echo 11 novpn >> /etc/iproute2/rt_tables
# Packets with mark 11 will use novpn
ip rule add fwmark 11 table novpn
# Novpn has a default gateway to the interface you want to use
ip route add default via 10.0.0.1 table novpn
# Unset reverse path filtering for all interfaces, or at least for "eth0" and "all"
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $i; done
Наконец, запустите ваше приложение на определенном интерфейсе:
exit
sudo cgcreate -t $USER:$USER -a $USER:$USER -g net_cls:novpn
cgexec -g net_cls:novpn traceroute www.google.com
# Close all Firefox windows first
cgexec -g net_cls:novpn firefox
Или, если вы хотите перенести уже запущенный процесс в cgroup, ну ... вы не можете! Похоже, это связано с функцией NAT (маскарад): iptables -nvL -t nat
не совпадает при переключении cgroup , но iptables -nvL -t mangle
действительно совпадает.
# Get PID of the process (we'll then suppose it's 1234)
pidof firefox
# Add to cgroup - THIS DOESN'T WORK! Silently fails to produce the final result.
sudo echo 1234 > /sys/fs/cgroup/net_cls/novpn/tasks
# Remove - but this works...
sudo echo 1234 > /sys/fs/cgroup/net_cls
Кредиты: ни один ответ не работал должным образом, но их сочетание сработало: chripell answer статья evolware Маршрутизация процесса занимает 2: использование cgroups, iptables и маршрутизации политики. Как сделать так, чтобы конкретный процесс НЕ проходил через соединение OpenVPN? Убей свитч для OpenVPN на основе iptables