monoid
|
|
|
|
|
Рег.: 14.02.2004
|
Сообщений: 1689
|
Из: ГЗ::Б::12
|
Рейтинг: 1331
|
|
Открыл для себя network namespaces
27.03.2014 16:55
|
|
|
Бывают неприятные ситуации, когда приходится пользоваться проприетарным vpn-софтом, который норовит переписать роуты и resolv.conf. Еще бывает, что хочется одновременно поднять два vpn'а, но они пересекаются по диапазонам адресов, к которым дают доступ.
Очевидно, что "неудобный" vpn можно поднять в виртуальной машине, чтобы он засирал роуты и resolv.conf только в ней, а не глобально. Если поднимать полновесную виртуалку или контейнер не хочется, network namespaces to the rescue: они позволяют запустить дерево процессов с выделенным сетевым стеком (интерфейсы, роуты и другая атрибутика) и даже со своим resolv.conf (магия mount --bind). Нужно как-то организовать для неймспейса выход во внешний мир (например, virtual ethernet pair + nat), потом можно запускать в неймспейсе какой-нибудь tmux и работать:
#!/bin/bash
attach()
{
name=${1-vpn}
if [ $UID -ne 0 ]; then
exec tmux -L $name attach
else
exec ip netns exec $name su -c "exec tmux -L $name new -A" $SUDO_USER
fi
}
start()
{
name=${1-vpn}
addrbase=${2-192.168.99}
ip link add $name.1 type veth peer name $name.2
ip addr add $addrbase.1/30 dev $name.1
ip link set $name.1 up
iptables -v -t nat -A POSTROUTING -s $addrbase.0/30 -o eth0 -j MASQUERADE
mkdir -p /etc/netns/$name
sed /127.0.0.1/d </etc/resolv.conf >/etc/netns/$name/resolv.conf
ip netns add $name
ip link set $name.2 netns $name
ip netns exec $name bash -c "
ip addr add $addrbase.2/30 dev $name.2
ip link set $name.2 up
ip route add default via $addrbase.1
ip link set lo up"
attach $1
}
stop()
{
name=${1-vpn}
addrbase=$(ip addr show $name.1 |
sed -n 's/.*inet \([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p')
ip link del $name.1
iptables -v -t nat -D POSTROUTING -s $addrbase.0/30 -o eth0 -j MASQUERADE
ip netns del $name
}
command="$1"
shift
case "$command" in
"start" | "stop" | "attach")
"$command" "$@"
;;
*)
echo "usage: $0 {start | stop | attach} [vpn-name] [vpn-addr-base]"
esac
|
# |
|
unkulunkulu
|
unkulunkulunkulu
|
|
|
|
Рег.: 12.11.2006
|
Сообщений: 18453
|
Из: 13000
|
Рейтинг: 11759
|
|
Re: Открыл для себя network namespaces
[re: monoid]
27.03.2014 19:18
|
|
|
|
monoid
|
|
|
|
|
Рег.: 14.02.2004
|
Сообщений: 1689
|
Из: ГЗ::Б::12
|
Рейтинг: 1331
|
|
|
Потом выясняется, что файрфокс нельзя запустить с настроенным профилем в неймспейсе, потому что он уже запущен снаружи, и приходится вытаскивать из неймспейса нужный веб-сервер через socat. Впрочем, при желании можно зароутить сразу целую подсеть через неймспейс через еще один нат, надо только взаимной рекурсии избежать.
А еще выясняется, что проприетарный vpn-клиент сцуко не работает, когда resolv.conf предоставлен через mount --bind, т.к. он хочет его типа забэкапить, а rename() возвращает EBUSY. Приходится подкостыливать через LD_PRELOAD.
ЗЫ. Как-то странно, что в iptables нужно писать "-o eth0". Нельзя чтобы оно само понимало, куда отдать пакет по роутам?
|
# |
|
green
|
|
|
|
|
Рег.: 28.11.2002
|
Сообщений: 20916
|
Из: MSU
|
Рейтинг: 5080
|
|
Re: Открыл для себя network namespaces
[re: monoid]
27.03.2014 19:54
|
|
|
Quote:
ЗЫ. Как-то странно, что в iptables нужно писать "-o eth0". Нельзя чтобы оно само понимало, куда отдать пакет по роутам?
Оно не задает куда отдававть пакет, это как раз по роутам и определяется. Оно задает на каком исходящем интерфейсе указанный NAT осуществлять.
|
|
monoid
|
|
|
|
|
Рег.: 14.02.2004
|
Сообщений: 1689
|
Из: ГЗ::Б::12
|
Рейтинг: 1331
|
|
Re: Открыл для себя network namespaces
[re: green]
27.03.2014 20:11
|
|
|
Действительно. Ну вот у меня в скрипте выше "-o eth0" захардкожено, но это не кошерно же, вдруг кто-то захочет его поюзать на ноуте, где wifi0, а у кого-то systemd с enp0s0akjdfhгцук0. Как правильно такое скриптовать?
|
# |
|
green
|
|
|
|
|
Рег.: 28.11.2002
|
Сообщений: 20916
|
Из: MSU
|
Рейтинг: 5080
|
|
Re: Открыл для себя network namespaces
[re: monoid]
28.03.2014 07:19
|
|
|
Quote:
Действительно. Ну вот у меня в скрипте выше "-o eth0" захардкожено, но это не кошерно же, вдруг кто-то захочет его поюзать на ноуте, где wifi0, а у кого-то systemd с enp0s0akjdfhгцук0. Как правильно такое скриптовать?
Можно, например, так: ip route show 0.0.0.0/0 | sed 's/.* dev \([^ ]*\) .*/\1/' Но это не все случаи покрывает. Еще там в скрипте опечатка, здесь:
Quote:
name=${1-vpn} addrbase=${2-192.168.99}
Кстати, можно использовать маску /31. Или на veth пару можно вообще peer to peer адреса вешать или маршрутизировать прям в устройство (про определенных условиях):
Quote:
# на хосте ip addr add $iplocal peer $ipremote dev $devlocal # в контейнере ip addr add $ipremote peer $iplocal dev $devremote ip ro add default via $iplocal
Quote:
# на хосте ip ro add $ipremote dev $devlocal # в контейнере ip addr add $ipremote/32 dev $devremote ip ro add default dev $devremote
Редактировал green (28.03.2014 20:08)
|
|
monoid
|
|
|
|
|
Рег.: 14.02.2004
|
Сообщений: 1689
|
Из: ГЗ::Б::12
|
Рейтинг: 1331
|
|
Re: Открыл для себя network namespaces
[re: green]
28.03.2014 10:14
|
|
|
Quote:
Еще там в скрипте опечатка, здесь:
Quote:
name=${1-vpn} addrbase=${2-192.168.99}
А что не так? Скрипт у меня работал.
|
# |
|
green
|
|
|
|
|
Рег.: 28.11.2002
|
Сообщений: 20916
|
Из: MSU
|
Рейтинг: 5080
|
|
Re: Открыл для себя network namespaces
[re: monoid]
28.03.2014 10:20
|
|
|
Quote:
А что не так? Скрипт у меня работал.
Мне подумалось, что идея была такая:
Quote:
name=${1:-vpn} addrbase=${2:-192.168.99}
Но похоже bash и без ":" переваривает. Это документированная фича?
|
|
monoid
|
|
|
|
|
Рег.: 14.02.2004
|
Сообщений: 1689
|
Из: ГЗ::Б::12
|
Рейтинг: 1331
|
|
Re: Открыл для себя network namespaces
[re: green]
28.03.2014 10:23
|
|
|
Да, но я тоже в документации заметил ее, только сильно присмотревшись:
Quote:
When not performing substring expansion, using the forms documented below, bash tests for a parameter that is unset or null. Omitting the colon results in a test only for a parameter that is unset.
${parameter:-word} Use Default Values. If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
|
# |
|
monoid
|
|
|
|
|
Рег.: 14.02.2004
|
Сообщений: 1689
|
Из: ГЗ::Б::12
|
Рейтинг: 1331
|
|
Re: Открыл для себя network namespaces
[re: green]
28.03.2014 14:32
|
|
|
Quote:
# на хосте ip ro add $ipremote dev $devlocal # в контейнере ip addr add $ipremote/32 dev $devremote ip ro add default dev $devremote
я что-то не понимаю, или это не работает? так он пытается из неймспейса выполнять arp-resolution:
code: 14:25:55.395093 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 8.8.8.8 tell 192.168.98.2, length 28
14:25:56.397572 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 8.8.8.8 tell 192.168.98.2, length 28
14:25:57.399569 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 8.8.8.8 tell 192.168.98.2, length 28
|
# |
|
green
|
|
|
|
|
Рег.: 28.11.2002
|
Сообщений: 20916
|
Из: MSU
|
Рейтинг: 5080
|
|
Re: Открыл для себя network namespaces
[re: monoid]
28.03.2014 20:05
|
|
|
Quote:
я что-то не понимаю, или это не работает? так он пытается из неймспейса выполнять arp-resolution:
Я немного попутал про veth, похоже. Система работает ведь с ним как с ehternet - arp-запросы посылает и т.п. В таком варианте будет работать, если proxy arp включить. Но arp-запросы будут все равно посылаться на всех. Либо если все же хочется на хосте не вешать адрес и не делать глобальный arp-прокси, то можно включить прокси арп на хосте, а в контейнере сделать: iplocal=<host_any_ip> ip route add default via $iplocal ip route add $iplocal dev $devremote или ip addr add $ipremote/32 peer $iplocal На хосте опционально можно вместо прокси арп повести тоже какой-нибудь существующий адрес в качестве $iplocal.
|
|