Tüm süreçlerin ve yalnızca trafiğin belirli işlemlerden / VPN'den geçeceği bir VPN (OpenVPN kullanarak) kurmaya çalışıyorum ; diğer işlemler fiziksel cihazı doğrudan kullanmaya devam etmelidir. Linux'ta bunu yapmanın yolunun ağ ad alanları ile olduğunu anlamak benim.
OpenVPN'i normal şekilde kullanırsam (yani istemciden VPN üzerinden gelen tüm trafiği huni ), iyi çalışır. Özellikle, OpenVPN'i şu şekilde başlatıyorum:
# openvpn --config destination.ovpn --auth-user-pass credentials.txt
(Bu sorunun sonunda, target.ovpn dosyasının düzeltilmiş bir sürümü bulunmaktadır.)
Bir sonraki adımda takıldım, tünel cihazını ad alanlarıyla sınırlayan komut dosyaları yazıyorum. Denedim:
Tünel cihazını doğrudan isim alanına koymak
# ip netns add tns0 # ip link set dev tun0 netns tns0 # ip netns exec tns0 ( ... commands to bring up tun0 as usual ... )
Bu komutlar başarıyla yürütülür, ancak ad alanının (ör. İle
ip netns exec tns0 traceroute -n 8.8.8.8
) içinde oluşturulan trafik bir kara deliğe düşer.Bir ağ ad alanına [hala] yalnızca sanal Ethernet (veth) arabirimleri atayabileceğiniz varsayımına göre (eğer doğruysa, bu yılki en gülünç gereksiz API kısıtlaması için bu ödülü alır), bir veth çifti ve bir köprü oluşturarak ve veth çiftinin bir ucunu isim alanına yerleştirir. Bu, zemindeki trafiği düşürmek kadar bile değil: Tüneli köprüye sokmama izin vermiyor! [DÜZENLE: Bunun nedeni köprülere yalnızca musluk aygıtları yerleştirilebileceğidir. Bir rasgele aygıtları bir ağ ad alanına yerleştirememenin aksine, bu gerçekten mantıklıdır, köprüler bir Ethernet katmanı kavramıdır; ne yazık ki, VPN sağlayıcım OpenVPN'i musluk modunda desteklemediğinden, bir geçici çözüme ihtiyacım var.]
# ip addr add dev tun0 local 0.0.0.0/0 scope link # ip link set tun0 up # ip link add name teo0 type veth peer name tei0 # ip link set teo0 up # brctl addbr tbr0 # brctl addif tbr0 teo0 # brctl addif tbr0 tun0 can't add tun0 to bridge tbr0: Invalid argument
Bu sorunun sonundaki senaryolar veth yaklaşımı içindir. Doğrudan yaklaşım için komut dosyaları düzenleme geçmişinde bulunabilir. Komut dosyalarında ilk olarak ayarlanmadan kullanılan değişkenler, openvpn
program tarafından çevrede ayarlanır - evet, özensizdir ve küçük harf adları kullanır.
Lütfen bunun nasıl işe yarayacağı konusunda özel tavsiyeler sunun. Buraya kargo tarikat tarafından programlama ediyorum acı farkındayım - gelmiştir herkes bu şeyler için kapsamlı belgeler yazılı? Herhangi bir - bulamıyorum komut dosyalarının genel kod incelemesi de takdir edilmektedir.
Önemli olması halinde:
# uname -srvm
Linux 3.14.5-x86_64-linode42 #1 SMP Thu Jun 5 15:22:13 EDT 2014 x86_64
# openvpn --version | head -1
OpenVPN 2.3.2 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [PKCS11] [eurephia] [MH] [IPv6] built on Mar 17 2014
# ip -V
ip utility, iproute2-ss140804
# brctl --version
bridge-utils, 1.5
Çekirdek, sanal barındırma sağlayıcım ( Linode ) tarafından oluşturuldu ve derlenmiş olmasına rağmen CONFIG_MODULES=y
, gerçek modülleri yok - buna göre CONFIG_*
ayarlanan tek değişken oldu ve aslında bu modüle sahip değilim (çekirdek dosya sistemimin dışında depolanıyor; boştur ve sihirli bir şekilde yüklenmediğini belirtir). İstek üzerine alıntılar sağlanmıştır, ancak her şeyi buraya yapıştırmak istemiyorum.m
/proc/config.gz
CONFIG_XEN_TMEM
/lib/modules
/proc/modules
/proc/config.gz
netns-up.sh
#! /bin/sh
mask2cidr () {
local nbits dec
nbits=0
for dec in $(echo $1 | sed 's/\./ /g') ; do
case "$dec" in
(255) nbits=$(($nbits + 8)) ;;
(254) nbits=$(($nbits + 7)) ;;
(252) nbits=$(($nbits + 6)) ;;
(248) nbits=$(($nbits + 5)) ;;
(240) nbits=$(($nbits + 4)) ;;
(224) nbits=$(($nbits + 3)) ;;
(192) nbits=$(($nbits + 2)) ;;
(128) nbits=$(($nbits + 1)) ;;
(0) ;;
(*) echo "Error: $dec is not a valid netmask component" >&2
exit 1
;;
esac
done
echo "$nbits"
}
mask2network () {
local host mask h m result
host="$1."
mask="$2."
result=""
while [ -n "$host" ]; do
h="${host%%.*}"
m="${mask%%.*}"
host="${host#*.}"
mask="${mask#*.}"
result="$result.$(($h & $m))"
done
echo "${result#.}"
}
maybe_config_dns () {
local n option servers
n=1
servers=""
while [ $n -lt 100 ]; do
eval option="\$foreign_option_$n"
[ -n "$option" ] || break
case "$option" in
(*DNS*)
set -- $option
servers="$servers
nameserver $3"
;;
(*) ;;
esac
n=$(($n + 1))
done
if [ -n "$servers" ]; then
cat > /etc/netns/$tun_netns/resolv.conf <<EOF
# name servers for $tun_netns
$servers
EOF
fi
}
config_inside_netns () {
local ifconfig_cidr ifconfig_network
ifconfig_cidr=$(mask2cidr $ifconfig_netmask)
ifconfig_network=$(mask2network $ifconfig_local $ifconfig_netmask)
ip link set dev lo up
ip addr add dev $tun_vethI \
local $ifconfig_local/$ifconfig_cidr \
broadcast $ifconfig_broadcast \
scope link
ip route add default via $route_vpn_gateway dev $tun_vethI
ip link set dev $tun_vethI mtu $tun_mtu up
}
PATH=/sbin:/bin:/usr/sbin:/usr/bin
export PATH
set -ex
# For no good reason, we can't just put the tunnel device in the
# subsidiary namespace; we have to create a "virtual Ethernet"
# device pair, put one of its ends in the subsidiary namespace,
# and put the other end in a "bridge" with the tunnel device.
tun_tundv=$dev
tun_netns=tns${dev#tun}
tun_bridg=tbr${dev#tun}
tun_vethI=tei${dev#tun}
tun_vethO=teo${dev#tun}
case "$tun_netns" in
(tns[0-9] | tns[0-9][0-9] | tns[0-9][0-9][0-9]) ;;
(*) exit 1;;
esac
if [ $# -eq 1 ] && [ $1 = "INSIDE_NETNS" ]; then
[ $(ip netns identify $$) = $tun_netns ] || exit 1
config_inside_netns
else
trap "rm -rf /etc/netns/$tun_netns ||:
ip netns del $tun_netns ||:
ip link del $tun_vethO ||:
ip link set $tun_tundv down ||:
brctl delbr $tun_bridg ||:
" 0
mkdir /etc/netns/$tun_netns
maybe_config_dns
ip addr add dev $tun_tundv local 0.0.0.0/0 scope link
ip link set $tun_tundv mtu $tun_mtu up
ip link add name $tun_vethO type veth peer name $tun_vethI
ip link set $tun_vethO mtu $tun_mtu up
brctl addbr $tun_bridg
brctl setfd $tun_bridg 0
#brctl sethello $tun_bridg 0
brctl stp $tun_bridg off
brctl addif $tun_bridg $tun_vethO
brctl addif $tun_bridg $tun_tundv
ip link set $tun_bridg up
ip netns add $tun_netns
ip link set dev $tun_vethI netns $tun_netns
ip netns exec $tun_netns $0 INSIDE_NETNS
trap "" 0
fi
netns-down.sh
#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
export PATH
set -ex
tun_netns=tns${dev#tun}
tun_bridg=tbr${dev#tun}
case "$tun_netns" in
(tns[0-9] | tns[0-9][0-9] | tns[0-9][0-9][0-9]) ;;
(*) exit 1;;
esac
[ -d /etc/netns/$tun_netns ] || exit 1
pids=$(ip netns pids $tun_netns)
if [ -n "$pids" ]; then
kill $pids
sleep 5
pids=$(ip netns pids $tun_netns)
if [ -n "$pids" ]; then
kill -9 $pids
fi
fi
# this automatically cleans up the the routes and the veth device pair
ip netns delete "$tun_netns"
rm -rf /etc/netns/$tun_netns
# the bridge and the tunnel device must be torn down separately
ip link set $dev down
brctl delbr $tun_bridg
destination.ovpn
client
auth-user-pass
ping 5
dev tun
resolv-retry infinite
nobind
persist-key
persist-tun
ns-cert-type server
verb 3
route-metric 1
proto tcp
ping-exit 90
remote [REDACTED]
<ca>
[REDACTED]
</ca>
<cert>
[REDACTED]
</cert>
<key>
[REDACTED]
</key>
grep veth /proc/modules
hiçbir şey listeler, ancak bunun kesin olup olmadığını bilmiyorum. Linode bulut sunucularının işletim sistemi bölümü içinde bir çekirdek yüklü olmadığından, eksik bir modülü yine de yükleyebileceğimden emin değilim.
lsmod
Hiç çıktı üretiyor mu ? Bir dizin var /lib/modules
mı?
lsmod: command not found
. Bir var /lib/modules
, ancak içinde herhangi bir modül yok, sadece boş modules.dep
dosyalar içeren bir grup çekirdek dizini var . Linode'a özgü yardımda konuşacağım ve bunun böyle olup olmadığını öğreneceğim.