Připojení zařízení pomocí IPv6 a tunelu prakticky
V předchozím díle krátkého seriálu jsme si vysvětlili princip, na jehož
základě lze zpřístupnit téměř libovolné zařízení na internetu pomocí
IPv6 a tunelu. V této části si ukážeme prakticky, jakým způsobem je možné takový
tunel vytvořit a jak přidělit svému zařízení za NATem veřejnou IPv6 adresu.
14.2.2013 00:00 |
Petr Bravenec
| Články autora
| přečteno 5024×
Při praktickém nastavování tunelu jsem se nechal inspirovat tímto krátkým návodem:
http://www.sixxs.net/wiki/L2tp
Pokud nezvolíte nějakou neobvyklou architekturu, mohli byste mít podle tohoto
návodu nastavený základ pro tunel s IPv6 během chvilky. S trochou štěstí by vám
mohl tunel už napoprvé fungovat alespoň na linkových adresách během půl hodiny
(já jsem si celou úlohu trochu zkomplikoval procesorem ARM, ale už po dvou
týdnech jsem na internetu našel fungující zdrojáky linuxového kernelu a mohl
doplnit podporu pro l2tp a ppp).
Tunel jsem zkoušel vytvořit v distribuci Debian (na architektuře x86) a Gentoo
(arm). Pro vytvoření tunelu s linkovými adresami potřebujete prakticky jen
démony xl2tpd
a pppd, pro nastavení veřejné IPv6 adresy
pak můžete potřebovat i některý další program:
radvd, dhcpd nebo, jako já, něco úplně
jiného.
Nastavení serveru
Na serveru vytvořte konfigurační soubor /etc/xl2tpd/xl2tpd.conf:
[global]
[lns default]
name = mujserver
assign ip = no
require chap = yes
refuse pap = yes
require authentication = yes
unix authentication = no
ppp debug = no
pppoptfile = /etc/ppp/options.l2tpd
Zařízení se musí při vytváření tunelu autentikovat mechanismem chap. Heslo je uložené v souboru
/etc/xl2tpd/l2tp-secrets:
# Secrets for authenticating l2tp tunnels
# us them secret
# my oni heslo
#
mujserver zarizeni heslo
Podobný soubor s hesly je umístěn i na zařízení, tam jsou však strany "my" a
"oni" prohozené. Heslo můžete mít společné pro různá zařízení, není však
problém vytvořit pro každé zařízení heslo vlastní.
V konfiguračním souboru můžete chtít změnit pouze parametr name - tento parametr je společným
propojovatelem klientské části, serverové části a heslo.
Xl2tpd démon poslouchá na UDP portu 1701 (nezapomeňte na pravidla ve firewallu) a při
příchozím požadavku na vytvoření tunelu od zařízení startuje pro toto zařízení démona pppd.
Toho musíte nastavit taky. V konfiguraci xl2tpd je uvedeno, že pro pppd se má použít
konfigurační soubor /etc/ppp/options.l2tpd:
refuse-eap
noccp
noauth
nodefaultroute
crtscts
idle 1800
mtu 1410
mru 1410
lock
connect-delay 5000
noip # zakáže IPv4
+ipv6 # povolí IPv6
ipv6 , # adresy pro IPv6 (nepřidělují se, zůstává prázdné)
ipv6cp-accept-local # nastavit pouze linkové adresy
Po nastavení stačí na serveru spoustit démon xl2tpd. Jedinou podmínkou pro
fungování démona je podpora pro l2tp a ppp v kernelu (obvykle není problém) a
natažené moduly ipv6 a l2tp_ppp.
Nastavení zařízení
Na straně zařízení je nastavení podobně jednoduché. Konfigurační soubor
/etc/xl2tpd/xl2tpd.conf:
[global]
[lac mujserver]
name = zarizeni
lns = mojebrana.hobrasoft.cz:1702
redial = yes
redial timeout = 15
require chap = yes
refuse pap = yes
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.l2tpd.client
Konfigurace xl2tpd na straně zařízení je podobná konfiguraci na serveru.
Pravděpodobně budete chtít změnit jméno sekce "lac" - sem uveďte jméno tunelu
na serveru - zde "mujserver", a parametr "name". Důležité je nastavení
parametru "lns" - zde se očekává buď IPv4 adresa nebo dns jméno, uvést můžete i
číslo portu (port 1702 používám kvůli jistému adminovi v zahraničí, který na
požadavek "povolte ven port 1701 protokolem UDP" povolil vše ostatní, kromě
portu 1701 - ten zakázal. Než shánět tlumočníka, abych adminovi sdělil svůj
názor a vysvětlil význam požadavku, bylo jednodušší doplnit na serveru jedno
pravidlo do iptables a změnit port).
Velmi podobný je i soubor s hesly /etc/xl2tpd/l2tp-secrets:
# Secrets for authenticating l2tp tunnels
# us them secret
# my oni heslo
#
zarizeni mujserver heslo
Konfigurace pppd je umístěná v souboru /etc/ppp/options.l2tpd.client a je prakticky shodná s konfigurací na serveru:
refuse-eap
noccp
noauth
nodefaultroute
crtscts
idle 1800
mtu 1410
mru 1410
lock
connect-delay 5000
noip # zakáže IPv4
+ipv6 # povolí IPv6
ipv6 , # adresy pro IPv6 (nepřidělují se, zůstává prázdné)
ipv6cp-accept-local # nastavit pouze linkové adresy
Jakmile máte nakonfigurovaný a nastartovaný xl2tpd démon na obou koncích, na serveru i na zařízení, můžete na
zařízení vyzkoušet nastartovat tunel:
echo "c mujserver" > /var/run/xl2tpd/l2tp-control
S trochou štěstí by se už nyní mohl tunel rozběhnout, ověřit jej můžete příkazem ifconfig nebo ip. Ve výpisu
by mělo figurovat síťové rozhraní ppp0 s linkovou IPv6 adresou:
# ifconfig
ppp0 Link encap:Point-to-Point Protokol
inet6-adr: fe80::1923:481c:d7f8:68dd/10 Rozsah:Linka
AKTIVOVÁNO POINTOPOINT BĚŽÍ NEARP MULTICAST MTU:1410 Metrika:1
RX packets:11 errors:0 dropped:0 overruns:0 frame:0
TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
kolizí:0 délka odchozí fronty:3
RX bytes:720 (720.0 B) TX bytes:618 (618.0 B)
# ip addr
109: ppp0: mtu 1410 qdisc pfifo_fast state UNKNOWN qlen 3
link/ppp
inet6 fe80::1923:481c:d7f8:68dd/10 scope link
valid_lft forever preferred_lft forever
Máte-li adresu nastavenou, můžete svůj nový tunel vyzkoušet. Nezapomeňte, že
linkové adresy lze použít pouze na síťovém rozhraní ppp0 a příkazu ping musíte
parametrem -I sdělit, které rozhraní má použít. Adresu protějšku můžete zjistit
na druhé straně tunelu:
# ping6 -I ppp0 fe80::fdc8:d2e6:eb72:ac51
PING fe80::fdc8:d2e6:eb72:ac51(fe80::fdc8:d2e6:eb72:ac51) from fe80::1923:481c:d7f8:68dd ppp0: 56 data bytes
64 bytes from fe80::fdc8:d2e6:eb72:ac51: icmp_seq=1 ttl=64 time=108 ms
64 bytes from fe80::fdc8:d2e6:eb72:ac51: icmp_seq=2 ttl=64 time=102 ms
64 bytes from fe80::fdc8:d2e6:eb72:ac51: icmp_seq=3 ttl=64 time=86.0 ms
Nyní by měl mezi serverem a zařízením fungovat veškerý síťový provoz, můžete se
zkusit připojit například přes ssh, opět nezapomeňte uvést jméno síťového
rozhraní:
# ssh 'fe80::fdc8:d2e6:eb72:ac51%ppp0'
The authenticity of host 'fe80::fdc8:d2e6:eb72:ac51%ppp0 (fe80::fdc8:d2e6:eb72:ac51%ppp0)' can't be established.
RSA key fingerprint is 68:7d:e6:2b:e4:e9:5c:a2:a9:a7:d4:90:4b:83:6b:06.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'fe80::fdc8:d2e6:eb72:ac51%ppp0' (RSA) to the list of known hosts.
Password:
server ~ #
Zprovoznění IPv6 protokolu na linkových adresách je základ, bez kterého nemá
smysl pokračovat dál. Máte-li s nastavením tunelu problém, zkuste hledat v logu
/var/log/daemon.log, pomoci vám může i utilita tcpdump.
Startování tunelu
Pro automatické startování tunelu musíte do startovacích skriptů spouštěných
při startu systému zahrnout i xl2tpd. Tím však nastartujete pouze démona, tunel
se nevytvoří. Ten se vytváří až při zápisu příkazu "c mujserver" do souboru
/var/run/xl2tpd/l2tp-control. Teoreticky by mělo stačit vytvořit tunel
jednorázově po startu xl2tpd. Prakticky to nestačí - xl2tpd v distribuci Debian
po nějakém čase neúspěšnou snahu na nastartování tunelu vzdá a vy tak můžete
zůstat bez připojení, dokud někdo zařízení schované za NATem nerestartuje
(parametr max redial nefunguje, jak by měl). Vhodnější a jednodušší, než
vytvářet vlastní startovací skript pro vytvoření tunelu, je jediný řádek v
crontab:
*/5 * * * * echo "c mujserver" > /var/run/xl2tpd/l2tp-control
Přizabijete tak dvě mouchy jednou ranou: vytváření tunelu při startu systému a
restart tunelu při déletrvajících problémech s IPv4.
Nastavení veřejné IPv6 adresy
Zprovoznění linkové adresy je jen část úkolu. Kvůli point-to-point komunikaci
nemělo smysl nastavovat IPv6 tunel, v původním zadání šlo o zpřístupnění
zařízení v lokální síti pomocí veřejné IPv6 adresy.
Máte-li v internetu jediné zařízení, které chcete takto vybavit veřejnou IPv6 adresou,
je nejjednodušší uvést adresy přímo do konfiguračního souboru pro pppd:
# Původní řádek zakomentovat, nebo smazat
# ipv6 , # adresy pro IPv6 (nepřidělují se, zůstává prázdné)
ipv6 2001:db8:3000:1::1, 2001:db8:3000:1::2
Máte-li zařízení více, je možné použít pro přidělování adres démona radvd. V
tomto případě je ale potřeba vytvořit konfiguraci pro každé síťové rozhraní v
souboru /etc/radvd.conf podobnou této:
interface ppp0 {
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
AdvHomeAgentFlag off;
prefix 2001:db8:3000:1::/64 {
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
};
};
Potíž může být v tom, že při přidělování adres pomocí radvd můžete dostat
pokaždé jinou IPv6 adresu. Neovlivníte ani síťové rozhraní, nad kterým se tunel
vytváří, takže vaše zařízení může dokonce pokaždé spadnout i do jiné sítě.
Pokud vám to nevadí, může být radvd nejjednodušším řešením (nezkoušel jsem).
Výše zmiňovaný informační pramen zmiňuje pro nastavení IP adres
také program quagga
a routovací protokol ospf6.
Jinou cestou může být přidělování adres pomocí dhcp (na IPv6 nemám zkušenosti),
kde však může být problém naopak s tím, že dostanete pokaždé stejnou IPv6
adresu - mně to třeba vadí z toho důvodu, že potřebuji mít adresu nastavitelnou
jednoduše v zařízení. Sám jsem proto zvolil třetí, nejméně vhodnou cestu:
zařízení se dohodne na IPv6 adrese se serverem pomocí jednoduchého skriptu,
který se spouští po úšpěšném vytvoření tunelu.
Skript /etc/ppp/ipv6-up
Jakmile je tunel vytvořený a ppp nastaví linkové adresy pro spojení zařízení se
serverem, máte možnost do celého procesu vstoupit pomocí skriptu
/etc/ppp/ipv6-up. Ten je volán z programu pppd a umožňuje vám provádět s celou
linkou další různá kouzla. V distribucích už bývají obsažené různé skripty,
které mění například /etc/resolv.conf, sambu, poštovní server (v každé
distribuci najdete něco jiného). Skript lze s úspěchem použít i pro nastavení
IPv6 adres na obou stranách tunelu (jak na serveru, tak na zařízení). Jako
typické využití skriptu bych viděl nastavení firewallu.
Skript se spouští na obou stranách tunelu. Skript je volaný s několika užitečnými
parametry (podle pořadí):
- $1 - jméno síťového zařízení (například ppp0)
- $2 - jméno sériové linky modemu (zde naprosto k ničemu)
- $3 - rychlost modemu (zde naprosto k ničemu)
- $4 - lokální IP adresa
- $5 - vzdálená IP adresa
- $6 - ipparam (uživatelský parametr, více se dočtete v manuálu)
Všimněte si, že skript dostane všechny potřebné informace pro komunikaci s druhou stranou.
Ve skriptu na zařízení se můžete připojit na server přes nově vytvořený tunel a požádat
si například o IP adresu pomocí HTTP protokolu (na druhé straně musí poslouchat webový server):
wget http://$4%1/dej-mi-adresu?HOSTNAME=`hostname`
Na straně serveru pak můžete skript využít pro nastavení firewallu, například takto:
ip6tables -A FORWARD -i $1 -j ACCEPT
ip6tables -A FORWARD -o $1 -j ACCEPT
Podobně, jako je při vytvoření tunelu volaný skript /etc/ppp/ipv6-up, při
ukončení tunelu se volá skript /etc/ppp/ipv6-down. Sem lze umístit například
uklízení v iptables na straně serveru, aby se vám ve firewallu nehromadila
zbytečná pravidla:
ip6tables -D FORWARD -i $1 -j ACCEPT
ip6tables -D FORWARD -o $1 -j ACCEPT
U zařízení pro sběr dat z fotovoltaických elektráren jsem skripty využil jak
pro nastavení veřejných IPv6 adres a firewallu, tak i pro další konfiguraci
zařízení, aby se zprovoznění vlastního zařízení omezilo na zapojení do sítě,
nastavení hostname a případně nastavení IPv4 adresy (pro případ, že je nutné
zařízení provozovat v síti bez DHCP).
Netcat6
Pro předávání parametrů jsem využil utilitu
netcat6. Netcat
je velmi univerzální nástroj pro komunikaci po síti - dokaže se připojit
protokolem UDP či TCP na libovolnou IP adresu s libovolným číslem portu (pak
jej můžete používat místo telnetu), nebo dokáže poslouchat na síti, čekat na
příchozí spojení a síťový provoz propojit s vaším vlastním skriptem. Pomocí
nástroje netcat tak můžete vytvořit v shellu jednoduchý síťový server.
"Originál" netcat nedovede pracovat v síti IPv6. V Gentoo jsem objevil čtyři
různé verze programu netcat, ale z těch vyzkoušených pro mé účely vyhovoval
pouze netcat6.
Pro skripty v ppp je dále výhodou, že u programu netcat lze velmi přesně
specifikovat, na jakém síťovém rozhraní, na kterém portu a jakým protokolem má
netcat poslouchat, nastavit lze i různé timeouty. Díky tomu je možné netcat
nastavit tak, aby se vaše zařízení mohla domlouvat pouze přes tunel a pouze v
krátkém časovém okamžiku těsně po vytvoření tunelu. Nemusíte se proto příliš
trápit se zabezpečením (nikdo jiný se s vámi bavit nemůže), ani s uklízením (po
vypršení timeoutu netcat automaticky skončí).
Ukážu vám nyní svoje skripty pro nastavení linky (očesané na nezbytné minimum).
Berte je, prosím, s malou rezervou. Chcete-li si situaci maximálně zjednodušit,
můžete ve svých skriptech nastavit IPv6 adresy natvrdo (nemáte-li zařízení více
a hodláte spoléhat na to, že váš ISP vaše IPv6 adresy nezmění).
Skript /etc/ppp/ipv6-up na straně serveru
#!/bin/sh
# Pracovní skript v /tmp adresáři
# Spouští se z programu netcat, jakmile protistrana naváže spojení
SCRIPT=/tmp/ipv6-up.$$.sh
# Přidat pravidlo do ip6tables
ip6tables -A FORWARD -i $1 -j ACCEPT
ip6tables -A FORWARD -o $1 -j ACCEPT
# Zde se vytváří skript pro netcat
cat < $SCRIPT
#!/bin/sh
IFACE=$1
LOCALIP=$4
REMOTEIP=$5
# do proměnné X je načteno hostname protistrany
read X
PUBLICIP=\$( cat /root/seznam-zarizeni | awk -v X="\$X" '\$1 == X { print \$2; }' )
if [ "\$PUBLICIP" = "" ]; then
PUBLICIP="2001:db8:3000::1"
fi
LOCALPUBLICIP="\${PUBLICIP}1"
REMOTEPUBLICIP="\${PUBLICIP}2"
/sbin/ip addr add "\$LOCALPUBLICIP" dev $1
/sbin/ip -6 route add "\$PUBLICIP/64" dev $1
echo "\$REMOTEPUBLICIP"
echo
echo
!
chmod 700 $SCRIPT
# Spustí se netcat a poslouchá na portu 1371 na spojení protistrany
# Jakmile je spojení uskutečněno, spustí se skript pro komunikaci
# s protistranou (vyvořený výše). Skript očekává hostname a podle
# hostname v jednoduchém seznamu vyhledá adresu a pošle ji protistraně
nc6 --timeout 15 --idle-timeout 3 -6 --exec $SCRIPT --listen --port 1371 --address "$4%$1"
rm -f $SCRIPT
Skript /etc/ppp/ipv6-up na straně zařízení
#!/bin/sh
sleep 1
# Parametry spojení zjištuji podle hostname
export HOSTNAME=$(hostname)
# Do X se uloží odpověď serveru (IPv6 adresa)
X=$(echo $HOSTNAME | nc6 --timeout 3 --idle-timeout 3 -6 "$5%$1" 1371)
NET=$(echo $X | sed 's/::.*/::/')
/sbin/ip addr add $X dev $1
/sbin/ip -6 route add ${NET}/64 dev $1
/sbin/ip -6 route replace default via ${NET}1 dev $1
Součástí uvedeného řešení je i tabulka s parametry. V tomto případě je tabulka
velmi jednoduchá. Skript ji očekává v /root/seznam-zarizeni. V tabulce je pro
každé zařízení jeden řádek s hostname zařízení a adresou sítě:
zarizeni1 2001:db8:3000:1::
zarizeni2 2001:db8:3000:2::
zarizeni3 2001:db8:3000:3::
Odkazy
Závěr
Dnešní technologie dokáže levně a snadno řešit množství úloh, které dříve
spadaly do kategorie scifi. Kde včera sbíral data několik dní člověk se
zápisníkem, stačí dnes jednoduché, jednoúčelové zařízení postavené na bázi PC
nebo jednodeskového ARM počítače. Kupodivu je to jiná technologie - IPv4 a NAT,
která efektivnímu využívání brání.
Řešení představené v článku ukazuje jednu z cest, jak využít alespoň oklikou
množství adres, které nabízí IPv6. Nepochybuji o tom, že by se dalo vymyslet
lepší řešení, zvláště pro přidělování a předávání veřejných IPv6 adres.
Budu rád, pokud mě na taková řešení upozorníte.
Verze pro tisk
|
Nejsou žádné diskuzní příspěvky u dané položky.
Příspívat do diskuze mohou pouze registrovaní uživatelé.
|
|