Artykuł o tym, jak udało mi się uruchomić serwer VPN za NAT-em domowego dostawcy (bez publicznego adresu IP). Od razu zaznaczam, że funkcjonalność tej realizacji bezpośrednio zależy od typu NAT używanego przez Twojego dostawcę oraz router..
Otóż, pojawiła się u mnie potrzeba podłączenia się z mojego smartfona z Androidem do domowego komputera, oba urządzenia są połączone z Internetem przez NAT-y dostawcy, dodatkowo komputer jest podłączony przez domowy router, który również NAT-uje połączenia.
Klasyczny schemat z wykorzystaniem wynajmowanego VPS/VDS z publicznym adresem IP, a także wynajem publicznego adresu IP od dostawcy nie był brany pod uwagę z kilku powodów.
Biorąc pod uwagę doświadczenia z poprzednich artykułów, przeprowadzając kilka eksperymentów ze STUN-ami i NAT-ami dostawców. Postanowiłem zrealizować mały eksperyment, wykonując polecenie na domowym routerze działającym na oprogramowaniu OpenWRT:
$ stun stun.sipnet.ruotrzymałem wynik:
STUN client version 0.97
Primary: Independent Mapping, Independent Filter, random port, will hairpin
Wartość zwrotna to 0x000002
Dosłowne tłumaczenie:
Independent Mapping — niezależne mapowanie
Independent Filter — niezależny filtr
random port — losowy port
will hairpin — będzie pinować
Wykonując analogiczne polecenie na swoim komputerze, otrzymałem:
STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Wartość zwrotna to 0x000006
Port Dependent Filter — filtr zależny od portu
Różnica w wynikach poleceń wskazywała na to, że domowy router wnosił "swoją cegiełkę" w proces translacji pakietów z Internetu, objawiało się to tym, że po wykonaniu polecenia na komputerze:
stun stun.sipnet.ru -p 11111 -votrzymywałem wynik:
…
MappedAddress = XX.1XX.1X4.2XX:4398
…
w tym momencie na chwilę otwierała się sesja UDP, jeśli w tym momencie wysłać zapytanie UDP (na przykład: netcat XX.1XX.1X4.2XX 4398 -u), to zapytanie przychodziło na domowy router, co potwierdził TCPDump uruchomiony na nim, ale zapytanie nie docierało do komputera — IPtables jako NAT-traslator na routerze odrzucał je.

Jednak sam fakt przejścia zapytania UDP przez NAT dostawcy dawał nadzieję na sukces. Ponieważ router znajduje się w mojej kompetencji, rozwiązałem problem przekierowując port UDP/11111 na komputer:
iptables -t nat -A PREROUTING -i eth1 -p udp -d 10.1XX.2XX.XXX --dport 11111 -j DNAT --to-destination 192.168.X.XXXW ten sposób uzyskałem możliwość nawiązania sesji UDP i odbierania żądań z Internetu z dowolnego adresu IP. W tym momencie uruchomiłem serwer OpenVPN (wcześniej go konfigrując), nasłuchując na porcie UDP/11111, wskazałem na smartfonie zewnętrzny adres IP i port (XX.1XX.1X4.2XX:4398) i pomyślnie połączyłem się z komputera. Jednak w tej realizacji pojawił się problem, ponieważ trzeba było jakoś utrzymać sesję UDP do momentu połączenia klienta OpenVPN z serwerem; nie podobała mi się opcja z okresowym uruchamianiem klienta STUN — nie chciałem bez potrzeby obciążać serwerów STUN.
Zwróciłem również uwagę na zapis «will hairpin — będzie pinować«, tryb ten
Hairpinning pozwala jednej maszynie w lokalnej sieci za NAT uzyskać dostęp do innej maszyny w tej samej sieci pod zewnętrznym adresem routera.

Ostatecznie problem utrzymania sesji UDP rozwiązałem prosto — uruchomiłem klienta na tym samym komputerze co serwer.
Działało to w ten sposób:
- uruchamiałem klienta STUN z lokalnym portem 11111
- otrzymywałem odpowiedź z zewnętrznym adresem IP i portem XX.1XX.1X4.2XX:4398
- wysyłałem dane z zewnętrznym adresem IP i portem na e-mail (można użyć dowolnej innej usługi), ustawioną na smartfonie
- uruchamiałem serwer OpenVPN na komputerze nasłuchującego na porcie UDP/11111
- uruchamiałem klienta OpenVPN na komputerze, wskazując XX.1XX.1X4.2XX:4398 do połączenia
- o każdej porze uruchamiałem klienta OpenVPN na smartfonie, wskazując adres IP i port (w moim przypadku adres IP nie zmieniał się) do połączenia

W ten sposób uzyskałem możliwość łączenia się z moim komputerem ze smartfona. Ta realizacja pozwala na podłączenie dowolnego klienta OpenVPN.
Praktyka
Będziesz potrzebować:
# apt install openvpn stun-client sendemailNapisawszy kilka skryptów, parę plików konfiguracyjnych, generując niezbędne certyfikaty (ponieważ klient na smartfonie działa tylko na certyfikatach), otrzymałem standardową realizację serwera OpenVPN.
Główny skrypt na komputerze
# 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
doneSkrypt wysyłania danych na e-mail:
# 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"Plik konfiguracyjny serwera:
# cat server.confproto 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 20Plik konfiguracyjny klienta:
# cat client.confclient
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 30Generowanie certyfikatów było realizowane przez w tym artykule.
Uruchamianie skryptu:
# ./vpn11.shWcześniej nadając mu uprawnienia do uruchomienia
# chmod +x vpn11.shPo stronie smartfona
Instalując aplikację OpenVPN dla Androida, skopiowawszy plik konfiguracyjny, certyfikaty i konfigurując go, wyszło tak:
Na smartfonie sprawdzam pocztę
Koryguję numer portu w ustawieniach
Uruchamiam klienta i łączę się
W trakcie pisania artykułu przeniosłem konfigurację z komputera na Raspberry Pi 3 i próbowałem uruchomić to wszystko na modemie LTE, ale nie udało się! Wynik polecenia
# stun stun.ekiga.net -p 11111STUN client version 0.97
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Wartość zwrotna to 0x000006
wartość Filtr zależny od portu nie pozwolił na uruchomienie systemu.
Ale domowy dostawca bez problemu umożliwił uruchomienie systemu na Raspberry Pi 3.
W połączeniu z kamerą internetową, z VLC dla
tworzenia strumienia RTSP z kamery internetowej
$ 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-keepi VLC na smartfonie do oglądania (strumień rtsp://10.2.0.1:8554/), powstał niezły system monitoringu wideo na odległość, można również uruchomić Sambę, routować ruch przez VPN, zdalnie zarządzać komputerem i wiele więcej…
Wnioski
Jak pokazuje praktyka, do zorganizowania serwera VPN można obejść się bez zewnętrznego adresu IP, za który trzeba płacić, tak samo jak za wynajmowany VPS/VDS. Ale wszystko zależy od dostawcy. Oczywiście chciałbym uzyskać więcej informacji o różnych dostawcach i typach używanych NAT'ów, ale to dopiero początek…
Dziękuję za uwagę!
Źródło: habr.com
