跳转至内容

VPN over SSH

来自 ArchWiki

有几种方法可以通过 SSH 设置虚拟专用网络。请注意,虽然这有时可能很有用,但它可能无法完全替代常规 VPN。例如,请参阅 [1]

使用 badvpn 的 tun2socks

注意 badvpn 项目已于 2022 年 8 月停止维护,最新稳定版本是 2015 年 4 月发布的。有一个 Go 重写版本,网址为 https://github.com/xjasonlyu/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 代理进行路由。

将流量导入隧道

现在剩下的就是设置一个本地路由,以便将一些流量导入其中。我们来设置三个路由。

  1. 指向用于隧道的 SSH 服务器的路由,具有较低的度量值。
  2. DNS 服务器的路由(因为 tun2socks 不处理 UDP,而 UDP 是 DNS 所必需的),具有较低的度量值。
  3. 所有其他流量的默认路由,其度量值高于其他路由。

设置特定度量值的想法是因为我们需要确保始终直接选择到 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 设置为 yespoint-to-pointethernet。设置为 yes 会为 point-to-pointethernet 隧道启用转发。有关详细信息,请参阅 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 的包装脚本。

参见

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.