Good time!
In this article I want to tell how I implemented (
Establishing a connection consists of several steps:
- Starting the node and waiting for the remote node to be ready;
- Determining the external IP address and UDP port;
- Transferring the external IP address and UDP port to the remote host;
- Obtaining an external IP address and UDP port from a remote host;
- Organization of an IPIP tunnel;
- Connection monitoring;
- If the connection is broken, delete the IPIP tunnel.
I thought for a long time and still think what can be used to exchange data between nodes, the simplest and fastest for me at the moment is working through Yandex.disk.
- Firstly, it is ease of use - you need 3 actions: create, read, delete. With curl it is:
Create:curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folder
Read:
curl -s --user "$usename:$password" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/$folder
Delete:
curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder
- Second, it's easy to install:
apt install curl
To determine the external IP address and UDP port, use the stun-client command:
stun stun.sipnet.ru -v -p $1 2>&1 | grep "MappedAddress"
Installation by command:
apt install stun-client
To organize the tunnel, regular OS tools from the iproute2 package are used. Exists
β load the FOU module:
modprobe fou
- listen on local port:
ip fou add port $localport ipproto 4
- create a tunnel:
ip link add name fou$name type ipip remote $remoteip local $localip encap fou encap-sport $localport encap-dport $remoteport
- raise the tunnel interface:
ip link set up dev fou$name
β assign the internal local and internal remote IP addresses of the tunnel:
ip addr add $intIP peer $peerip dev fou$name
Remove tunnel:
ip link del dev fou$name
ip fou del port $localport
The tunnel state is monitored by periodically pinging the internal IP address of the tunnel of a remote node, using the command:
ping -c 1 $peerip -s 0
Periodic ping is needed primarily to maintain the channel, otherwise, if the tunnel is idle, the NAT tables on the routers may be cleared and then the connection will be terminated.
If the ping fails, then the IPIP tunnel is removed and waits for a readiness from the remote host.
Actually the script itself:
#!/bin/bash
username="[email protected]"
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 0
Variables username, Password ΠΈ folder should be the same on both sides, but peek - 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 &
I draw your attention to the fact that the IPIP tunnel is not secure in terms of the fact that the traffic is not encrypted, but this is easily solved using IPsec by
I have been using this script to connect to a working PC for several weeks and have not noticed any problems. Convenient in terms of what you set up and forget.
Perhaps you will have comments and suggestions, I will be glad to listen.
Thank you for attention!
Source: habr.com