Tốt thời gian trong ngày!
Trong bài viết này tôi muốn cho bạn biết tôi đã triển khai như thế nào ((Đoạn mã Bash để kết nối hai máy tính phía sau NAT bằng công nghệ UDP hole punching, sử dụng hệ điều hành làm ví dụ) Ubuntu/Debian.
Thiết lập kết nối bao gồm một số bước:
- Khởi động một nút và đợi nút từ xa sẵn sàng;
- Xác định địa chỉ IP bên ngoài và cổng UDP;
- Chuyển địa chỉ IP bên ngoài và cổng UDP sang máy chủ từ xa;
- Lấy địa chỉ IP bên ngoài và cổng UDP từ máy chủ từ xa;
- Tổ chức đường hầm IPIP;
- Giám sát kết nối;
- Nếu kết nối bị mất, hãy xóa đường hầm IPIP.
Tôi đã suy nghĩ rất lâu và vẫn nghĩ thứ có thể dùng để trao đổi dữ liệu giữa các nút, cách đơn giản và nhanh nhất đối với tôi lúc này là làm việc thông qua Yandex.disk.
- Thứ nhất, nó rất dễ sử dụng - bạn cần 3 hành động: tạo, đọc, xóa. Với cuộn tròn thì đây là:
Tạo ra:curl -s -X MKCOL --user "$usename:$password" https://webdav.yandex.ru/$folderĐọc:
curl -s --user "$usename:$password" -X PROPFIND -H "Depth: 1" https://webdav.yandex.ru/$folderXóa bỏ:
curl -s -X DELETE --user "$usename:$password" https://webdav.yandex.ru/$folder - Thứ hai, nó rất dễ cài đặt:
apt install curl
Để xác định địa chỉ IP bên ngoài và cổng UDP, hãy sử dụng lệnh stun-client:
stun stun.sipnet.ru -v -p $1 2>&1 | grep "MappedAddress"Cài đặt bằng lệnh:
apt install stun-clientĐể tổ chức một đường hầm, các công cụ hệ điều hành tiêu chuẩn từ gói iproute2 được sử dụng. tồn tại có thể được nâng lên bằng các phương tiện tiêu chuẩn (L2TPv3, GRE, v.v.), nhưng tôi đã chọn IPIP vì nó tạo ra tải bổ sung tối thiểu cho hệ thống. Tôi đã thử L2TPv3 qua UDP và rất thất vọng, tốc độ giảm 10 lần, nhưng đây có thể là những hạn chế khác nhau liên quan đến nhà cung cấp hoặc thứ gì khác. Vì đường hầm IPIP hoạt động ở cấp IP nên đường hầm FOU được sử dụng để hoạt động ở cấp cổng UDP. Để tổ chức đường hầm IPIP, bạn cần:
- tải mô-đun FOU:
modprobe fou- nghe cổng địa phương:
ip fou add port $localport ipproto 4- tạo đường hầm:
ip link add name fou$name type ipip remote $remoteip local $localip encap fou encap-sport $localport encap-dport $remoteport- nâng cao giao diện đường hầm:
ip link set up dev fou$name— gán địa chỉ IP từ xa nội bộ và nội bộ của đường hầm:
ip addr add $intIP peer $peerip dev fou$nameXóa một đường hầm:
ip link del dev fou$nameip fou del port $localportTrạng thái đường hầm được giám sát bằng cách định kỳ ping địa chỉ IP nội bộ của đường hầm nút từ xa bằng lệnh:
ping -c 1 $peerip -s 0Ping định kỳ chủ yếu cần thiết để duy trì kênh, nếu không, khi đường hầm không hoạt động, bảng NAT trên bộ định tuyến có thể bị xóa và sau đó kết nối sẽ bị hỏng.
Nếu ping biến mất thì đường hầm IPIP sẽ bị xóa và chờ máy chủ từ xa sẵn sàng.
Bản thân kịch bản:
#!/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 0Biến tên truy nhập, mật khẩu и thư mục nên giống nhau ở cả hai bên, nhưng mách nước - khác nhau, ví dụ: 10.0.0.1 và 10.0.0.2. Thời gian trên các nút phải được đồng bộ hóa. Bạn có thể chạy tập lệnh như thế này:
nohup script.sh &Tôi muốn bạn chú ý đến thực tế là đường hầm IPIP không an toàn xét từ quan điểm lưu lượng truy cập không được mã hóa, nhưng điều này có thể được giải quyết dễ dàng bằng cách sử dụng IPsec trên , nó có vẻ đơn giản và dễ hiểu đối với tôi.
Tôi đã sử dụng tập lệnh này để kết nối với PC làm việc được vài tuần và không nhận thấy bất kỳ vấn đề nào. Thuận tiện trong việc thiết lập nó và quên nó.
Có lẽ bạn sẽ có ý kiến và đề xuất, tôi sẽ rất vui khi lắng nghe.
Cảm ơn bạn!
Nguồn: www.habr.com
