Jó napot!
Ebben a cikkben szeretném elmondani, hogyan valósítottam meg () Bash szkriptet két, NAT mögött lévő számítógép összekapcsolására, UDP hole punching technológia felhasználásával, az Ubuntu/Debian operációs rendszer példáján.
A kapcsolat létrehozása több lépésből áll:
- A csomópont indítása és a távoli csomópont készenlétének várakozása;
- A külső IP-cím és UDP-port meghatározása;
- A külső IP-cím és UDP-port átadása a távoli csomópontnak;
- A külső IP-cím és UDP-port megkapása a távoli csomóponttól;
- IPIP-alagút létrehozása;
- A kapcsolat figyelése;
- Kapcsolat megszakadása esetén az IPIP alagút törlése.
Hosszú ideig gondolkodtam, és még mindig azon gondolkodom, hogy mit lehetne használni az adatok cseréjére a csomópontok között, a legegyszerűbb és leggyorsabb, amit jelenleg ismerek, az a Yandex.Disk-en keresztüli munka.
- Először is, ez egyszerű a használatában – három lépés szükséges: létrehozás, olvasás, törlés. Curl segítségével ez:
Létrehozás:curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folderOlvasás:
curl -s --user "$usename:$password" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/$folderTörlés:
curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder - Másodszor, ez egyszerű a telepítésben:
apt install curl
A külső IP-cím és UDP-port meghatározásához stun-client parancsot használunk:
stun stun.sipnet.ru -v -p $1 2>&1 | grep "MappedAddress"Telepítés parancs:
apt install stun-clientAz alagút létrehozásához az iproute2 csomagból származó beépített eszközöket használunk. Számos hozható létre beépített eszközökkel (L2TPv3, GRE stb.), de én az IPIP-et választottam, mert ez minimális extra terhelést jelent a rendszerre. Próbáltam az L2TPv3-at UDP felett, és csalódtam, a sebesség tízszeresére csökkent, de ez lehet különböző korlátozások következménye a szolgáltatóktól vagy más okok miatt. Mivel az IPIP-alagút az IP szinten működik, FOU-alagutat használunk, hogy a UDP-port szinten működhessünk. Az IPIP-alagút létrehozásához szükséges:
— a FOU modul betöltése:
modprobe fou— helyi port figyelése:
ip fou add port $localport ipproto 4— alagút létrehozása:
ip link add name fou$name type ipip remote $remoteip local $localip encap fou encap-sport $localport encap-dport $remoteport— alagút interfész aktiválása:
ip link set up dev fou$name— belső helyi és távoli IP-cím hozzárendelése az alagúthoz:
ip addr add $intIP peer $peerip dev fou$nameAlagút törlése:
ip link del dev fou$nameip fou del port $localportA tunnel's status is monitored by periodically pinging the internal IP address of the remote node's tunnel with the command:
ping -c 1 $peerip -s 0Periodic pinging is primarily needed to maintain the channel; otherwise, if the tunnel is idle, NAT tables may be cleared on the routers, causing the connection to break.
If the ping stops, the IPIP tunnel gets removed and waits for readiness from the remote node.
Here is the actual script:
#!/bin/bash
username="username@yandex.ru"
password="password"
folder="vpnid"
intip="10.0.0.1"
localport=`shuf -i 10000-65000 -n 1`
cid=`shuf -i 10000-99999 -n 1`
tid=`shuf -i 10-99 -n 1`
function yaread {
curl -s --user "$1:$2" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/$3 | sed 's/></>n</g' | grep "displayname" | sed 's/<d:displayname>//g' | sed 's/</d:displayname>//g' | grep -v $3 | grep -v $4 | sort -r
}
function yacreate {
curl -s -X MKCOL --user "$1:$2" https://webdav.yandex.ru/$3
}
function yadelete {
curl -s -X DELETE --user "$1:$2" https://webdav.yandex.ru/$3
}
function myipport {
stun stun.sipnet.ru -v -p $1 2>&1 | grep "MappedAddress" | sort | uniq | awk '{print $3}' | head -n1
}
function tunnel-up {
modprobe fou
ip fou add port $4 ipproto 4
ip link add name fou$7 type ipip remote $1 local $3 encap fou encap-sport $4 encap-dport $2
ip link set up dev fou$7
ip addr add $6 peer $5 dev fou$7
}
function tunnel-check {
sleep 10
pings=0
until [[ $pings == 4 ]]; do
if ping -c 1 $1 -s 0 &>/dev/null;
then echo -n .; n=0
else echo -n !; ((pings++))
fi
sleep 15
done
}
function tunnel-down {
ip link del dev fou$1
ip fou del port $2
}
trap 'echo -e "nDisconnecting..." && yadelete $username $password $folder; tunnel-down $tunnelid $localport; echo "IPIP tunnel disconnected!"; exit 1' 1 2 3 8 9 14 15
until [[ -n $end ]]; do
yacreate $username $password $folder
until [[ -n $ip ]]; do
mydate=`date +%s`
timeout="60"
list=`yaread $username $password $folder $cid | head -n1`
yacreate $username $password $folder/$mydate:$cid
for l in $list; do
if [ `echo $l | sed 's/:/ /g' | awk {'print $1'}` -ge $(($mydate-65)) ]; then
#echo $list
myipport=`myipport $localport`
yacreate $username $password $folder/$mydate:$cid:$myipport:$intip:$tid
timeout=$(( $timeout + `echo $l | sed 's/:/ /g' | awk {'print $1'}` - $mydate + 3 ))
ip=`echo $l | sed 's/:/ /g' | awk '{print $3}'`
port=`echo $l | sed 's/:/ /g' | awk '{print $4}'`
peerip=`echo $l | sed 's/:/ /g' | awk '{print $5}'`
peerid=`echo $l | sed 's/:/ /g' | awk '{print $6}'`
if [[ -n $peerid ]]; then tunnelid=$(($peerid*$tid)); fi
fi
done
if ( [[ -z "$ip" ]] && [ "$timeout" -gt 0 ] ) ; then
echo -n "!"
sleep $timeout
fi
done
localip=`ip route get $ip | head -n1 | sed 's|.*src ||' | cut -d' ' -f1`
tunnel-up $ip $port $localip $localport $peerip $intip $tunnelid
tunnel-check $peerip
tunnel-down $tunnelid $localport
yadelete $username $password $folder
unset ip port myipport
done
exit 0Változók username, password és folder must be the same on both sides, while intip — can be different, for example: 10.0.0.1 and 10.0.0.2. The time on the nodes must be synchronized. You can run the script like this:
nohup script.sh &Please note that the IPIP tunnel is not secure in terms of unencrypted traffic, but this can be easily resolved by using IPsec. I found it simple and comprehensible.
I have been using this script to connect to my work PC for several weeks, and I haven't noticed any problems. It's convenient in that I set it up and forgot about it.
You may have comments and suggestions; I would be happy to hear them.
Köszönöm a figyelmet!
Forrás: habr.com
