在提供商的 NAT 后面运行 VPN 服务器

一篇关于我如何设法在我的家庭提供商的 NAT 后面运行 VPN 服务器(没有白色 IP 地址)的文章。 让我马上预订:那个 此实现的性能直接取决于提供商使用的 NAT 类型以及路由器.
因此,我需要从我的 Android 智能手机连接到我的家用计算机,这两个设备都通过提供商 NAT 连接到互联网,并且计算机通过家庭路由器连接,这也是 NAT 连接。
由于多种原因,未考虑使用具有白色 IP 地址的租赁 VPS/VDS 以及从提供商处租用白色 IP 地址的经典方案。
考虑中 过去文章的经验,对提供商的 STUN 和 NAT 进行了多次实验。 我决定做一个小实验,在运行 OpenWRT 固件的家庭路由器上运行以下命令:

$ stun stun.sipnet.ru

得到结果:

STUN客户端版本0.97
主要:独立映射、独立过滤、随机端口、发夹
返回值为 0x000002

直译:
Independent Mapping——独立映射
独立过滤器-独立过滤器
随机端口-随机端口
会发夹-会有一个发夹
在我的电脑上运行类似的命令,我得到:

STUN客户端版本0.97
主要:独立映射、端口相关过滤器、随机端口、发夹
返回值为 0x000006

Port Dependent Filter - 端口相关过滤器
命令输出结果的差异表明家庭路由器正在为互联网传输数据包的过程做出“贡献”;这体现在当在计算机上执行命令时:

stun stun.sipnet.ru -p 11111 -v

我得到的结果是:

...
映射地址 = XX.1XX.1X4.2XX:4398
...

此时,一个UDP会话已打开一段时间,如果此时您发送一个UDP请求(例如:netcat XX.1XX.1X4.2XX 4398 -u),则该请求来到了家庭路由器,即由其上运行的 TCPDump 确认,但请求未到达计算机 - IPtables 作为路由器上的 NAT 转换器将其丢弃。
在提供商的 NAT 后面运行 VPN 服务器
但 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 地址接收来自 Internet 的请求。 此时,我启动了OpenVPN服务器(之前已配置)监听UDP/11111端口,在智能手机上指示外部IP地址和端口(XX.1XX.1X4.2XX:4398)并成功从智能手机连接到电脑。 但在这个实现中出现了一个问题:有必要以某种方式维持 UDP 会话,直到 OpenVPN 客户端连接到服务器;我不喜欢定期启动 STUN 客户端的选项 - 我不想浪费负载STUN 服务器。
我还注意到条目“会发夹-会有一个发夹”,这个模式

Hairpinning 允许 NAT 后面的本地网络上的一台计算机通过路由器的外部地址访问同一网络上的另一台计算机。

在提供商的 NAT 后面运行 VPN 服务器
结果,我简单地解决了维护 UDP 会话的问题 - 我在与服务器相同的计算机上启动了客户端。
它的工作原理是这样的:

  • 在本地端口 11111 上启动 STUN 客户端
  • 收到具有外部 IP 地址和端口 XX.1XX.1X4.2XX:4398 的响应
  • 使用外部 IP 地址和端口将数据发送到智能手机上配置的电子邮件(可以使用任何其他服务)
  • 在侦听 UDP/11111 端口的计算机上启动 OpenVPN 服务器
  • 在指定 XX.1XX.1X4.2XX:4398 的计算机上启动 OpenVPN 客户端进行连接
  • 随时在智能手机上启动 OpenVPN 客户端,指示 IP 地址和端口(在我的情况下,IP 地址没有更改)以进行连接

在提供商的 NAT 后面运行 VPN 服务器
这样我就可以从智能手机连接到我的计算机。 此实施允许您连接任何 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

在智能手机方面

通过安装应用程序 适用于 Android 的 OpenVPN,复制了配置文件、证书并进行了配置,结果是这样的:
我在智能手机上查看电子邮件在提供商的 NAT 后面运行 VPN 服务器
我在设置中编辑端口号在提供商的 NAT 后面运行 VPN 服务器
我启动客户端并连接在提供商的 NAT 后面运行 VPN 服务器

在撰写本文时,我将配置从计算机转移到 Raspberry Pi 3,并尝试在 LTE 调制解调器上运行整个系统,但没有成功! 命令结果

# stun stun.ekiga.net -p 11111

STUN客户端版本0.97
主要:独立映射、端口相关过滤器、随机端口、发夹
返回值为 0x000006

端口相关过滤器 不允许系统启动。
但家庭提供商允许系统在 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

添加评论