По крайней мере, под ksh
и bash
, переменные могут иметь три объема, не два как все остающиеся ответы в настоящее время говорят.
В дополнение к экспортируемому (т.е. среда) переменная и оболочка неэкспортируемые переменные объемы, существует также третий более узкий для функциональных локальных переменных.
Переменные, объявленные в оболочке, функционируют с typeset
маркер только видим в функциях, которыми они объявляются в и в (sub) функции, вызванные оттуда.
Это ksh
/ bash
код:
# Create a shell script named /tmp/show that displays the scoped variables values.
echo 'echo [$environment] [$shell] [$local]' > /tmp/show
chmod +x /tmp/show
# Function local variable declaration
function f
{
typeset local=three
echo "in function":
. /tmp/show
}
# Global variable declaration
export environment=one
# Unexported (i.e. local) variable declaration
shell=two
# Call the function that creates a function local variable and
# display all three variable values from inside the function
f
# Display the three values from outside the function
echo "in shell":
. /tmp/show
# Display the same values from a subshell
echo "in subshell":
/tmp/show
# Display the same values from a disconnected shell (simulated here by a clean environment start)
echo "in other shell"
env -i /tmp/show
производит этот вывод:
in function:
[one] [two] [three]
in shell:
[one] [two] []
in subshell:
[one] [] []
in other shell
[] [] []
Как Вы видите, экспортируемая переменная отображена от первых трех мест, неэкспортируемые переменные не отображен вне текущей оболочки, и функциональная локальная переменная не имеет никакого значения вне самой функции. Последний тест не показывает значений вообще, это вызвано тем, что экспортируемые переменные не совместно используются оболочками, т.е. они могут только быть наследованы, и наследованное значение не может быть затронуто впоследствии родительской оболочкой.
Обратите внимание, что это последнее поведение очень отличается от того Windows, где можно использовать Системные переменные, которые являются полностью глобальными и общими всеми процессами.
Очень простое решение:
1. используйте OpenVPN 2.3 или больше (в настоящее время, последнее с 2.3 альфами) для сервера + клиенты
2. используйте параметр конфигурации OpenVPN ниже
3. не используйте ничто больше (никакой ipfilter, никакие приемы)
На стороне сервера необходимо вручную распределить адреса VPN (так нет server
опция, необходимо использовать ifconfig
или ifconfig-push
) :
# /etc/openvpn/server.conf
ifconfig 10.99.99.1 10.99.99.2
route 10.99.99.0 255.255.255.0
push "route 10.99.99.0 255.255.255.0"
push "client-nat dnat 10.99.99.11 255.255.255.255 10.10.111.11"
push "client-nat dnat 10.99.99.12 255.255.255.255 10.10.112.12"
push "client-nat dnat 10.99.99.13 255.255.255.255 10.10.113.13"
route
и push route
и client-nat
строки требуются, если Вы хотите связаться непосредственно между маршрутизаторами (ping 10.99.99.1
от удаленного сайта до VPN). Еще можно отбросить их.
.
.
Теперь необходимо выбрать адрес виртуальной сети. Я сохранил то же, которое Вы использовали в своем примере: 10.10.0.0/16
Вы позволяете направлять для этого:
# /etc/openvpn/server.conf
route 10.10.0.0 255.255.0.0
push "route 10.10.0.0 255.255.0.0"
.
.
Необходимо теперь дать клиенту команду использовать 1:1 NAT:
# /etc/openvpn/ccd/client_11
ifconfig-push 10.99.99.11 10.99.99.1
push "client-nat snat 10.99.99.11 255.255.255.255 10.10.111.11"
push "client-nat snat 192.168.0.0 255.255.255.0 10.10.11.0"
push "client-nat dnat 10.10.10.0 255.255.255.0 192.168.0.0"
iroute 10.10.11.0 255.255.255.0
iroute 10.10.111.0 255.255.255.0
Первая строка установила адрес удаленного маршрутизатора. Остерегайтесь о драйвере Windows, требующем специальных адресов.
Вторые и последние строки позволяют удаленному маршрутизатору связываться от 10.99.99.x интерфейс.
Третьи и четвертые строки делают источник и место назначения 1:1 NAT
Пятая строка говорит OpenVPN, что сделать с соответствующими пакетами.
Этот метод позволяет соединять сайты с идентичным (или не) адреса локальной сети без любого затененного хоста.
Я сделал что-то похожее с реальными интерфейсами, но я не вижу, почему оно не работало бы с интерфейсами VPN.
Идея состоит в том, что, поскольку Вы имеете ту же подсеть в наличии в различных интерфейсах на том маршрутизаторе, она усложняет маршрутизацию. В основном, когда пакет для 10.10.13.123 вводит маршрутизатор, это - DNATed прежде, чем направить к 192.168.0.123, таким образом, необходимо смочь сказать маршрутизации, что он был предназначен для 192.168.0.123 в интерфейсе VPN13.
Это может быть сделано при помощи меток брандмауэра и правил маршрутизации, которые используют те метки. SNAT и DNAT должны быть сделаны с целью брандмауэра NETMAP. Для SNAT это - та же проблема в POSTROUTING, Вы потеряли информацию, что пакет прибыл из этого или что интерфейс и они все получили исходный адрес 192.168.0.x. Таким образом, Вам нужна метка также для содержания той информации от искажения-PREROUTING до туземного-POSTROUTING. Можно использовать ту же метку, но затем это означало бы, что те пакеты будут использовать ту альтернативную таблицу маршрутизации, таким образом, необходимо было бы копировать глобальную таблицу маршрутизации на всех.
Для каждой сети Вы сделали бы:
lnet=192.168.0.0/24
if10=eth0 if11=tun0 if12=tun1 if13=tun2
n=0
for site in 10 11 12 13; do
table=$site
net=10.10.$site.0/24
n=$(($n + 1))
eval "interface=\$if$site"
inmark=$(($n * 2)) outmark=$(($n * 2 + 1))
iptables -t nat -A PREROUTING -d "$net" -j NETMAP --to "$lnet"
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -m mark --mark "$inmark"/0xf -j NETMAP --to "$net"
iptables -t mangle -A PREROUTING -i "$interface" -j MARK --set-mark "$inmark"/0xf
iptables -t mangle -A PREROUTING -d "$net" -j MARK --set-mark "$outmark"/0xf
ip rule add fwmark "$outmark"/0xf table "$table"
ip route add "$lnet" dev "$interface" table "$table"
done
Выше, мы используем первые 4 бита метки, чтобы позволить до 7 сетей быть направленными тот путь.