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 不处理 UDP,而 UDP 是 DNS 所必需的),具有较低的度量值。
- 所有其他流量的默认路由,其度量值高于其他路由。
设置特定度量值的想法是因为我们需要确保始终直接选择到 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<local-tun-number>:<remote-tun-number> 内建支持 TUN/TAP。这里描述的是一个三层/点对点/TUN 隧道。也可以创建二层/以太网/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 后面,可以添加保持连接的选项。
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 包转发、路由以及可能在两端的 netfilter。
- 如果你不启用隧道功能,当你想使用
-w创建 SSH 隧道时,可能会遇到以下错误。
channel 0: open failed: connect failed: open failed Tunnel forwarding failed
通过 SSH 使用 PPP
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) 是一个围绕 SSH 上的 pppd 的包装脚本。