Артыкул аб тым, як мне атрымалася запусціць VPN-сервер за NAT'ам хатняга правайдэра (без белага IP-адрасу). Адразу абмоўлюся: што працаздольнасць дадзенай рэалізацыя напрамую залежыць ад тыпу NAT выкарыстоўванага Вашым правайдэрам, а таксама роўтэрам.
Такім чынам, узнікла ў мяне неабходнасць падлучацца са свайго Android-смартфона да хатняга кампутара, абодва дэвайса падлучаныя да Інтэрнэту праз правайдэрскія NAT'ы, плюсам кампутар падлучаны праз хатні роўтар, які таксама NAT'іл злучэнні.
Класічная схема з выкарыстаннем арандаванага VPS/VDS з белым IP-адрасам, а таксама арэнда белага IP-адрасу ў правайдэра не разглядалася па некалькіх прычынах.
З улікам
$ stun stun.sipnet.ru
атрымаў вынік:
STUN client version 0.97
Primary: Independent Mapping, Independent Filter, random port, will hairpin
Return value is 0x000002
Даслоўны пераклад:
Independent Mapping - незалежнае адлюстраванне
Independent Filter – незалежны фільтр
random port - выпадковы порт
will hairpin - будзе шпілька
Выканаўшы аналагічную каманду на сваім ПК, атрымаў:
STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Return value is 0x000006
Port Dependent Filter – порт залежны фільтр
Розніца ў выніках вываду каманд казала аб тым, што хатні роўтэр уносіў «свой уклад» у працэс трансляцыі пакетаў з Інтэрнэту, гэта выяўлялася ў тым, што пры выкананні каманды на кампутары:
stun stun.sipnet.ru -p 11111 -v
я атрымліваў вынік:
...
MappedAddress = XX.1XX.1X4.2XX:4398
...
у гэты момант на некаторы час адчынялася UDP-сесія, калі ў гэты момант паслаць UDP-запыт (напрыклад: netcat XX.1XX.1X4.2XX 4398 -u), то запыт прыходзіў на хатні роўтар, што пацвердзіў TCPDump запушчаны на ім, але запыт не даходзіў да кампутара – IPtables у якасці NAT-транслятара на роўтары драпаў яго.
Але сам факт праходжання UDP запыту праз правайдэрскі NAT даваў надзею на поспех. Так як роўтэр знаходзіцца ў маёй юрысдыкцыі, вырашыў праблему перанакіраваннем UDP/11111 порта на кампутар:
iptables -t nat -A PREROUTING -i eth1 -p udp -d 10.1XX.2XX.XXX --dport 11111 -j DNAT --to-destination 192.168.X.XXX
Тым самым атрымаў магчымасць ініцыяваць UDP-сесію і атрымліваць запыты з Інтэрнэта з любога IP-адрасу. У гэты момант запусціў OpenVPN-server (папярэдне сканфігураваўшы) слухаючы UDP/11111 порт, паказаў на смартфоне вонкавы IP-адрас і порт (XX.1XX.1X4.2XX:4398) і паспяхова падлучыўся са смартфона да кампутара. Але ў дадзенай рэалізацыі ўзнікла праблема, трэба было неяк падтрымліваць UDP-сесію да моманту падключэння OpenVPN-кліента да сервера, варыянт з перыядычным запускам STUN-кліента мне не спадабаўся – не хацелася марна нагружаць STUN-серверы.
Таксама звярнуў увагу на запіс
Hairpinning дазваляе адной машыне ў лакальнай сетцы за NAT атрымаць доступ да іншай машыны ў той жа сеткі па вонкавым адрасе маршрутызатара.
У выніку праблему падтрымання UDP-сесіі вырашыў проста - запусціў кліента на гэтым жа кампутары з серверам.
Працавала гэта так:
- запускаў STUN-кліента з лакальным портам 11111
- атрымліваў адказ з вонкавым IP-адрасам і портам XX.1XX.1X4.2XX:4398
- адпраўляў дадзеныя з вонкавым IP-адрасам і портам на пошту (магчымы любы іншы сэрвіс), наладжаную на смартфоне
- запускаў OpenVPN-сервер на кампутары з праслухоўкай UDP/11111 порта
- запускаў OpenVPN-кліента на кампутары з указаннем XX.1XX.1X4.2XX:4398 для падлучэння
- у любы час запускаў OpenVPN-кліента на смартфоне з указаннем IP-адрасы і порта (у маім выпадку IP-адрас не змяняўся) для падлучэння
Такім чынам я атрымаў магчымасць падлучацца да свайго кампутара са смартфона. Дадзеная рэалізацыя дазваляе падлучаць любога OpenVPN-кліента.
Практыка
спатрэбіцца:
# apt install openvpn stun-client sendemail
Напісаўшы пару скрыптоў, пару канфігурацыйных файлаў, згенераваўшы неабходныя сертыфікаты (бо кліент на смартфоне працуе толькі па сертыфікатах) атрымалася звычайная рэалізацыя OpenVPN-сервера.
Асноўны скрыпт на кампутары
# cat vpn11.sh
#!/bin/bash
until [[ -n "$iftosrv" ]]; do echo "$(date) Определяю сетевой интерфейс"; iftosrv=`ip route get 8.8.8.8 | head -n 1 | sed 's|.*dev ||' | awk '{print $1}'`; sleep 5; done
ABSOLUTE_FILENAME=`readlink -f "$0"`
DIR=`dirname "$ABSOLUTE_FILENAME"`
localport=11111
until [[ $a ]]; do
address=`stun stun.sipnet.ru -v -p $localport 2>&1 | grep "MappedAddress" | sort | uniq | head -n 1 | sed 's/:/ /g' | awk '{print $3" "$4}'`
ip=`echo "$address" | awk {'print $1'}`
port=`echo "$address" | awk {'print $2'}`
srv="openvpn --config $DIR/server.conf --port $localport --daemon"
$srv
echo "$(date) Сервер запущен с внешним адресом $ip:$port"
$DIR/sendemail.sh "OpenVPN-Server" "$ip:$port"
sleep 1
openvpn --config $DIR/client.conf --remote $ip --port $port
echo "$(date) Cоединение клиента с сервером разорвано"
for i in `ps xa | grep "$srv" | grep -v grep | awk '{print $1}'`; do
kill $i && echo "$(date) Завершен процесс сервера $i ($srv)"
done
echo "Жду 15 сек"
sleep 15
done
Скрыпт адпраўкі даных на пошту:
# cat sendemail.sh
#!/bin/bash
from="От кого"
pass="Пароль"
to="Кому"
theme="$1"
message="$2"
server="smtp.yandex.ru:587"
sendEmail -o tls=yes -f "$from" -t "$to" -s "$server" -xu "$from" -xp "$pass" -u "$theme" -m "$message"
Канфігурацыйны файл сервера:
# cat server.conf
proto udp
dev tun
ca /home/vpn11-srv/ca.crt
cert /home/vpn11-srv/server.crt
key /home/vpn11-srv/server.key
dh /home/vpn11-srv/dh2048.pem
server 10.2.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
tls-server
tls-auth /home/vpn11-srv/ta.key 0
tls-timeout 60
auth SHA256
cipher AES-256-CBC
client-to-client
keepalive 10 30
comp-lzo
max-clients 10
user nobody
group nogroup
persist-key
persist-tun
log /var/log/vpn11-server.log
verb 3
mute 20
Канфігурацыйны файл кліента:
# cat client.conf
client
dev tun
proto udp
ca "/home/vpn11-srv/ca.crt"
cert "/home/vpn11-srv/client1.crt"
key "/home/vpn11-srv/client1.key"
tls-client
tls-auth "/home/vpn11-srv/ta.key" 1
auth SHA256
cipher AES-256-CBC
auth-nocache
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
log /var/log/vpn11-clent.log
verb 3
mute 20
ping 10
ping-exit 30
Генерацыя сертыфікатаў праводзілася па
Запуск скрыпту:
# ./vpn11.sh
Папярэдне зрабіўшы яго выкананым
# chmod +x vpn11.sh
На баку смартфона
Усталяваўшы дадатак OpenVPN для Android, скапіяваўшы канфігурацыйны файл, сертыфікаты і наладзіўшы яго, атрымалася так:
На смартфоне правяраю пошту
Праўлю нумар порта ў наладах
Запускаю кліента і падключаюся
У працэсе напісання артыкула я перанёс канфігурацыю з кампутара на Raspberry Pi 3 і паспрабаваў запусціць усю гэтую справу на LTE мадэме, але не атрымалася! Вынік каманды
# stun stun.ekiga.net -p 11111
STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Return value is 0x000006
значэнне Port Dependent Filter не дазволіла запусціцца сістэме.
Але хатні правайдэр без праблем даў запусціцца сістэме на Raspberry Pi 3.
У звязку з вэб-камерай, зVLC для
стварэння RTSP-струменю з вэб-камеры
$ cvlc v4l2:///dev/video0:chroma=h264 :input-slave=alsa://hw:1,0 --sout '#transcode{vcodec=x264,venc=x264{preset=ultrafast,profile=baseline,level=31},vb=2048,fps=12,scale=1,acodec=mpga,ab=128,channels=2,samplerate=44100,scodec=none}:rtp{sdp=rtsp://10.2.0.1:8554/}' --no-sout-all --sout-keep
і VLC на смартфоне для прагляду (струмень rtsp://10.2.0.1:8554/), атрымалася не дрэнная сістэма відэаназірання на адлегласці, гэтак жа можна падняць Samba, маршрутызаваць трафік праз VPN, выдалена кіраваць кампутарам і шмат чаго яшчэ…
Выснова
Як паказала практыка, для аргінізацыі VPN-сервера можна абыйсціся і без вонкавага IP-адрасы за які трэба плаціць, гэтак жа як і за які арандуецца VPS/VDS. Але ўсё залежыць ад правайдэра. Вядома жадалася атрымаць больш інфармацыі аб розных правайдэрах і тыпах выкарыстоўваных NAT'ов, але гэта толькі пачатак…
Дзякуй за ўвагу!
Крыніца: habr.com