VPN over SSH
有几种方法可以通过 SSH 设置虚拟专用网络。请注意,虽然这可能偶尔有用,但它可能无法完全替代常规 VPN。例如,请参阅 [1]。
使用 badvpn 的 tun2socks
badvpn 是用于各种 VPN 相关用例的实用程序集合。
启动 SSH 动态 SOCKS 代理
首先,我们将像往常一样设置一个普通的 SSH 动态 socks 代理
$ ssh -TND 4711 <your_user>@<SSH_server>
设置 badvpn 和隧道接口
之后,我们可以继续设置 TUN。
# ip tuntap add dev tun0 mode tun user <your_local_user> # ip addr replace 10.0.0.1/24 dev tun0 # badvpn-tun2socks --tundev tun0 --netif-ipaddr 10.0.0.2 --netif-netmask 255.255.255.0 --socks-server-addr localhost:4711
现在您有了一个可工作的本地 tun0
接口,它将所有进入它的流量通过您之前设置的 SOCKS 代理路由。
将流量导入隧道
现在剩下要做的就是设置一个本地路由,将一些流量导入其中。让我们设置一个路由,将所有流量都路由到其中。我们将需要三个路由
- 指向我们用于隧道的 SSH 服务器的路由,具有较低的跃点数。
- DNS 服务器的路由(因为 tun2socks 不支持 DNS 所必需的 UDP),具有较低的跃点数。
- 所有其他流量的默认路由,其跃点数高于其他路由。
专门设置跃点数的想法是因为我们需要确保选择到 SSH 服务器的路由始终是直接的,否则它会返回到 SSH 隧道中,这将导致循环,我们将因此失去 SSH 连接。除此之外,我们需要设置显式的 DNS 路由,因为 tun2socks 不隧道传输 UDP(DNS 需要)。我们还需要一个新的默认路由,其跃点数低于您旧的默认路由,以便流量能够进入隧道。 说了这么多,让我们开始工作
# ip route add <IP_of_SSH_server> via <IP_of_original_gateway> metric 5 # ip route add <IP_of_DNS_server> via <IP_of_original_gateway> metric 5 # ip route add default via 10.0.0.2 metric 6
现在所有流量(DNS 和 SSH 服务器本身除外)都应该通过 tun0
。
OpenSSH 的内置隧道
OpenSSH 使用 -w<本地-tun-编号>:<远程-tun-编号>
内置了 TUN/TAP 支持。这里描述了一个第 3 层/点对点/TUN 隧道。也可以创建第 2 层/以太网/TAP 隧道。
为 TUN 设备启用转发
要为 TUN 设备启用转发,请编辑 /etc/ssh/sshd_config
并将 PermitTunnel
设置为 yes
、point-to-point
或 ethernet
。 设置为 yes
将同时为 point-to-point
和 ethernet
隧道启用转发。 有关详细信息,请参阅 sshd_config(5)。
/etc/ssh/sshd_config
... PermitTunnel yes ...
然后重新加载 sshd.service
。
使用 systemd-networkd 创建 tun 接口
/etc/systemd/network/vpn.netdev
[NetDev] Name=tun5 Kind=tun [Tun] User=vpn Group=network
/etc/systemd/network/vpn.network
[Match] Name=tun5 [Address] Address=192.168.200.2/24
创建这些文件后,通过重启 systemd-networkd.service
来启用它们。
此外,您可以使用 ip tunnel
命令管理 tun 接口。
在 SSH 命令中创建接口
SSH 会自动创建两个接口,但 IP 和路由应在连接建立后配置。
ssh \ -o PermitLocalCommand=yes \ -o LocalCommand="sudo ifconfig tun5 192.168.244.2 pointopoint 192.168.244.1 netmask 255.255.255.0" \ -o ServerAliveInterval=60 \ -w 5:5 vpn@example.com \ 'sudo ifconfig tun5 192.168.244.1 pointopoint 192.168.244.2 netmask 255.255.255.0; echo tun0 ready'
启动 SSH
ssh -f -w5:5 vpn@example.com -i ~/.ssh/key "sleep 1000000000"
或者,如果您位于 NAT 之后,您可以添加 keep-alive 选项。
ssh -f -w5:5 vpn@example.com \ -o ServerAliveInterval=30 \ -o ServerAliveCountMax=5 \ -o TCPKeepAlive=yes \ -i ~/.ssh/key "sleep 1000000000"
故障排除
- ssh 应该具有 tun 接口的访问权限或创建它的权限。检查 tun 接口和/或 /dev/net/tun 的所有者。
- 显然,如果您想访问网络而不是单台机器,您应该正确设置 IP 数据包转发、路由,并且可能在双方都设置网络过滤器。
- 如果您不启用隧道,当您想使用
-w
创建 SSH 隧道时,可能会收到以下错误
channel 0: open failed: connect failed: open failed Tunnel forwarding failed
使用 PPP over SSH
pppd 可以轻松地用于通过 SSH 服务器创建隧道
# pppd updetach noauth silent nodeflate pty "/usr/bin/ssh root@remote-gw /usr/sbin/pppd nodetach notty noauth" ipparam vpn 10.0.8.1:10.0.8.2
建立 VPN 连接后,您可以通过它路由流量。要访问内部网络
# ip route add 192.168.0.0/16 via 10.0.8.2
要通过隧道路由所有 Internet 流量,例如,为了保护您在未加密网络上的通信,首先通过您的常规网关添加一个到 SSH 服务器的路由
# ip route add <remote-gw> via <current default gateway>
接下来,用隧道替换默认路由
# ip route replace default via 10.0.8.2
辅助脚本
pvpn(软件包 pvpnAUR) 是 pppd
over SSH 的包装脚本。